diff --git a/.gas-snapshot b/.gas-snapshot index 78dea1dae..23980f0ec 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,588 +1,589 @@ -Burn_LockupDynamic_Integration_Concrete_Test:test_Burn_CallerApprovedOperator() (gas: 89934) -Burn_LockupDynamic_Integration_Concrete_Test:test_Burn_CallerNFTOwner() (gas: 80731) -Burn_LockupDynamic_Integration_Concrete_Test:test_Burn_NonTransferableNFT() (gas: 80762) -Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 81871) -Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11317) -Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 90162) -Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusPending() (gas: 14278) -Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 19536) -Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusStreaming() (gas: 19551) -Burn_LockupLinear_Integration_Concrete_Test:test_Burn_CallerApprovedOperator() (gas: 92131) -Burn_LockupLinear_Integration_Concrete_Test:test_Burn_CallerNFTOwner() (gas: 82942) -Burn_LockupLinear_Integration_Concrete_Test:test_Burn_NonTransferableNFT() (gas: 82973) -Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 84085) +Burn_LockupDynamic_Integration_Concrete_Test:test_Burn_CallerApprovedOperator() (gas: 89728) +Burn_LockupDynamic_Integration_Concrete_Test:test_Burn_CallerNFTOwner() (gas: 80566) +Burn_LockupDynamic_Integration_Concrete_Test:test_Burn_NonTransferableNFT() (gas: 80555) +Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 81703) +Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11307) +Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 90105) +Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusPending() (gas: 14290) +Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 19526) +Burn_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusStreaming() (gas: 19475) +Burn_LockupLinear_Integration_Concrete_Test:test_Burn_CallerApprovedOperator() (gas: 91971) +Burn_LockupLinear_Integration_Concrete_Test:test_Burn_CallerNFTOwner() (gas: 82804) +Burn_LockupLinear_Integration_Concrete_Test:test_Burn_NonTransferableNFT() (gas: 82793) +Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 83947) Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11293) Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 82872) -Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusPending() (gas: 14254) +Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusPending() (gas: 14276) Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 19512) -Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusStreaming() (gas: 19527) -Burn_LockupTranched_Integration_Concrete_Test:test_Burn_CallerApprovedOperator() (gas: 100990) -Burn_LockupTranched_Integration_Concrete_Test:test_Burn_CallerNFTOwner() (gas: 91801) -Burn_LockupTranched_Integration_Concrete_Test:test_Burn_NonTransferableNFT() (gas: 91832) -Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 92960) +Burn_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusStreaming() (gas: 19461) +Burn_LockupTranched_Integration_Concrete_Test:test_Burn_CallerApprovedOperator() (gas: 100802) +Burn_LockupTranched_Integration_Concrete_Test:test_Burn_CallerNFTOwner() (gas: 91635) +Burn_LockupTranched_Integration_Concrete_Test:test_Burn_NonTransferableNFT() (gas: 91624) +Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 92794) Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11337) -Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 89982) -Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusPending() (gas: 14298) +Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 90032) +Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusPending() (gas: 14320) Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 19556) -Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusStreaming() (gas: 19571) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_CancelMultiple() (gas: 815232) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_CancelMultiple_ArrayCountZero() (gas: 6329) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_AllStreamsCold() (gas: 32142) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_AllStreamsNotCancelable() (gas: 835114) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 12417) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 78395) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeStreamsCold() (gas: 326410) -CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeStreamsNotCancelable() (gas: 918387) -CancelMultiple_LockupDynamic_Integration_Fuzz_Test:testFuzz_CancelMultiple(uint256,uint40) (runs: 5, μ: 1175383, ~: 1174865) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_CancelMultiple() (gas: 595097) +Burn_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusStreaming() (gas: 19505) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_CancelMultiple() (gas: 825543) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_CancelMultiple_ArrayCountZero() (gas: 6315) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_AllStreamsCold() (gas: 32135) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_AllStreamsNotCancelable() (gas: 834301) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 12422) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 78418) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeStreamsCold() (gas: 326169) +CancelMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeStreamsNotCancelable() (gas: 917699) +CancelMultiple_LockupDynamic_Integration_Fuzz_Test:testFuzz_CancelMultiple(uint256,uint40) (runs: 50, μ: 1182497, ~: 1186661) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_CancelMultiple() (gas: 605488) CancelMultiple_LockupLinear_Integration_Concrete_Test:test_CancelMultiple_ArrayCountZero() (gas: 6332) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_AllStreamsCold() (gas: 34306) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_AllStreamsNotCancelable() (gas: 636392) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 12414) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 80403) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeStreamsCold() (gas: 254607) -CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeStreamsNotCancelable() (gas: 719687) -CancelMultiple_LockupLinear_Integration_Fuzz_Test:testFuzz_CancelMultiple(uint256,uint40) (runs: 5, μ: 861197, ~: 863450) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_CancelMultiple() (gas: 770735) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_AllStreamsCold() (gas: 34328) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_AllStreamsNotCancelable() (gas: 635517) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 12436) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 80425) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeStreamsCold() (gas: 254338) +CancelMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeStreamsNotCancelable() (gas: 718901) +CancelMultiple_LockupLinear_Integration_Fuzz_Test:testFuzz_CancelMultiple(uint256,uint40) (runs: 50, μ: 871389, ~: 873499) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_CancelMultiple() (gas: 781606) CancelMultiple_LockupTranched_Integration_Concrete_Test:test_CancelMultiple_ArrayCountZero() (gas: 6354) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_AllStreamsCold() (gas: 41696) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_AllStreamsNotCancelable() (gas: 934828) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 12436) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 87796) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeStreamsCold() (gas: 343455) -CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeStreamsNotCancelable() (gas: 1028867) -CancelMultiple_LockupTranched_Integration_Fuzz_Test:testFuzz_CancelMultiple(uint256,uint40) (runs: 5, μ: 1175542, ~: 1173622) -Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel() (gas: 371699) -Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientDoesNotImplementHook() (gas: 356833) -Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientNotContract() (gas: 97011) -Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientReentrancy() (gas: 358721) -Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientReverts() (gas: 357400) -Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_StatusPending() (gas: 71443) -Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11314) -Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 86956) -Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 63201) -Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 26741) -Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 246730) -Cancel_LockupDynamic_Integration_Fuzz_Test:testFuzz_Cancel(uint256,uint128) (runs: 5, μ: 440408, ~: 440715) -Cancel_LockupDynamic_Integration_Fuzz_Test:testFuzz_Cancel_StatusPending(uint256) (runs: 5, μ: 71792, ~: 71598) -Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel() (gas: 276919) -Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientDoesNotImplementHook() (gas: 262068) -Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientNotContract() (gas: 79360) -Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientReentrancy() (gas: 263946) -Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientReverts() (gas: 262635) -Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_StatusPending() (gas: 73435) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_AllStreamsCold() (gas: 41710) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_AllStreamsNotCancelable() (gas: 934117) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 12458) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 87800) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeStreamsCold() (gas: 343272) +CancelMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeStreamsNotCancelable() (gas: 1028209) +CancelMultiple_LockupTranched_Integration_Fuzz_Test:testFuzz_CancelMultiple(uint256,uint40) (runs: 50, μ: 1187346, ~: 1189529) +Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel() (gas: 374152) +Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientDoesNotImplementHook() (gas: 357307) +Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientNotContract() (gas: 97679) +Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientReentrancy() (gas: 359190) +Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_RecipientReverts() (gas: 357874) +Cancel_LockupDynamic_Integration_Concrete_Test:test_Cancel_StatusPending() (gas: 72695) +Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11309) +Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 86904) +Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 63165) +Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 26736) +Cancel_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 246553) +Cancel_LockupDynamic_Integration_Fuzz_Test:testFuzz_Cancel(uint256,uint128) (runs: 50, μ: 441056, ~: 442191) +Cancel_LockupDynamic_Integration_Fuzz_Test:testFuzz_Cancel_StatusPending(uint256) (runs: 50, μ: 73280, ~: 73354) +Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel() (gas: 279422) +Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientDoesNotImplementHook() (gas: 262552) +Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientNotContract() (gas: 80064) +Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientReentrancy() (gas: 264430) +Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_RecipientReverts() (gas: 263119) +Cancel_LockupLinear_Integration_Concrete_Test:test_Cancel_StatusPending() (gas: 74751) Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11298) Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 79680) -Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 65441) +Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 65418) Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 28901) -Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 192902) -Cancel_LockupLinear_Integration_Fuzz_Test:testFuzz_Cancel(uint256,uint128) (runs: 5, μ: 317991, ~: 318255) -Cancel_LockupLinear_Integration_Fuzz_Test:testFuzz_Cancel_StatusPending(uint256) (runs: 5, μ: 73922, ~: 73871) -Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel() (gas: 360534) -Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientDoesNotImplementHook() (gas: 345630) -Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientNotContract() (gas: 86746) -Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientReentrancy() (gas: 347552) -Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientReverts() (gas: 346197) -Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_StatusPending() (gas: 80881) +Cancel_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 192700) +Cancel_LockupLinear_Integration_Fuzz_Test:testFuzz_Cancel(uint256,uint128) (runs: 50, μ: 318219, ~: 319610) +Cancel_LockupLinear_Integration_Fuzz_Test:testFuzz_Cancel_StatusPending(uint256) (runs: 50, μ: 75350, ~: 75556) +Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel() (gas: 363234) +Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientDoesNotImplementHook() (gas: 346311) +Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientNotContract() (gas: 87493) +Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientReentrancy() (gas: 348233) +Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_RecipientReverts() (gas: 346878) +Cancel_LockupTranched_Integration_Concrete_Test:test_Cancel_StatusPending() (gas: 82179) Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11342) -Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 86790) -Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 74272) -Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 36313) -Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 273818) -Cancel_LockupTranched_Integration_Fuzz_Test:testFuzz_Cancel(uint256,uint128) (runs: 5, μ: 404148, ~: 404572) -Cancel_LockupTranched_Integration_Fuzz_Test:testFuzz_Cancel_StatusPending(uint256) (runs: 5, μ: 81368, ~: 81317) -Constructor_LockupDynamic_Integration_Concrete_Test:test_Constructor() (gas: 5026066) -Constructor_LockupLinear_Integration_Concrete_Test:test_Constructor() (gas: 3890433) -Constructor_LockupTranched_Integration_Concrete_Test:test_Constructor() (gas: 4081319) -CreateWithDurations_LockupDynamic_Integration_Concrete_Test:test_CreateWithDurations() (gas: 345377) -CreateWithDurations_LockupDynamic_Integration_Fuzz_Test:testFuzz_CreateWithDurations((uint128,uint64,uint40)[]) (runs: 5, μ: 5491601, ~: 7294034) -CreateWithDurations_LockupLinear_Integration_Concrete_Test:test_CreateWithDurations() (gas: 273812) -CreateWithDurations_LockupLinear_Integration_Fuzz_Test:testFuzz_CreateWithDurations((uint40,uint40)) (runs: 5, μ: 272460, ~: 272184) -CreateWithDurations_LockupTranched_Integration_Concrete_Test:test_CreateWithDurations() (gas: 375613) -CreateWithDurations_LockupTranched_Integration_Fuzz_Test:testFuzz_CreateWithDurations((uint128,uint40)[]) (runs: 5, μ: 5587007, ~: 6183306) -CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test:test_CreateWithTimestamps() (gas: 338393) -CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test:test_CreateWithTimestamps_AssetMissingReturnValue() (gas: 344814) -CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_EndTimeNotInTheFuture() (gas: 38819) -CreateWithTimestamps_LockupDynamic_Integration_Fuzz_Test:testFuzz_CreateWithTimestamps(address,(address,address,uint128,address,bool,bool,uint40,(uint128,uint64,uint40)[],(address,uint256))) (runs: 5, μ: 3746257, ~: 3891426) -CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_CreateWithTimestamps() (gas: 272572) -CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_CreateWithTimestamps_AssetMissingReturnValue() (gas: 279015) -CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_CreateWithTimestamps_CliffTimeZero() (gas: 228453) -CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_RevertGiven_EndTimeNotInTheFuture() (gas: 33005) -CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test:testFuzz_CreateWithTimestamps(address,(address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256))) (runs: 5, μ: 358201, ~: 362647) -CreateWithTimestamps_LockupTranched_Integration_Concrete_Test:test_CreateWithTimestamps() (gas: 365732) -CreateWithTimestamps_LockupTranched_Integration_Concrete_Test:test_CreateWithTimestamps_AssetMissingReturnValue() (gas: 372087) -CreateWithTimestamps_LockupTranched_Integration_Concrete_Test:test_RevertGiven_EndTimeNotInTheFuture() (gas: 41674) -CreateWithTimestamps_LockupTranched_Integration_Fuzz_Test:testFuzz_CreateWithTimestamps(address,(address,address,uint128,address,bool,bool,uint40,(uint128,uint40)[],(address,uint256))) (runs: 5, μ: 3607120, ~: 3725226) -GenerateAccentColor_Integration_Concrete_Test:test_GenerateAccentColor() (gas: 13242) -GetAsset_LockupDynamic_Integration_Concrete_Test:test_GetAsset() (gas: 276169) -GetAsset_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11991) -GetAsset_LockupLinear_Integration_Concrete_Test:test_GetAsset() (gas: 224871) -GetAsset_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11969) -GetAsset_LockupTranched_Integration_Concrete_Test:test_GetAsset() (gas: 301708) -GetAsset_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11991) -GetCliffTime_LockupLinear_Integration_Concrete_Test:test_GetCliffTime() (gas: 225459) -GetCliffTime_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11436) -GetDepositedAmount_LockupDynamic_Integration_Concrete_Test:test_GetDepositedAmount() (gas: 279054) -GetDepositedAmount_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11668) -GetDepositedAmount_LockupLinear_Integration_Concrete_Test:test_GetDepositedAmount() (gas: 227708) -GetDepositedAmount_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11634) -GetDepositedAmount_LockupTranched_Integration_Concrete_Test:test_GetDepositedAmount() (gas: 304615) -GetDepositedAmount_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11690) -GetEndTime_LockupDynamic_Integration_Concrete_Test:test_GetEndTime() (gas: 278874) -GetEndTime_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11568) -GetEndTime_LockupLinear_Integration_Concrete_Test:test_GetEndTime() (gas: 227598) -GetEndTime_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11568) -GetEndTime_LockupTranched_Integration_Concrete_Test:test_GetEndTime() (gas: 304457) -GetEndTime_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11612) -GetRange_LockupDynamic_Integration_Concrete_Test:test_GetRange() (gas: 278255) -GetRange_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13067) -GetRange_LockupLinear_Integration_Concrete_Test:test_GetRange() (gas: 227888) -GetRange_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13251) -GetRange_LockupTranched_Integration_Concrete_Test:test_GetRange() (gas: 303751) -GetRange_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13067) -GetRecipient_LockupDynamic_Integration_Concrete_Test:test_GetRecipient() (gas: 12464) -GetRecipient_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 67739) -GetRecipient_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11456) -GetRecipient_LockupLinear_Integration_Concrete_Test:test_GetRecipient() (gas: 12436) -GetRecipient_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 69950) -GetRecipient_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11428) -GetRecipient_LockupTranched_Integration_Concrete_Test:test_GetRecipient() (gas: 12464) -GetRecipient_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 78809) -GetRecipient_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11456) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusDepleted() (gas: 311270) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusPending() (gas: 301075) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusSettled() (gas: 306305) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusStreaming() (gas: 306298) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusCanceled() (gas: 345790) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusDepleted() (gas: 347632) -GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11954) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusDepleted() (gas: 258243) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusPending() (gas: 247789) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusSettled() (gas: 253019) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusStreaming() (gas: 253012) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusCanceled() (gas: 289238) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusDepleted() (gas: 290999) -GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11932) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusDepleted() (gas: 339855) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusPending() (gas: 326614) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusSettled() (gas: 331844) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusStreaming() (gas: 331837) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusCanceled() (gas: 369129) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusDepleted() (gas: 370938) -GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11954) -GetSegments_LockupDynamic_Integration_Concrete_Test:test_GetSegments() (gas: 283695) -GetSegments_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13744) -GetSender_LockupDynamic_Integration_Concrete_Test:test_GetSender() (gas: 275931) -GetSender_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11800) -GetSender_LockupLinear_Integration_Concrete_Test:test_GetSender() (gas: 224627) -GetSender_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11772) -GetSender_LockupTranched_Integration_Concrete_Test:test_GetSender() (gas: 301470) -GetSender_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11800) -GetStartTime_LockupDynamic_Integration_Concrete_Test:test_GetStartTime() (gas: 279116) -GetStartTime_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11787) -GetStartTime_LockupLinear_Integration_Concrete_Test:test_GetStartTime() (gas: 227818) -GetStartTime_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11765) -GetStartTime_LockupTranched_Integration_Concrete_Test:test_GetStartTime() (gas: 304655) -GetStartTime_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11787) -GetStream_LockupDynamic_Integration_Concrete_Test:test_GetStream() (gas: 264782) -GetStream_LockupDynamic_Integration_Concrete_Test:test_GetStream_StatusSettled() (gas: 52545) -GetStream_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 15581) -GetStream_LockupLinear_Integration_Concrete_Test:test_GetStream() (gas: 37598) -GetStream_LockupLinear_Integration_Concrete_Test:test_GetStream_StatusSettled() (gas: 42180) -GetStream_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14337) -GetStream_LockupTranched_Integration_Concrete_Test:test_GetStream() (gas: 291442) -GetStream_LockupTranched_Integration_Concrete_Test:test_GetStream_StatusSettled() (gas: 57205) -GetStream_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 15565) -GetTranches_LockupTranched_Integration_Concrete_Test:test_GetTranches() (gas: 310185) -GetTranches_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13497) -GetWithdrawnAmount_LockupDynamic_Integration_Concrete_Test:test_GetWithdrawnAmount() (gas: 355530) -GetWithdrawnAmount_LockupDynamic_Integration_Concrete_Test:test_GetWithdrawnAmount_NoPreviousWithdrawals() (gas: 304291) -GetWithdrawnAmount_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11954) -GetWithdrawnAmount_LockupDynamic_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount(uint256,uint128) (runs: 5, μ: 358827, ~: 359251) -GetWithdrawnAmount_LockupDynamic_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount_NoPreviousWithdrawals(uint256) (runs: 5, μ: 305919, ~: 305643) -GetWithdrawnAmount_LockupLinear_Integration_Concrete_Test:test_GetWithdrawnAmount() (gas: 274898) -GetWithdrawnAmount_LockupLinear_Integration_Concrete_Test:test_GetWithdrawnAmount_NoPreviousWithdrawals() (gas: 253005) -GetWithdrawnAmount_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11932) -GetWithdrawnAmount_LockupLinear_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount(uint256,uint128) (runs: 5, μ: 278393, ~: 278657) -GetWithdrawnAmount_LockupLinear_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount_NoPreviousWithdrawals(uint256) (runs: 5, μ: 254633, ~: 254357) -GetWithdrawnAmount_LockupTranched_Integration_Concrete_Test:test_GetWithdrawnAmount() (gas: 356428) -GetWithdrawnAmount_LockupTranched_Integration_Concrete_Test:test_GetWithdrawnAmount_NoPreviousWithdrawals() (gas: 329830) -GetWithdrawnAmount_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11954) -GetWithdrawnAmount_LockupTranched_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount(uint256,uint128) (runs: 5, μ: 359942, ~: 360187) -GetWithdrawnAmount_LockupTranched_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount_NoPreviousWithdrawals(uint256) (runs: 5, μ: 331320, ~: 331182) -IsCancelable_LockupDynamic_Integration_Concrete_Test:test_IsCancelable() (gas: 481194) -IsCancelable_LockupDynamic_Integration_Concrete_Test:test_IsCancelable_Cold() (gas: 304629) -IsCancelable_LockupDynamic_Integration_Concrete_Test:test_IsCancelable_StreamCancelable() (gas: 295851) -IsCancelable_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11269) -IsCancelable_LockupLinear_Integration_Concrete_Test:test_IsCancelable() (gas: 382141) -IsCancelable_LockupLinear_Integration_Concrete_Test:test_IsCancelable_Cold() (gas: 253537) -IsCancelable_LockupLinear_Integration_Concrete_Test:test_IsCancelable_StreamCancelable() (gas: 244594) -IsCancelable_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11285) -IsCancelable_LockupTranched_Integration_Concrete_Test:test_IsCancelable() (gas: 530457) -IsCancelable_LockupTranched_Integration_Concrete_Test:test_IsCancelable_Cold() (gas: 331729) -IsCancelable_LockupTranched_Integration_Concrete_Test:test_IsCancelable_StreamCancelable() (gas: 321418) -IsCancelable_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11294) -IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusCanceled() (gas: 344613) -IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusDepleted() (gas: 311043) -IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusPending() (gas: 299108) -IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusSettled() (gas: 304895) -IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusStreaming() (gas: 321223) -IsCold_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11552) -IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusCanceled() (gas: 288108) -IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusDepleted() (gas: 258068) -IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusPending() (gas: 247874) -IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusSettled() (gas: 253826) -IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusStreaming() (gas: 254340) -IsCold_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11590) -IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusCanceled() (gas: 367998) -IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusDepleted() (gas: 339679) -IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusPending() (gas: 324698) -IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusSettled() (gas: 332018) -IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusStreaming() (gas: 332495) -IsCold_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11599) -IsDepleted_LockupDynamic_Integration_Concrete_Test:test_IsDepleted() (gas: 310426) -IsDepleted_LockupDynamic_Integration_Concrete_Test:test_IsDepleted_StreamNotDepleted() (gas: 295220) -IsDepleted_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11181) -IsDepleted_LockupLinear_Integration_Concrete_Test:test_IsDepleted() (gas: 257422) -IsDepleted_LockupLinear_Integration_Concrete_Test:test_IsDepleted_StreamNotDepleted() (gas: 243957) -IsDepleted_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11194) -IsDepleted_LockupTranched_Integration_Concrete_Test:test_IsDepleted() (gas: 339033) -IsDepleted_LockupTranched_Integration_Concrete_Test:test_IsDepleted_StreamNotDepleted() (gas: 320781) -IsDepleted_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11203) -IsStream_LockupDynamic_Integration_Concrete_Test:test_IsStream() (gas: 295557) -IsStream_LockupDynamic_Integration_Concrete_Test:test_IsStream_Null() (gas: 8510) -IsStream_LockupLinear_Integration_Concrete_Test:test_IsStream() (gas: 244299) -IsStream_LockupLinear_Integration_Concrete_Test:test_IsStream_Null() (gas: 8526) -IsStream_LockupTranched_Integration_Concrete_Test:test_IsStream() (gas: 321101) -IsStream_LockupTranched_Integration_Concrete_Test:test_IsStream_Null() (gas: 8513) -IsTransferable_LockupDynamic_Integration_Concrete_Test:test_IsTransferable_Stream() (gas: 295700) -IsTransferable_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11642) -IsTransferable_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamTransferNotEnabled() (gas: 481113) -IsTransferable_LockupLinear_Integration_Concrete_Test:test_IsTransferable_Stream() (gas: 244459) -IsTransferable_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11677) -IsTransferable_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamTransferNotEnabled() (gas: 382091) -IsTransferable_LockupTranched_Integration_Concrete_Test:test_IsTransferable_Stream() (gas: 321261) -IsTransferable_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11664) -IsTransferable_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamTransferNotEnabled() (gas: 530370) -IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusCanceled() (gas: 344120) -IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusDepleted() (gas: 310524) -IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusPending() (gas: 298512) -IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusSettled() (gas: 304478) -IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusStreaming() (gas: 320675) -IsWarm_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11090) -IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusCanceled() (gas: 287615) -IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusDepleted() (gas: 257544) -IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusPending() (gas: 247273) -IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusSettled() (gas: 253409) -IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusStreaming() (gas: 253787) -IsWarm_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11128) -IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusCanceled() (gas: 367461) -IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusDepleted() (gas: 339111) -IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusPending() (gas: 324053) -IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusSettled() (gas: 331557) -IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusStreaming() (gas: 331898) -IsWarm_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11093) -MapSymbol_Integration_Concrete_Test:test_MapSymbol_LockupDynamic() (gas: 17279) -MapSymbol_Integration_Concrete_Test:test_MapSymbol_LockupLinear() (gas: 16907) -MapSymbol_Integration_Concrete_Test:test_RevertGiven_UnknownNFT() (gas: 911419) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusDepleted() (gas: 310510) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusPending() (gas: 304381) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusSettled() (gas: 304352) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusStreaming() (gas: 311251) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 344054) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 347259) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StreamNotCancelable() (gas: 488812) -RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11129) -RefundableAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_RefundableAmountOf(uint256) (runs: 5, μ: 44041, ~: 30163) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusDepleted() (gas: 257501) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusPending() (gas: 253088) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusSettled() (gas: 253253) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusStreaming() (gas: 254718) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 287520) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 290644) -RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StreamNotCancelable() (gas: 389772) +Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 86840) +Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 74221) +Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 36305) +Cancel_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 273654) +Cancel_LockupTranched_Integration_Fuzz_Test:testFuzz_Cancel(uint256,uint128) (runs: 50, μ: 405987, ~: 406220) +Cancel_LockupTranched_Integration_Fuzz_Test:testFuzz_Cancel_StatusPending(uint256) (runs: 50, μ: 82750, ~: 82693) +Constructor_LockupDynamic_Integration_Concrete_Test:test_Constructor() (gas: 5056466) +Constructor_LockupLinear_Integration_Concrete_Test:test_Constructor() (gas: 3903481) +Constructor_LockupTranched_Integration_Concrete_Test:test_Constructor() (gas: 4104734) +CreateWithDurations_LockupDynamic_Integration_Concrete_Test:test_CreateWithDurations() (gas: 356999) +CreateWithDurations_LockupDynamic_Integration_Fuzz_Test:testFuzz_CreateWithDurations((uint128,uint64,uint40)[]) (runs: 50, μ: 4078448, ~: 3524013) +CreateWithDurations_LockupLinear_Integration_Concrete_Test:test_CreateWithDurations() (gas: 286244) +CreateWithDurations_LockupLinear_Integration_Fuzz_Test:testFuzz_CreateWithDurations((uint40,uint40)) (runs: 50, μ: 281828, ~: 284643) +CreateWithDurations_LockupTranched_Integration_Concrete_Test:test_CreateWithDurations() (gas: 387388) +CreateWithDurations_LockupTranched_Integration_Fuzz_Test:testFuzz_CreateWithDurations((uint128,uint40)[]) (runs: 50, μ: 4592175, ~: 4807073) +CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test:test_CreateWithTimestamps() (gas: 350001) +CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test:test_CreateWithTimestamps_AssetMissingReturnValue() (gas: 356422) +CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_EndTimeNotInTheFuture() (gas: 38801) +CreateWithTimestamps_LockupDynamic_Integration_Fuzz_Test:testFuzz_CreateWithTimestamps(address,(address,address,uint128,address,bool,bool,uint40,(uint128,uint64,uint40)[],(address,uint256))) (runs: 50, μ: 4240375, ~: 3897903) +CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_CreateWithTimestamps() (gas: 284891) +CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_CreateWithTimestamps_AssetMissingReturnValue() (gas: 291246) +CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_CreateWithTimestamps_StartTimeLessThanEndTime() (gas: 242528) +CreateWithTimestamps_LockupLinear_Integration_Concrete_Test:test_RevertGiven_EndTimeNotInTheFuture() (gas: 33024) +CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test:testFuzz_CreateWithTimestamps(address,(address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256))) (runs: 50, μ: 397470, ~: 409218) +CreateWithTimestamps_LockupTranched_Integration_Concrete_Test:test_CreateWithTimestamps() (gas: 377346) +CreateWithTimestamps_LockupTranched_Integration_Concrete_Test:test_CreateWithTimestamps_AssetMissingReturnValue() (gas: 383767) +CreateWithTimestamps_LockupTranched_Integration_Concrete_Test:test_RevertGiven_EndTimeNotInTheFuture() (gas: 41670) +CreateWithTimestamps_LockupTranched_Integration_Fuzz_Test:testFuzz_CreateWithTimestamps(address,(address,address,uint128,address,bool,bool,uint40,(uint128,uint40)[],(address,uint256))) (runs: 50, μ: 4246517, ~: 4719143) +GenerateAccentColor_Integration_Concrete_Test:test_GenerateAccentColor() (gas: 16028) +GetAsset_LockupDynamic_Integration_Concrete_Test:test_GetAsset() (gas: 279107) +GetAsset_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12005) +GetAsset_LockupLinear_Integration_Concrete_Test:test_GetAsset() (gas: 227792) +GetAsset_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11991) +GetAsset_LockupTranched_Integration_Concrete_Test:test_GetAsset() (gas: 304673) +GetAsset_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12013) +GetCliffTime_LockupLinear_Integration_Concrete_Test:test_GetCliffTime() (gas: 228432) +GetCliffTime_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11413) +GetDepositedAmount_LockupDynamic_Integration_Concrete_Test:test_GetDepositedAmount() (gas: 282044) +GetDepositedAmount_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11637) +GetDepositedAmount_LockupLinear_Integration_Concrete_Test:test_GetDepositedAmount() (gas: 230681) +GetDepositedAmount_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11611) +GetDepositedAmount_LockupTranched_Integration_Concrete_Test:test_GetDepositedAmount() (gas: 307632) +GetDepositedAmount_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11667) +GetEndTime_LockupDynamic_Integration_Concrete_Test:test_GetEndTime() (gas: 281864) +GetEndTime_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11537) +GetEndTime_LockupLinear_Integration_Concrete_Test:test_GetEndTime() (gas: 230571) +GetEndTime_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11545) +GetEndTime_LockupTranched_Integration_Concrete_Test:test_GetEndTime() (gas: 307474) +GetEndTime_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11589) +GetRange_LockupDynamic_Integration_Concrete_Test:test_GetRange() (gas: 278092) +GetRange_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13036) +GetRange_LockupLinear_Integration_Concrete_Test:test_GetRange() (gas: 227708) +GetRange_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13228) +GetRange_LockupTranched_Integration_Concrete_Test:test_GetRange() (gas: 303615) +GetRange_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13044) +GetRecipient_LockupDynamic_Integration_Concrete_Test:test_GetRecipient() (gas: 15675) +GetRecipient_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 67651) +GetRecipient_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11436) +GetRecipient_LockupLinear_Integration_Concrete_Test:test_GetRecipient() (gas: 15655) +GetRecipient_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 69889) +GetRecipient_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11416) +GetRecipient_LockupTranched_Integration_Concrete_Test:test_GetRecipient() (gas: 15683) +GetRecipient_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 78720) +GetRecipient_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11444) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusDepleted() (gas: 311818) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusPending() (gas: 301586) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusSettled() (gas: 306861) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StatusStreaming() (gas: 306854) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusCanceled() (gas: 346255) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusDepleted() (gas: 348111) +GetRefundedAmount_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11935) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusDepleted() (gas: 258782) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusPending() (gas: 248283) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusSettled() (gas: 253558) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StatusStreaming() (gas: 253551) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusCanceled() (gas: 289733) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusDepleted() (gas: 291516) +GetRefundedAmount_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11921) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusDepleted() (gas: 340410) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusPending() (gas: 327152) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusSettled() (gas: 332427) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StatusStreaming() (gas: 332420) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusCanceled() (gas: 369718) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_GetRefundedAmount_StreamHasBeenCanceled_StatusDepleted() (gas: 371537) +GetRefundedAmount_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11943) +GetSegments_LockupDynamic_Integration_Concrete_Test:test_GetSegments() (gas: 283532) +GetSegments_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13713) +GetSender_LockupDynamic_Integration_Concrete_Test:test_GetSender() (gas: 278892) +GetSender_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11769) +GetSender_LockupLinear_Integration_Concrete_Test:test_GetSender() (gas: 227571) +GetSender_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11749) +GetSender_LockupTranched_Integration_Concrete_Test:test_GetSender() (gas: 304458) +GetSender_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11777) +GetStartTime_LockupDynamic_Integration_Concrete_Test:test_GetStartTime() (gas: 282061) +GetStartTime_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11801) +GetStartTime_LockupLinear_Integration_Concrete_Test:test_GetStartTime() (gas: 230746) +GetStartTime_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11787) +GetStartTime_LockupTranched_Integration_Concrete_Test:test_GetStartTime() (gas: 307627) +GetStartTime_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11809) +GetStream_LockupDynamic_Integration_Concrete_Test:test_GetStream() (gas: 276867) +GetStream_LockupDynamic_Integration_Concrete_Test:test_GetStream_StatusSettled() (gas: 64268) +GetStream_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 15755) +GetStream_LockupLinear_Integration_Concrete_Test:test_GetStream() (gas: 52571) +GetStream_LockupLinear_Integration_Concrete_Test:test_GetStream_StatusSettled() (gas: 54618) +GetStream_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14524) +GetStream_LockupTranched_Integration_Concrete_Test:test_GetStream() (gas: 303573) +GetStream_LockupTranched_Integration_Concrete_Test:test_GetStream_StatusSettled() (gas: 68952) +GetStream_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 15753) +GetTranches_LockupTranched_Integration_Concrete_Test:test_GetTranches() (gas: 310004) +GetTranches_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 13519) +GetWithdrawnAmount_LockupDynamic_Integration_Concrete_Test:test_GetWithdrawnAmount() (gas: 356065) +GetWithdrawnAmount_LockupDynamic_Integration_Concrete_Test:test_GetWithdrawnAmount_NoPreviousWithdrawals() (gas: 304847) +GetWithdrawnAmount_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11934) +GetWithdrawnAmount_LockupDynamic_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount(uint256,uint128) (runs: 50, μ: 359040, ~: 359618) +GetWithdrawnAmount_LockupDynamic_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount_NoPreviousWithdrawals(uint256) (runs: 50, μ: 306462, ~: 306683) +GetWithdrawnAmount_LockupLinear_Integration_Concrete_Test:test_GetWithdrawnAmount() (gas: 275415) +GetWithdrawnAmount_LockupLinear_Integration_Concrete_Test:test_GetWithdrawnAmount_NoPreviousWithdrawals() (gas: 253544) +GetWithdrawnAmount_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11920) +GetWithdrawnAmount_LockupLinear_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount(uint256,uint128) (runs: 50, μ: 278630, ~: 278520) +GetWithdrawnAmount_LockupLinear_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount_NoPreviousWithdrawals(uint256) (runs: 50, μ: 255145, ~: 255380) +GetWithdrawnAmount_LockupTranched_Integration_Concrete_Test:test_GetWithdrawnAmount() (gas: 357087) +GetWithdrawnAmount_LockupTranched_Integration_Concrete_Test:test_GetWithdrawnAmount_NoPreviousWithdrawals() (gas: 330413) +GetWithdrawnAmount_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11942) +GetWithdrawnAmount_LockupTranched_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount(uint256,uint128) (runs: 50, μ: 360154, ~: 360186) +GetWithdrawnAmount_LockupTranched_Integration_Fuzz_Test:testFuzz_GetWithdrawnAmount_NoPreviousWithdrawals(uint256) (runs: 50, μ: 332001, ~: 331963) +IsCancelable_LockupDynamic_Integration_Concrete_Test:test_IsCancelable() (gas: 483969) +IsCancelable_LockupDynamic_Integration_Concrete_Test:test_IsCancelable_Cold() (gas: 305109) +IsCancelable_LockupDynamic_Integration_Concrete_Test:test_IsCancelable_StreamCancelable() (gas: 298835) +IsCancelable_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11294) +IsCancelable_LockupLinear_Integration_Concrete_Test:test_IsCancelable() (gas: 384875) +IsCancelable_LockupLinear_Integration_Concrete_Test:test_IsCancelable_Cold() (gas: 254006) +IsCancelable_LockupLinear_Integration_Concrete_Test:test_IsCancelable_StreamCancelable() (gas: 247567) +IsCancelable_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11318) +IsCancelable_LockupTranched_Integration_Concrete_Test:test_IsCancelable() (gas: 533279) +IsCancelable_LockupTranched_Integration_Concrete_Test:test_IsCancelable_Cold() (gas: 332234) +IsCancelable_LockupTranched_Integration_Concrete_Test:test_IsCancelable_StreamCancelable() (gas: 324435) +IsCancelable_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11327) +IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusCanceled() (gas: 345085) +IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusDepleted() (gas: 311529) +IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusPending() (gas: 299599) +IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusSettled() (gas: 305439) +IsCold_LockupDynamic_Integration_Concrete_Test:test_IsCold_StatusStreaming() (gas: 321700) +IsCold_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11580) +IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusCanceled() (gas: 288614) +IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusDepleted() (gas: 258551) +IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusPending() (gas: 248354) +IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusSettled() (gas: 254354) +IsCold_LockupLinear_Integration_Concrete_Test:test_IsCold_StatusStreaming() (gas: 254797) +IsCold_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11623) +IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusCanceled() (gas: 368598) +IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusDepleted() (gas: 340178) +IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusPending() (gas: 325222) +IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusSettled() (gas: 332582) +IsCold_LockupTranched_Integration_Concrete_Test:test_IsCold_StatusStreaming() (gas: 333051) +IsCold_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11632) +IsDepleted_LockupDynamic_Integration_Concrete_Test:test_IsDepleted() (gas: 310963) +IsDepleted_LockupDynamic_Integration_Concrete_Test:test_IsDepleted_StreamNotDepleted() (gas: 298184) +IsDepleted_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11161) +IsDepleted_LockupLinear_Integration_Concrete_Test:test_IsDepleted() (gas: 257950) +IsDepleted_LockupLinear_Integration_Concrete_Test:test_IsDepleted_StreamNotDepleted() (gas: 246904) +IsDepleted_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11182) +IsDepleted_LockupTranched_Integration_Concrete_Test:test_IsDepleted() (gas: 339577) +IsDepleted_LockupTranched_Integration_Concrete_Test:test_IsDepleted_StreamNotDepleted() (gas: 323772) +IsDepleted_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11191) +IsStream_LockupDynamic_Integration_Concrete_Test:test_IsStream() (gas: 298544) +IsStream_LockupDynamic_Integration_Concrete_Test:test_IsStream_Null() (gas: 11602) +IsStream_LockupLinear_Integration_Concrete_Test:test_IsStream() (gas: 247261) +IsStream_LockupLinear_Integration_Concrete_Test:test_IsStream_Null() (gas: 11623) +IsStream_LockupTranched_Integration_Concrete_Test:test_IsStream() (gas: 324107) +IsStream_LockupTranched_Integration_Concrete_Test:test_IsStream_Null() (gas: 11610) +IsTransferable_LockupDynamic_Integration_Concrete_Test:test_IsTransferable_Stream() (gas: 298690) +IsTransferable_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11689) +IsTransferable_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamTransferNotEnabled() (gas: 483824) +IsTransferable_LockupLinear_Integration_Concrete_Test:test_IsTransferable_Stream() (gas: 247432) +IsTransferable_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11732) +IsTransferable_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamTransferNotEnabled() (gas: 384755) +IsTransferable_LockupTranched_Integration_Concrete_Test:test_IsTransferable_Stream() (gas: 324278) +IsTransferable_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11719) +IsTransferable_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamTransferNotEnabled() (gas: 533122) +IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusCanceled() (gas: 344575) +IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusDepleted() (gas: 311040) +IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusPending() (gas: 299017) +IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusSettled() (gas: 304957) +IsWarm_LockupDynamic_Integration_Concrete_Test:test_IsWarm_StatusStreaming() (gas: 321212) +IsWarm_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11118) +IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusCanceled() (gas: 288095) +IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusDepleted() (gas: 258046) +IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusPending() (gas: 247756) +IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusSettled() (gas: 253866) +IsWarm_LockupLinear_Integration_Concrete_Test:test_IsWarm_StatusStreaming() (gas: 254293) +IsWarm_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11161) +IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusCanceled() (gas: 368035) +IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusDepleted() (gas: 339629) +IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusPending() (gas: 324580) +IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusSettled() (gas: 332050) +IsWarm_LockupTranched_Integration_Concrete_Test:test_IsWarm_StatusStreaming() (gas: 332503) +IsWarm_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11126) +MapSymbol_Integration_Concrete_Test:test_MapSymbol_LockupDynamic() (gas: 20092) +MapSymbol_Integration_Concrete_Test:test_MapSymbol_LockupLinear() (gas: 19732) +MapSymbol_Integration_Concrete_Test:test_MapSymbol_LockupTranched() (gas: 20496) +MapSymbol_Integration_Concrete_Test:test_RevertGiven_UnknownNFT() (gas: 911452) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusDepleted() (gas: 311027) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusPending() (gas: 304884) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusSettled() (gas: 304855) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StatusStreaming() (gas: 311672) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 344510) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 347729) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RefundableAmountOf_StreamNotCancelable() (gas: 489143) +RefundableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11121) +RefundableAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_RefundableAmountOf(uint256) (runs: 50, μ: 49760, ~: 64695) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusDepleted() (gas: 258007) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusPending() (gas: 253572) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusSettled() (gas: 253737) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StatusStreaming() (gas: 255135) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 288004) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 291150) +RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RefundableAmountOf_StreamNotCancelable() (gas: 390054) RefundableAmountOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11132) -RefundableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_RefundableAmountOf(uint256) (runs: 5, μ: 32677, ~: 32471) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusDepleted() (gas: 339091) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusPending() (gas: 331273) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusSettled() (gas: 331424) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusStreaming() (gas: 332554) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 367389) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 370561) -RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StreamNotCancelable() (gas: 538043) +RefundableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_RefundableAmountOf(uint256) (runs: 50, μ: 33537, ~: 33714) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusDepleted() (gas: 339613) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusPending() (gas: 331795) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusSettled() (gas: 331944) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StatusStreaming() (gas: 333077) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 367967) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 371149) +RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RefundableAmountOf_StreamNotCancelable() (gas: 538413) RefundableAmountOf_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11132) -RefundableAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_RefundableAmountOf(uint256) (runs: 5, μ: 41154, ~: 40603) -Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce() (gas: 673760) -Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientDoesNotImplementHook() (gas: 666877) -Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientNotContract() (gas: 278302) -Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientReentrancy() (gas: 672112) -Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientReverts() (gas: 667440) -Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11618) -Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 87301) -Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 63570) -Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 24775) -Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 629158) -Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce() (gas: 526920) -Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientDoesNotImplementHook() (gas: 520007) -Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientNotContract() (gas: 227020) -Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientReentrancy() (gas: 525172) -Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientReverts() (gas: 520570) +RefundableAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_RefundableAmountOf(uint256) (runs: 50, μ: 42343, ~: 42478) +Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce() (gas: 674450) +Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientDoesNotImplementHook() (gas: 667547) +Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientNotContract() (gas: 279340) +Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientReentrancy() (gas: 672720) +Renounce_LockupDynamic_Integration_Concrete_Test:test_Renounce_RecipientReverts() (gas: 668110) +Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11611) +Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 87243) +Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 63573) +Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 24758) +Renounce_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 628608) +Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce() (gas: 527612) +Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientDoesNotImplementHook() (gas: 520677) +Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientNotContract() (gas: 228094) +Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientReentrancy() (gas: 525842) +Renounce_LockupLinear_Integration_Concrete_Test:test_Renounce_RecipientReverts() (gas: 521240) Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11619) Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 80032) -Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 65826) +Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 65848) Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 26936) -Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 482308) -Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce() (gas: 749480) -Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientDoesNotImplementHook() (gas: 742567) -Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientNotContract() (gas: 306605) -Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientReentrancy() (gas: 749114) -Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientReverts() (gas: 743130) +Renounce_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 481702) +Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce() (gas: 750292) +Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientDoesNotImplementHook() (gas: 743357) +Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientNotContract() (gas: 307711) +Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientReentrancy() (gas: 749898) +Renounce_LockupTranched_Integration_Concrete_Test:test_Renounce_RecipientReverts() (gas: 743920) Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11619) -Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 87098) -Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 74613) -Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 34304) -Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 703431) -SafeAssetDecimals_Integration_Concrete_Test:test_SafeAssetDecimals() (gas: 12029) -SafeAssetDecimals_Integration_Concrete_Test:test_SafeAssetDecimals_DecimalsNotImplemented() (gas: 10852) -SafeAssetDecimals_Integration_Concrete_Test:test_SafeAssetDecimals_EOA() (gas: 11625) -SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol() (gas: 18460) -SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_Bytes32() (gas: 62214) -SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_EOA() (gas: 13222) -SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_LongSymbol() (gas: 546503) -SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_SymbolNotImplemented() (gas: 12399) -SetNFTDescriptor_LockupDynamic_Integration_Concrete_Test:test_SetNFTDescriptor_NewNFTDescriptor() (gas: 6618523) -SetNFTDescriptor_LockupDynamic_Integration_Concrete_Test:test_SetNFTDescriptor_SameNFTDescriptor() (gas: 2304797) -SetNFTDescriptor_LockupLinear_Integration_Concrete_Test:test_SetNFTDescriptor_NewNFTDescriptor() (gas: 6618805) -SetNFTDescriptor_LockupLinear_Integration_Concrete_Test:test_SetNFTDescriptor_SameNFTDescriptor() (gas: 2304889) -SetNFTDescriptor_LockupTranched_Integration_Concrete_Test:test_SetNFTDescriptor_NewNFTDescriptor() (gas: 6628035) -SetNFTDescriptor_LockupTranched_Integration_Concrete_Test:test_SetNFTDescriptor_SameNFTDescriptor() (gas: 2314332) -StatusOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11634) -StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf() (gas: 321307) -StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_AssetsFullyWithdrawn() (gas: 311132) -StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_RefundableAmountNotZero() (gas: 305062) -StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_StartTimeInTheFuture() (gas: 299139) -StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_StreamCanceled() (gas: 344739) -StatusOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11637) -StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf() (gas: 253708) -StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_AssetsFullyWithdrawn() (gas: 258117) -StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_RefundableAmountNotZero() (gas: 253958) -StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_StartTimeInTheFuture() (gas: 247865) -StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_StreamCanceled() (gas: 288199) -StatusOf_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11659) -StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf() (gas: 331933) -StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_AssetsFullyWithdrawn() (gas: 339741) -StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_RefundableAmountNotZero() (gas: 332163) -StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_StartTimeInTheFuture() (gas: 324702) -StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_StreamCanceled() (gas: 368102) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11349) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_CurrentTimestamp1st() (gas: 46012) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_CurrentTimestampNot1st() (gas: 50875) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_OneSegment() (gas: 242637) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInTheFuture() (gas: 20263) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInThePresent() (gas: 25627) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StatusDepleted() (gas: 63926) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StatusPending() (gas: 20393) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StatusSettled() (gas: 26723) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 87670) -StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 111421) -StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Calculation((uint128,uint64,uint40)[],uint40) (runs: 5, μ: 2511998, ~: 2840809) -StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Monotonicity((uint128,uint64,uint40)[],uint40,uint40) (runs: 5, μ: 3710255, ~: 3160094) -StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_OneSegment((uint128,uint64,uint40),uint40) (runs: 5, μ: 259274, ~: 259452) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11371) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_CliffTimeInTheFuture() (gas: 28307) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_CliffTimeInThePast() (gas: 19297) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_CliffTimeInThePresent() (gas: 29169) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StatusDepleted() (gas: 66161) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StatusPending() (gas: 22311) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StatusSettled() (gas: 28824) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 80402) -StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 104039) -StreamedAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Calculation(uint40,uint128) (runs: 5, μ: 240765, ~: 239992) -StreamedAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_CliffTimeInTheFuture(uint40) (runs: 5, μ: 29242, ~: 28966) -StreamedAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Monotonicity(uint40,uint40,uint128) (runs: 5, μ: 246655, ~: 248105) +Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusCanceled() (gas: 87148) +Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusDepleted() (gas: 74607) +Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StatusSettled() (gas: 34296) +Renounce_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotCancelable() (gas: 702951) +SafeAssetDecimals_Integration_Concrete_Test:test_SafeAssetDecimals() (gas: 15233) +SafeAssetDecimals_Integration_Concrete_Test:test_SafeAssetDecimals_DecimalsNotImplemented() (gas: 14011) +SafeAssetDecimals_Integration_Concrete_Test:test_SafeAssetDecimals_EOA() (gas: 12384) +SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol() (gas: 21211) +SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_Bytes32() (gas: 65033) +SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_EOA() (gas: 13573) +SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_LongSymbol() (gas: 549340) +SafeAssetSymbol_Integration_Concrete_Test:test_SafeAssetSymbol_SymbolNotImplemented() (gas: 15218) +SetNFTDescriptor_LockupDynamic_Integration_Concrete_Test:test_SetNFTDescriptor_NewNFTDescriptor() (gas: 6621165) +SetNFTDescriptor_LockupDynamic_Integration_Concrete_Test:test_SetNFTDescriptor_SameNFTDescriptor() (gas: 2173601) +SetNFTDescriptor_LockupLinear_Integration_Concrete_Test:test_SetNFTDescriptor_NewNFTDescriptor() (gas: 6621585) +SetNFTDescriptor_LockupLinear_Integration_Concrete_Test:test_SetNFTDescriptor_SameNFTDescriptor() (gas: 2173921) +SetNFTDescriptor_LockupTranched_Integration_Concrete_Test:test_SetNFTDescriptor_NewNFTDescriptor() (gas: 6630809) +SetNFTDescriptor_LockupTranched_Integration_Concrete_Test:test_SetNFTDescriptor_SameNFTDescriptor() (gas: 2183286) +StatusOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11639) +StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf() (gas: 321826) +StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_AssetsFullyWithdrawn() (gas: 311658) +StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_RefundableAmountNotZero() (gas: 305618) +StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_StartTimeInTheFuture() (gas: 299673) +StatusOf_LockupDynamic_Integration_Concrete_Test:test_StatusOf_StreamCanceled() (gas: 345203) +StatusOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11647) +StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf() (gas: 254225) +StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_AssetsFullyWithdrawn() (gas: 258634) +StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_RefundableAmountNotZero() (gas: 254497) +StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_StartTimeInTheFuture() (gas: 248382) +StatusOf_LockupLinear_Integration_Concrete_Test:test_StatusOf_StreamCanceled() (gas: 288693) +StatusOf_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11669) +StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf() (gas: 332488) +StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_AssetsFullyWithdrawn() (gas: 340274) +StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_RefundableAmountNotZero() (gas: 332738) +StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_StartTimeInTheFuture() (gas: 325263) +StatusOf_LockupTranched_Integration_Concrete_Test:test_StatusOf_StreamCanceled() (gas: 368690) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11363) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_CurrentTimestamp1st() (gas: 46712) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_CurrentTimestampNot1st() (gas: 51600) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_OneSegment() (gas: 243140) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInTheFuture() (gas: 20956) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInThePresent() (gas: 26320) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StatusDepleted() (gas: 64611) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StatusPending() (gas: 21041) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StatusSettled() (gas: 27350) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 88316) +StreamedAmountOf_LockupDynamic_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 112081) +StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Calculation((uint128,uint64,uint40)[],uint40) (runs: 50, μ: 3527814, ~: 3132657) +StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Monotonicity((uint128,uint64,uint40)[],uint40,uint40) (runs: 50, μ: 3974945, ~: 4117049) +StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_OneSegment((uint128,uint64,uint40),uint40) (runs: 50, μ: 275320, ~: 269270) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11327) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_CliffTimeInTheFuture() (gas: 29033) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_CliffTimeInThePast() (gas: 22523) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_CliffTimeInThePresent() (gas: 29895) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StatusDepleted() (gas: 66820) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StatusPending() (gas: 23037) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StatusSettled() (gas: 29550) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 81106) +StreamedAmountOf_LockupLinear_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 104765) +StreamedAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Calculation(uint40,uint128) (runs: 50, μ: 250714, ~: 250611) +StreamedAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_CliffTimeInTheFuture(uint40) (runs: 50, μ: 30129, ~: 30364) +StreamedAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Monotonicity(uint40,uint40,uint128) (runs: 50, μ: 255728, ~: 257888) StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11371) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf() (gas: 43891) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_CurrentTimestamp1st() (gas: 35099) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInTheFuture() (gas: 29618) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInThePresent() (gas: 34982) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StatusDepleted() (gas: 74969) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StatusPending() (gas: 29725) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StatusSettled() (gas: 36258) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 87534) -StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 111207) -StreamedAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Calculation((uint128,uint40)[],uint40) (runs: 5, μ: 2959814, ~: 3379078) -StreamedAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Monotonicity((uint128,uint40)[],uint40,uint40) (runs: 5, μ: 2997213, ~: 2909950) -TokenURI_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 13902) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf() (gas: 44651) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_CurrentTimestamp1st() (gas: 35797) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInTheFuture() (gas: 30316) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StartTimeInThePresent() (gas: 35680) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StatusDepleted() (gas: 75645) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StatusPending() (gas: 30423) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StatusSettled() (gas: 36954) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 88288) +StreamedAmountOf_LockupTranched_Integration_Concrete_Test:test_StreamedAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 111949) +StreamedAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Calculation((uint128,uint40)[],uint40) (runs: 50, μ: 3412261, ~: 3624836) +StreamedAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_StreamedAmountOf_Monotonicity((uint128,uint40)[],uint40,uint40) (runs: 50, μ: 3836358, ~: 3850731) +TokenURI_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 13949) TokenURI_LockupDynamic_Integration_Concrete_Test:test_TokenURI_Decoded() (gas: 6624) -TokenURI_LockupDynamic_Integration_Concrete_Test:test_TokenURI_Full() (gas: 6601) -TokenURI_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 13877) +TokenURI_LockupDynamic_Integration_Concrete_Test:test_TokenURI_Full() (gas: 6623) +TokenURI_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 13932) TokenURI_LockupLinear_Integration_Concrete_Test:test_TokenURI_Decoded() (gas: 6624) -TokenURI_LockupLinear_Integration_Concrete_Test:test_TokenURI_Full() (gas: 6601) -TokenURI_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 13899) +TokenURI_LockupLinear_Integration_Concrete_Test:test_TokenURI_Full() (gas: 6623) +TokenURI_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTDoesNotExist() (gas: 13954) TokenURI_LockupTranched_Integration_Concrete_Test:test_TokenURI_Decoded() (gas: 6624) -TokenURI_LockupTranched_Integration_Concrete_Test:test_TokenURI_Full() (gas: 6601) -TransferFrom_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 281816) -TransferFrom_LockupDynamic_Integration_Concrete_Test:test_TransferFrom() (gas: 294142) -TransferFrom_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 230015) -TransferFrom_LockupLinear_Integration_Concrete_Test:test_TransferFrom() (gas: 242845) -TransferFrom_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 307514) -TransferFrom_LockupTranched_Integration_Concrete_Test:test_TransferFrom() (gas: 319688) -WasCanceled_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11972) -WasCanceled_LockupDynamic_Integration_Concrete_Test:test_WasCanceled() (gas: 312812) -WasCanceled_LockupDynamic_Integration_Concrete_Test:test_WasCanceled_StreamNotCanceled() (gas: 296044) -WasCanceled_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11985) -WasCanceled_LockupLinear_Integration_Concrete_Test:test_WasCanceled() (gas: 259524) -WasCanceled_LockupLinear_Integration_Concrete_Test:test_WasCanceled_StreamNotCanceled() (gas: 244781) -WasCanceled_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11972) -WasCanceled_LockupTranched_Integration_Concrete_Test:test_WasCanceled() (gas: 339741) -WasCanceled_LockupTranched_Integration_Concrete_Test:test_WasCanceled_StreamNotCanceled() (gas: 321583) -WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 72520) -WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14131) -WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 250166) -WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_WithdrawMaxAndTransfer() (gas: 160470) -WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_WithdrawMaxAndTransfer_WithdrawableAmountZero() (gas: 97615) -WithdrawMaxAndTransfer_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMaxAndTransfer(uint256,address) (runs: 5, μ: 138955, ~: 157016) -WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 74730) -WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14116) -WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 196381) -WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_WithdrawMaxAndTransfer() (gas: 115324) -WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_WithdrawMaxAndTransfer_WithdrawableAmountZero() (gas: 99898) -WithdrawMaxAndTransfer_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMaxAndTransfer(uint256,address) (runs: 5, μ: 105715, ~: 113052) -WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 83583) -WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14138) -WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 277260) -WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_WithdrawMaxAndTransfer() (gas: 125432) -WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_WithdrawMaxAndTransfer_WithdrawableAmountZero() (gas: 108707) -WithdrawMaxAndTransfer_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMaxAndTransfer(uint256,address) (runs: 5, μ: 108104, ~: 123265) -WithdrawMax_LockupDynamic_Integration_Concrete_Test:test_WithdrawMax() (gas: 137497) -WithdrawMax_LockupDynamic_Integration_Concrete_Test:test_WithdrawMax_EndTimeNotInTheFuture() (gas: 77911) -WithdrawMax_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMax(uint256) (runs: 5, μ: 117056, ~: 123442) -WithdrawMax_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMax_EndTimeNotInTheFuture(uint256) (runs: 5, μ: 80372, ~: 80265) -WithdrawMax_LockupLinear_Integration_Concrete_Test:test_WithdrawMax() (gas: 78765) -WithdrawMax_LockupLinear_Integration_Concrete_Test:test_WithdrawMax_EndTimeNotInTheFuture() (gas: 80135) -WithdrawMax_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMax(uint256) (runs: 5, μ: 77716, ~: 77609) -WithdrawMax_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMax_EndTimeNotInTheFuture(uint256) (runs: 5, μ: 82596, ~: 82489) -WithdrawMax_LockupTranched_Integration_Concrete_Test:test_WithdrawMax() (gas: 90206) -WithdrawMax_LockupTranched_Integration_Concrete_Test:test_WithdrawMax_EndTimeNotInTheFuture() (gas: 89003) -WithdrawMax_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMax(uint256) (runs: 5, μ: 87584, ~: 88106) -WithdrawMax_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMax_EndTimeNotInTheFuture(uint256) (runs: 5, μ: 91464, ~: 91357) -WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_AllStatusesDepleted() (gas: 73532) -WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 20750) -WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 124808) -WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeStatusesDepleted() (gas: 83005) -WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_WithdrawMultiple() (gas: 268527) -WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_WithdrawMultiple_ArrayCountsZero() (gas: 6576) -WithdrawMultiple_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMultiple(uint256,uint128) (runs: 5, μ: 2695106, ~: 2695379) -WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_AllStatusesDepleted() (gas: 75674) -WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 20636) +TokenURI_LockupTranched_Integration_Concrete_Test:test_TokenURI_Full() (gas: 6623) +TransferFrom_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 281658) +TransferFrom_LockupDynamic_Integration_Concrete_Test:test_TransferFrom() (gas: 294710) +TransferFrom_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 229833) +TransferFrom_LockupLinear_Integration_Concrete_Test:test_TransferFrom() (gas: 243397) +TransferFrom_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 307376) +TransferFrom_LockupTranched_Integration_Concrete_Test:test_TransferFrom() (gas: 320284) +WasCanceled_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12019) +WasCanceled_LockupDynamic_Integration_Concrete_Test:test_WasCanceled() (gas: 315725) +WasCanceled_LockupDynamic_Integration_Concrete_Test:test_WasCanceled_StreamNotCanceled() (gas: 299008) +WasCanceled_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12040) +WasCanceled_LockupLinear_Integration_Concrete_Test:test_WasCanceled() (gas: 262452) +WasCanceled_LockupLinear_Integration_Concrete_Test:test_WasCanceled_StreamNotCanceled() (gas: 247728) +WasCanceled_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12027) +WasCanceled_LockupTranched_Integration_Concrete_Test:test_WasCanceled() (gas: 342695) +WasCanceled_LockupTranched_Integration_Concrete_Test:test_WasCanceled_StreamNotCanceled() (gas: 324574) +WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 72267) +WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14095) +WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 249967) +WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_WithdrawMaxAndTransfer() (gas: 161853) +WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test:test_WithdrawMaxAndTransfer_WithdrawableAmountZero() (gas: 97659) +WithdrawMaxAndTransfer_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMaxAndTransfer(uint256,address) (runs: 50, μ: 138167, ~: 158647) +WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 74526) +WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14093) +WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 196166) +WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_WithdrawMaxAndTransfer() (gas: 116725) +WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test:test_WithdrawMaxAndTransfer_WithdrawableAmountZero() (gas: 99964) +WithdrawMaxAndTransfer_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMaxAndTransfer(uint256,address) (runs: 50, μ: 99953, ~: 114536) +WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_RevertGiven_NFTBurned() (gas: 83351) +WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 14115) +WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamNotTransferable() (gas: 277083) +WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_WithdrawMaxAndTransfer() (gas: 126986) +WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test:test_WithdrawMaxAndTransfer_WithdrawableAmountZero() (gas: 108745) +WithdrawMaxAndTransfer_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMaxAndTransfer(uint256,address) (runs: 50, μ: 111182, ~: 124791) +WithdrawMax_LockupDynamic_Integration_Concrete_Test:test_WithdrawMax() (gas: 138996) +WithdrawMax_LockupDynamic_Integration_Concrete_Test:test_WithdrawMax_EndTimeNotInTheFuture() (gas: 80630) +WithdrawMax_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMax(uint256) (runs: 50, μ: 120523, ~: 123572) +WithdrawMax_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMax_EndTimeNotInTheFuture(uint256) (runs: 50, μ: 83249, ~: 83404) +WithdrawMax_LockupLinear_Integration_Concrete_Test:test_WithdrawMax() (gas: 80273) +WithdrawMax_LockupLinear_Integration_Concrete_Test:test_WithdrawMax_EndTimeNotInTheFuture() (gas: 82915) +WithdrawMax_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMax(uint256) (runs: 50, μ: 78556, ~: 78693) +WithdrawMax_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMax_EndTimeNotInTheFuture(uint256) (runs: 50, μ: 85520, ~: 85689) +WithdrawMax_LockupTranched_Integration_Concrete_Test:test_WithdrawMax() (gas: 91922) +WithdrawMax_LockupTranched_Integration_Concrete_Test:test_WithdrawMax_EndTimeNotInTheFuture() (gas: 91755) +WithdrawMax_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMax(uint256) (runs: 50, μ: 88695, ~: 88993) +WithdrawMax_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMax_EndTimeNotInTheFuture(uint256) (runs: 50, μ: 94402, ~: 94529) +WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_AllStatusesDepleted() (gas: 73486) +WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 20712) +WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 124801) +WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_SomeStatusesDepleted() (gas: 82981) +WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_WithdrawMultiple() (gas: 274573) +WithdrawMultiple_LockupDynamic_Integration_Concrete_Test:test_WithdrawMultiple_ArrayCountsZero() (gas: 6560) +WithdrawMultiple_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawMultiple(uint256,uint128) (runs: 50, μ: 2704176, ~: 2704701) +WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_AllStatusesDepleted() (gas: 75652) +WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 20614) WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 109270) WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_RevertGiven_SomeStatusesDepleted() (gas: 85147) -WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_WithdrawMultiple() (gas: 221649) +WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_WithdrawMultiple() (gas: 227818) WithdrawMultiple_LockupLinear_Integration_Concrete_Test:test_WithdrawMultiple_ArrayCountsZero() (gas: 6549) -WithdrawMultiple_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMultiple(uint256,uint128) (runs: 5, μ: 1986261, ~: 1986387) -WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_AllStatusesDepleted() (gas: 84532) -WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 20707) -WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 124109) -WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeStatusesDepleted() (gas: 94005) -WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_WithdrawMultiple() (gas: 245406) -WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_WithdrawMultiple_ArrayCountsZero() (gas: 6593) -WithdrawMultiple_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMultiple(uint256,uint128) (runs: 5, μ: 2876750, ~: 2876876) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 19879) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamDepleted() (gas: 65314) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw() (gas: 354742) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_CallerApprovedOperator() (gas: 113106) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_CallerRecipient() (gas: 83569) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_CallerUnknownAddress() (gas: 84520) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_EndTimeNotInTheFuture() (gas: 67797) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_GoodSender() (gas: 297401) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientDoesNotImplementHook() (gas: 354175) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientNotContract() (gas: 107941) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientReentrancy() (gas: 375539) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientReverts() (gas: 354751) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_ReentrancySender() (gas: 322132) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RevertingSender() (gas: 297364) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_SenderDoesNotImplementHook() (gas: 296886) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_SenderNotContract() (gas: 85185) -Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_StreamHasBeenCanceled() (gas: 127476) -Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw(uint256,address,uint128) (runs: 5, μ: 126442, ~: 100726) -Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_CallerApprovedOperator(address) (runs: 5, μ: 147886, ~: 147886) -Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_SegmentFuzing(((uint128,uint64,uint40)[],uint256,address)) (runs: 5, μ: 3809541, ~: 4704372) -Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_StreamHasBeenCanceled(uint256,address,uint128) (runs: 5, μ: 160725, ~: 160792) -Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_UnknownCaller(address) (runs: 5, μ: 105849, ~: 105849) -Withdraw_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 19848) -Withdraw_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamDepleted() (gas: 67539) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw() (gas: 273616) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_CallerApprovedOperator() (gas: 95396) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_CallerRecipient() (gas: 65873) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_CallerUnknownAddress() (gas: 66824) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_EndTimeNotInTheFuture() (gas: 69934) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_GoodSender() (gas: 229906) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientDoesNotImplementHook() (gas: 273047) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientNotContract() (gas: 76596) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientReentrancy() (gas: 280732) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientReverts() (gas: 273623) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_ReentrancySender() (gas: 240955) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RevertingSender() (gas: 229870) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_SenderDoesNotImplementHook() (gas: 229392) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_SenderNotContract() (gas: 67489) -Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_StreamHasBeenCanceled() (gas: 109726) -Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw(uint256,address,uint128) (runs: 5, μ: 104108, ~: 104278) -Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw_CallerApprovedOperator(address) (runs: 5, μ: 116531, ~: 116531) -Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw_StreamHasBeenCanceled(uint256,address,uint128) (runs: 5, μ: 142788, ~: 142836) -Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw_UnknownCaller(address) (runs: 5, μ: 74502, ~: 74502) -Withdraw_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 19855) -Withdraw_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamDepleted() (gas: 76333) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw() (gas: 355808) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_CallerApprovedOperator() (gas: 102748) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_CallerRecipient() (gas: 73225) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_CallerUnknownAddress() (gas: 74176) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_EndTimeNotInTheFuture() (gas: 77360) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_GoodSender() (gas: 310741) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientDoesNotImplementHook() (gas: 355239) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientNotContract() (gas: 85301) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientReentrancy() (gas: 364263) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientReverts() (gas: 355815) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_ReentrancySender() (gas: 323117) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RevertingSender() (gas: 310705) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_SenderDoesNotImplementHook() (gas: 310227) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_SenderNotContract() (gas: 74841) -Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_StreamHasBeenCanceled() (gas: 117182) -Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw(uint256,address,uint128) (runs: 5, μ: 115236, ~: 114843) -Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_CallerApprovedOperator(address) (runs: 5, μ: 125232, ~: 125232) -Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_StreamHasBeenCanceled(uint256,address,uint128) (runs: 5, μ: 150199, ~: 150351) -Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_TrancheFuzzing(((uint128,uint40)[],uint256,address)) (runs: 5, μ: 3284018, ~: 3684660) -Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_UnknownCaller(address) (runs: 5, μ: 83209, ~: 83209) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11987) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf() (gas: 346640) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_NoPreviousWithdrawals() (gas: 316158) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StartTimeInThePresent() (gas: 305667) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusDepleted() (gas: 312216) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusPending() (gas: 302415) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusSettled() (gas: 308704) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 346784) -WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 348964) -WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf(uint40,uint128) (runs: 5, μ: 317851, ~: 302058) -WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_NoPreviousWithdrawals(uint40) (runs: 5, μ: 290517, ~: 288578) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12010) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_CliffTimeInTheFuture() (gas: 244010) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_NoPreviousWithdrawals() (gas: 253946) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusDepleted() (gas: 259188) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusPending() (gas: 249082) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusSettled() (gas: 255565) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 290276) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 292308) -WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_WithWithdrawals() (gas: 277445) -WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf(uint40,uint128,uint128) (runs: 5, μ: 462713, ~: 461869) -WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_CliffTimeInTheFuture(uint40) (runs: 5, μ: 253983, ~: 253707) -WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_NoPreviousWithdrawals(uint40,uint128) (runs: 5, μ: 439185, ~: 440083) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11987) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf() (gas: 364161) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_NoPreviousWithdrawals() (gas: 337855) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StartTimeInThePresent() (gas: 332563) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusDepleted() (gas: 340800) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusPending() (gas: 329311) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusSettled() (gas: 335780) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 370122) -WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 372269) -WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf(uint40,uint128) (runs: 5, μ: 328843, ~: 328727) -WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_NoPreviousWithdrawals(uint40) (runs: 5, μ: 303871, ~: 303913) \ No newline at end of file +WithdrawMultiple_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawMultiple(uint256,uint128) (runs: 50, μ: 1995688, ~: 1995633) +WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_AllStatusesDepleted() (gas: 84497) +WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_OnlyNull() (gas: 20700) +WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeNull() (gas: 124147) +WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_RevertGiven_SomeStatusesDepleted() (gas: 93992) +WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_WithdrawMultiple() (gas: 251699) +WithdrawMultiple_LockupTranched_Integration_Concrete_Test:test_WithdrawMultiple_ArrayCountsZero() (gas: 6608) +WithdrawMultiple_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawMultiple(uint256,uint128) (runs: 50, μ: 2887130, ~: 2887100) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 19851) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_StreamDepleted() (gas: 65278) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw() (gas: 355910) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_CallerApprovedOperator() (gas: 113737) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_CallerRecipient() (gas: 84219) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_CallerUnknownAddress() (gas: 85125) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_EndTimeNotInTheFuture() (gas: 69772) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_GoodSender() (gas: 297883) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientDoesNotImplementHook() (gas: 355343) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientNotContract() (gas: 109286) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientReentrancy() (gas: 376688) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RecipientReverts() (gas: 355941) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_ReentrancySender() (gas: 323308) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_RevertingSender() (gas: 297846) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_SenderDoesNotImplementHook() (gas: 297368) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_SenderNotContract() (gas: 85854) +Withdraw_LockupDynamic_Integration_Concrete_Test:test_Withdraw_StreamHasBeenCanceled() (gas: 129471) +Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw(uint256,address,uint128) (runs: 50, μ: 126142, ~: 103351) +Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_CallerApprovedOperator(address) (runs: 50, μ: 149197, ~: 149197) +Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_SegmentFuzing(((uint128,uint64,uint40)[],uint256,address)) (runs: 50, μ: 3930319, ~: 3826320) +Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_StreamHasBeenCanceled(uint256,address,uint128) (runs: 50, μ: 162571, ~: 162747) +Withdraw_LockupDynamic_Integration_Fuzz_Test:testFuzz_Withdraw_UnknownCaller(address) (runs: 50, μ: 107201, ~: 107201) +Withdraw_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 19826) +Withdraw_LockupLinear_Integration_Concrete_Test:test_RevertGiven_StreamDepleted() (gas: 67517) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw() (gas: 274768) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_CallerApprovedOperator() (gas: 96056) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_CallerRecipient() (gas: 66533) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_CallerUnknownAddress() (gas: 67439) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_EndTimeNotInTheFuture() (gas: 71955) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_GoodSender() (gas: 230368) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientDoesNotImplementHook() (gas: 274199) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientNotContract() (gas: 77955) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientReentrancy() (gas: 281870) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RecipientReverts() (gas: 274797) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_ReentrancySender() (gas: 242127) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_RevertingSender() (gas: 230332) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_SenderDoesNotImplementHook() (gas: 229854) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_SenderNotContract() (gas: 68168) +Withdraw_LockupLinear_Integration_Concrete_Test:test_Withdraw_StreamHasBeenCanceled() (gas: 111795) +Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw(uint256,address,uint128) (runs: 50, μ: 106092, ~: 106044) +Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw_CallerApprovedOperator(address) (runs: 50, μ: 117877, ~: 117877) +Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw_StreamHasBeenCanceled(uint256,address,uint128) (runs: 50, μ: 145053, ~: 144905) +Withdraw_LockupLinear_Integration_Fuzz_Test:testFuzz_Withdraw_UnknownCaller(address) (runs: 50, μ: 75848, ~: 75848) +Withdraw_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 19833) +Withdraw_LockupTranched_Integration_Concrete_Test:test_RevertGiven_StreamDepleted() (gas: 76283) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw() (gas: 357101) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_CallerApprovedOperator() (gas: 103451) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_CallerRecipient() (gas: 73928) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_CallerUnknownAddress() (gas: 74834) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_EndTimeNotInTheFuture() (gas: 79361) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_GoodSender() (gas: 311290) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientDoesNotImplementHook() (gas: 356532) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientNotContract() (gas: 86758) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientReentrancy() (gas: 365577) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RecipientReverts() (gas: 357130) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_ReentrancySender() (gas: 324426) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_RevertingSender() (gas: 311254) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_SenderDoesNotImplementHook() (gas: 310776) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_SenderNotContract() (gas: 75563) +Withdraw_LockupTranched_Integration_Concrete_Test:test_Withdraw_StreamHasBeenCanceled() (gas: 119282) +Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw(uint256,address,uint128) (runs: 50, μ: 117380, ~: 117109) +Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_CallerApprovedOperator(address) (runs: 50, μ: 126674, ~: 126674) +Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_StreamHasBeenCanceled(uint256,address,uint128) (runs: 50, μ: 152488, ~: 152396) +Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_TrancheFuzzing(((uint128,uint40)[],uint256,address)) (runs: 50, μ: 3656828, ~: 3369659) +Withdraw_LockupTranched_Integration_Fuzz_Test:testFuzz_Withdraw_UnknownCaller(address) (runs: 50, μ: 84673, ~: 84673) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12001) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf() (gas: 347152) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_NoPreviousWithdrawals() (gas: 316711) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StartTimeInThePresent() (gas: 306125) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusDepleted() (gas: 312711) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusPending() (gas: 302873) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusSettled() (gas: 309163) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 347262) +WithdrawableAmountOf_LockupDynamic_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 349434) +WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf(uint40,uint128) (runs: 50, μ: 321569, ~: 302618) +WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_NoPreviousWithdrawals(uint40) (runs: 50, μ: 285304, ~: 278607) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 11965) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_CliffTimeInTheFuture() (gas: 246950) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_NoPreviousWithdrawals() (gas: 254430) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusDepleted() (gas: 259672) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusPending() (gas: 249588) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusSettled() (gas: 256071) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 290715) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 292814) +WithdrawableAmountOf_LockupLinear_Integration_Concrete_Test:test_WithdrawableAmountOf_WithWithdrawals() (gas: 277929) +WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf(uint40,uint128,uint128) (runs: 50, μ: 474838, ~: 475697) +WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_CliffTimeInTheFuture(uint40) (runs: 50, μ: 254609, ~: 254885) +WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_NoPreviousWithdrawals(uint40,uint128) (runs: 50, μ: 450939, ~: 451827) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_RevertGiven_Null() (gas: 12009) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf() (gas: 364842) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_NoPreviousWithdrawals() (gas: 338486) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StartTimeInThePresent() (gas: 333040) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusDepleted() (gas: 341300) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusPending() (gas: 329788) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StatusSettled() (gas: 336256) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusCanceled() (gas: 370722) +WithdrawableAmountOf_LockupTranched_Integration_Concrete_Test:test_WithdrawableAmountOf_StreamHasBeenCanceled_StatusDepleted() (gas: 372857) +WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf(uint40,uint128) (runs: 50, μ: 329755, ~: 329375) +WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test:testFuzz_WithdrawableAmountOf_NoPreviousWithdrawals(uint40) (runs: 50, μ: 304445, ~: 304467) \ No newline at end of file diff --git a/.solhint.json b/.solhint.json index a40b9ff6b..d9bf4b91a 100644 --- a/.solhint.json +++ b/.solhint.json @@ -9,7 +9,7 @@ "func-name-mixedcase": "off", "func-visibility": ["error", { "ignoreConstructors": true }], "gas-custom-errors": "off", - "max-line-length": ["error", 123], + "max-line-length": ["error", 124], "named-parameters-mapping": "warn", "no-empty-blocks": "off", "not-rely-on-time": "off", diff --git a/bun.lockb b/bun.lockb index 73c05be7a..294955172 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/foundry.toml b/foundry.toml index 237a2d1a3..1a693ed6d 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,12 +2,12 @@ auto_detect_solc = false bytecode_hash = "none" emv_version = "paris" - extra_output = ['storageLayout'] + extra_output = ["storageLayout"] ffi = true fs_permissions = [ - { access = "read", path = "out-optimized" }, { access = "read", path = "./out" }, - { access = "read-write", path = "./cache" } + { access = "read", path = "./out-optimized" }, + { access = "read-write", path = "./cache" }, ] gas_reports = [ "SablierV2LockupDynamic", diff --git a/package.json b/package.json index 4b86d328a..c7dd297e8 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,11 @@ "url": "https://github.com/sablier-labs/v2-core/issues" }, "dependencies": { - "@openzeppelin/contracts": "5.0.0", - "@prb/math": "github:PaulRBerg/prb-math#a111d11" + "@openzeppelin/contracts": "5.0.2", + "@prb/math": "github:PaulRBerg/prb-math#16419e5" }, "devDependencies": { - "@sphinx-labs/plugins": "^0.30.6", + "@sphinx-labs/plugins": "^0.31.2", "forge-std": "github:foundry-rs/forge-std#v1.8.1", "prettier": "^2.8.8", "solady": "0.0.129", @@ -67,7 +67,7 @@ "gas:snapshot": "forge snapshot --mp \"./test/integration/**/*.sol\" --nmt \"test(Fuzz)?_RevertWhen_\\w{1,}?\"", "gas:snapshot:optimized": "bun run build:optimized && FOUNDRY_PROFILE=test-optimized forge snapshot --mp \"./test/integration/**/*.sol\" --nmt \"test(Fork)?(Fuzz)?_RevertWhen_\\w{1,}?\"", "lint": "bun run lint:sol && bun run prettier:check", - "lint:sol": "forge fmt --check && bun solhint \"{script,src,test}/**/*.sol\"", + "lint:sol": "forge fmt --check && bun solhint \"{precompiles,script,src,test}/**/*.sol\"", "prepack": "bun install && bash ./shell/prepare-artifacts.sh", "prettier:check": "prettier --check \"**/*.{json,md,svg,yml}\"", "prettier:write": "prettier --write \"**/*.{json,md,svg,yml}\"", diff --git a/precompiles/Precompiles.sol b/precompiles/Precompiles.sol index 3acf8d3fb..105bf4add 100644 --- a/precompiles/Precompiles.sol +++ b/precompiles/Precompiles.sol @@ -18,20 +18,21 @@ contract Precompiles { CONSTANTS //////////////////////////////////////////////////////////////////////////*/ - uint256 internal constant MAX_COUNT = 500; + uint256 internal constant MAX_SEGMENT_COUNT = 500; + uint256 internal constant MAX_TRANCHE_COUNT = 500; /*////////////////////////////////////////////////////////////////////////// BYTECODES //////////////////////////////////////////////////////////////////////////*/ bytes public constant BYTECODE_LOCKUP_DYNAMIC = - hex"60c034620003dc576001600160401b0390601f601f1962005a3a3881900383810183168501919086831186841017620002f557808692606094604052833981010312620003dc5782516001600160a01b038082169590929091869003620003dc5760209485810151938416809403620003dc57604001519362000081620003e1565b95601d87527f5361626c696572205632204c6f636b75702044796e616d6963204e465400000081880152620000b5620003e1565b90601182527029a0a116ab1916a627a1a5aaa816a22ca760791b81830152306080528751858111620002f5576001988954908a82811c92168015620003d1575b84831014620002d45781868493116200037b575b50839086831160011462000317576000926200030b575b5050600019600383901b1c191690891b1788555b8151948511620002f557600254938885811c95168015620002ea575b82861014620002d457848487961162000277575b50819385116001146200020d57505060009262000201575b5050600019600383901b1c191690841b176002555b60018060a01b03198481600054161760005560085416176008556040519260007fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a360a0526007556156389081620004028239608051816139a6015260a051818181610c9f0152613a6d0152f35b0151905038806200017c565b88959392919316600260005283600020936000905b8282106200025d575050841162000243575b505050811b0160025562000191565b015160001960f88460031b161c1916905538808062000234565b8484015186558a9790950194938401939081019062000222565b9091929394506002600052826000208580880160051c820192858910620002ca575b9188978c9297969594930160051c01915b828110620002ba57505062000164565b600081558897508b9101620002aa565b9250819262000299565b634e487b7160e01b600052602260045260246000fd5b94607f169462000150565b634e487b7160e01b600052604160045260246000fd5b01519050388062000120565b90878c94169184600052856000209260005b878282106200036457505084116200034a575b505050811b01885562000134565b015160001960f88460031b161c191690553880806200033c565b8385015186558f9790950194938401930162000329565b9091508a600052836000208680850160051c820192868610620003c7575b918d91869594930160051c01915b828110620003b757505062000109565b600081558594508d9101620003a7565b9250819262000399565b91607f1691620000f5565b600080fd5b60408051919082016001600160401b03811183821017620002f55760405256fe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a7146126dc57508063027b6744146126b957806306fdde03146125f3578063081812fc146125d5578063095ea7b3146124d45780631400ecec1461242f5780631c1cdd4c146123c95780631e99d569146123ab57806323b872dd1461239457806331df3d481461228857806340e58ee514611f8e578063425d30dd14611f3a57806342842e0e14611f0057806342966c6814611d245780634426757014611cfd5780634857501f14611c875780634869e12d14611c4b5780634cc55e1114611b5057806354c02292146118cb5780636352211e1461189c5780636d0cee751461189c57806370a082311461182b57806375829def146117995780637cad6cd11461169e5780637de6b1db146114865780638659c27014611125578063894e9a0d14610d985780638f69b99314610d155780639067b67714610cc25780639188ec8414610c8757806395d89b4114610b77578063a22cb46514610aba578063a80fc07114610a65578063ad35efd414610a02578063b2564569146109ae578063b637b86514610951578063b88d4fde146108c8578063b8a3be6614610891578063b971302a1461083f578063bc2be1be146107ec578063c156a11d146106a8578063c87b56dd14610593578063cc364f48146104f9578063d4dbd20b146104a4578063d511609f14610455578063d975dfed14610408578063e985e9c5146103b1578063ea5ead1914610383578063eac8f5b81461032e578063f590c176146102c9578063f851a440146102a25763fdd46d601461025b57600080fd5b3461029d57606036600319011261029d57610274612809565b6044356001600160801b038116810361029d5761029b9161029361399c565b6004356133a6565b005b600080fd5b3461029d57600036600319011261029d5760206001600160a01b0360005416604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060406000205460f81c6040519015158152f35b6024906040519062b8e7e760e51b82526004820152fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160a01b0360016040600020015416604051908152f35b3461029d57604036600319011261029d5761029b6004356103a2612809565b6103ab82614242565b91612ffb565b3461029d57604036600319011261029d576103ca6127f3565b6103d2612809565b906001600160a01b03809116600052600660205260406000209116600052602052602060ff604060002054166040519015158152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610444602091614242565b6001600160801b0360405191168152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060026040600020015460801c604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160801b0360036040600020015416604051908152f35b3461029d57602036600319011261029d576004356000602060405161051d81612943565b828152015280600052600960205260ff60016040600020015460a81c16156103175760005260096020526040806000205464ffffffffff82519161056083612943565b818160a01c16835260c81c166020820152610591825180926020908164ffffffffff91828151168552015116910152565bf35b3461029d5760208060031936011261029d57600435906105b282613735565b5060006001600160a01b0360085416926044604051809581937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa91821561069c57600092610623575b5061061f6040519282849384528301906127ce565b0390f35b9091503d806000833e6106368183612990565b810190828183031261029d5780519067ffffffffffffffff821161029d570181601f8201121561029d57805161066b816129b2565b926106796040519485612990565b81845284828401011161029d57610695918480850191016127ab565b908261060a565b6040513d6000823e3d90fd5b3461029d57604036600319011261029d576004356106c4612809565b6106cc61399c565b81600052600960205260ff60016040600020015460a81c16156107d5578160005260036020526001600160a01b038060406000205416918233036107b65761071384614242565b6001600160801b0381166107a5575b508181161561078d578361073591613857565b908116806107555760248460405190637e27328960e01b82526004820152fd5b820361075d57005b6040516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b6024604051633250574960e11b815260006004820152fd5b6107b0908486612ffb565b84610722565b60405163216caf0d60e01b815260048101859052336024820152604490fd5b6024826040519062b8e7e760e51b82526004820152fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602064ffffffffff60406000205460a01c16604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160a01b0360406000205416604051908152f35b3461029d57602036600319011261029d576004356000526009602052602060ff60016040600020015460a81c166040519015158152f35b3461029d57608036600319011261029d576108e16127f3565b6108e9612809565b6064359167ffffffffffffffff831161029d573660238401121561029d57826004013591610916836129b2565b926109246040519485612990565b808452366024828701011161029d57602081600092602461029b9801838801378501015260443591612e87565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600a60205261061f61099a6040600020612df7565b604051918291602083526020830190612899565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060ff60016040600020015460b01c166040519015158152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610a3c906137d0565b6040516005821015610a4f576020918152f35b634e487b7160e01b600052602160045260246000fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160801b0360026040600020015416604051908152f35b3461029d57604036600319011261029d57610ad36127f3565b6024359081151580920361029d576001600160a01b0316908115610b4657336000526006602052604060002082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b602482604051907f5b08ba180000000000000000000000000000000000000000000000000000000082526004820152fd5b3461029d57600036600319011261029d5760405160006002549060018260011c9160018416918215610c7d575b6020948585108414610c67578587948686529182600014610c47575050600114610bea575b50610bd692500383612990565b61061f6040519282849384528301906127ce565b84915060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace906000915b858310610c2f575050610bd6935082010185610bc9565b80548389018501528794508693909201918101610c18565b60ff191685820152610bd695151560051b8501019250879150610bc99050565b634e487b7160e01b600052602260045260246000fd5b92607f1692610ba4565b3461029d57600036600319011261029d5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602064ffffffffff60406000205460c81c16604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610d4f906137d0565b600581101580610a4f5760028214908115610d8b575b8115610d79575b6020826040519015158152f35b9050610a4f5760046020911482610d6c565b5050600381146000610d65565b3461029d57602036600319011261029d57604051610180810181811067ffffffffffffffff8211176110eb576060916101609160405260008152600060208201526000604082015260008382015260006080820152600060a0820152600060c0820152600060e082015260006101008201526000610120820152610e1a612da4565b6101408201520152600435600052600960205260ff60016040600020015460a81c161561110d5760043560005260096020526040600020610eeb600260405192610e6384612973565b80546001600160a01b038116855264ffffffffff8160a01c16602086015264ffffffffff8160c81c16604086015260ff8160f01c161515606086015260f81c1515608085015260ff60018201546001600160a01b03811660a0870152818160a01c16151560c0870152818160a81c16151560e087015260b01c16151561010085015201612dc3565b610120820152610efc6004356137d0565b6005811015610a4f57600214611101575b610120810151906001600160a01b0360a0820151169164ffffffffff6040830151166060830151151591610100840151151560c0850151151560e086015115159060043560005260036020526001600160a01b036040600020541697600a6020526040600020956001600160a01b0389511697608064ffffffffff60208c0151169a01511515916040519a8b67ffffffffffffffff6101808281810110920111176110eb576101609c610ffe9b6101808e016040528d5260208d015260408c015260608b015260808a015260a089015260c088015260e0870152610100860152610120850152610140840152612df7565b8282015261061f604051928392602084526001600160a01b0381511660208501526001600160a01b03602082015116604085015264ffffffffff604082015116606085015264ffffffffff60608201511660808501526080810151151560a085015260a0810151151560c08501526001600160a01b0360c08201511660e085015260e081015115156101008501526101008101511515610120850152610120810151151561014085015261014081015160406001600160801b03918281511685880152826020820151166101808801520151166101a085015201516101c0808401526101e0830190612899565b634e487b7160e01b600052604160045260246000fd5b60006060820152610f0d565b602460405162b8e7e760e51b81526004356004820152fd5b3461029d5760208060031936011261029d5760043567ffffffffffffffff811161029d57611157903690600401612868565b9061116061399c565b6000915b80831061116d57005b611178838284612d49565b359261118261399c565b83600052600980865260ff90600182816040600020015460a81c161561146f57866000528188526040600020838282015460a01c166000146111d65760248860405190634a5541ef60e01b82526004820152fd5b969495965460f81c611457576112028560005260096020526001600160a01b0360406000205416331490565b156114385761121085613758565b91856000528089526112286002604060002001612dc3565b926001600160801b03948585511686831610156114205787600052828b5260406000205460f01c16156114085780858b6112686112729483895116612a06565b9601511690612a06565b86600052818a528960406000207f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa50815496600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89161783558a6113578a8716998a156113ef575b60038096019b84169b8c6fffffffffffffffffffffffffffffffff198254161790556001600160a01b03809116998a9688528160406000205416998a985260406000200154169661132d8c878a61467f565b60405193849384916040919493606084019584526001600160801b03809216602085015216910152565b0390a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce789604051888152a1803b61139a575b5050505060019150019190611164565b803b1561029d5760019560006084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af16113e0575b80808061138a565b6113e99061295f565b856113d8565b898601600160a01b60ff60a01b198254161790556112db565b602487604051906339c6dc7360e21b82526004820152fd5b602488604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b815260048101869052336024820152604490fd5b6024856040519063fe19f19f60e01b82526004820152fd5b6024876040519062b8e7e760e51b82526004820152fd5b3461029d5760208060031936011261029d57600435906114a461399c565b816000526009815260ff60016040600020015460a81c16156107d5576114c9826137d0565b6005811015610a4f57600481036114f25760248360405190634a5541ef60e01b82526004820152fd5b60038103611512576024836040519063fe19f19f60e01b82526004820152fd5b600214611686576115398260005260096020526001600160a01b0360406000205416331490565b1561166757816000526009815260ff60406000205460f01c161561164f578160005260098152604060002060ff60f01b19815416905560405191807f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f600080a2600382526001600160a01b036040600020541692833b6115e0575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78383604051908152a1005b833b1561029d57600081602481837ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7987f450154640000000000000000000000000000000000000000000000000000000083528760048401525af1156115b4576116499061295f565b836115b4565b602482604051906339c6dc7360e21b82526004820152fd5b60405163216caf0d60e01b815260048101839052336024820152604490fd5b602482604051906322cad1af60e11b82526004820152fd5b3461029d57602036600319011261029d576004356001600160a01b039081811680910361029d578160005416338103611770575060085491816001600160a01b03198416176008556040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a2600754600019810190811161175a5760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a1005b634e487b7160e01b600052601160045260246000fd5b6040516331b339a960e21b81526001600160a01b03919091166004820152336024820152604490fd5b3461029d57602036600319011261029d576117b26127f3565b6000546001600160a01b0380821692338403611804576001600160a01b03199350169182911617600055337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf80600080a3005b6040516331b339a960e21b81526001600160a01b0385166004820152336024820152604490fd5b3461029d57602036600319011261029d576001600160a01b0361184c6127f3565b16801561186b5760005260046020526020604060002054604051908152f35b60246040517f89c62b6400000000000000000000000000000000000000000000000000000000815260006004820152fd5b3461029d57602036600319011261029d5760206118ba600435613735565b6001600160a01b0360405191168152f35b3461029d576020600319818136011261029d5760043567ffffffffffffffff9182821161029d576101208236039182011261029d5761190861399c565b60c4820135906022190181121561029d57810160048101359083821161029d57602401606082023603811361029d57611942913691612c7a565b9182519161194f83612c62565b9261195d6040519485612990565b808452601f1961196c82612c62565b018660005b828110611b3a5750505064ffffffffff90814216936001600160801b039687611999826139f8565b515116828a6119a7846139f8565b51015116858060406119b8866139f8565b5101511689011690604051926119cd84612927565b83528b83015260408201526119e1886139f8565b526119eb876139f8565b506001938760015b8a8c878310611ab95790838b8b611a0c81600401612d83565b92611a1960248301612d83565b92611a2660448401612d6f565b946064840135946001600160a01b039586811680910361029d57611ab198611a7198611aa698611a5860848a01612d97565b9481611a6660a48c01612d97565b976040519d8e61290a565b168c52168c8b0152166040890152606088015215156080870152151560a086015260c085015260e084015260e4369101612d1a565b610100820152613a19565b604051908152f35b889385806040611aed8b86611add8a8e9a611ad4828d613a05565b5151169a613a05565b5101511694600019890190613a05565b51015116816040611afe888c613a05565b5101511601169160405193611b1285612927565b84528301526040820152611b26828c613a05565b52611b31818b613a05565b500188906119f3565b611b42612da4565b828289010152018790611971565b3461029d57604036600319011261029d5767ffffffffffffffff60043581811161029d57611b82903690600401612868565b9160243590811161029d57611b9b903690600401612868565b9091611ba561399c565b818403611c145760005b848110611bb857005b80611c0e611bc96001938886612d49565b35611bd5838987612d49565b3560005260036020526001600160a01b0360406000205416611c00611bfb85898b612d49565b612d6f565b91611c0961399c565b6133a6565b01611baf565b60448483604051917faec9344000000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610444602091614197565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000611cc3826137d0565b6005811015610a4f57600203611ce1575b6020906040519015158152f35b506000526009602052602060ff60406000205460f01c16611cd4565b3461029d57600036600319011261029d5760206001600160a01b0360085416604051908152f35b3461029d5760208060031936011261029d5760043590611d4261399c565b816000526009815260ff60016040600020015460a81c16156107d557816000526009815260ff60016040600020015460a01c1615611ecf57611d838261412e565b156116675781600052600381526001600160a01b0380604060002054166009835260ff60016040600020015460b01c16159081611ec5575b5080611ebd575b611ea5577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790836000526003835260406000205416918215928315611e6a575b846000526003825260406000206001600160a01b03198154169055846000604051927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4848152a1611e5257005b60249060405190637e27328960e01b82526004820152fd5b611e8b85600052600560205260406000206001600160a01b03198154169055565b806000526004825260406000206000198154019055611e02565b60248360405190630da9b01360e01b82526004820152fd5b506000611dc2565b9050151584611dbb565b602482604051907f817cd6390000000000000000000000000000000000000000000000000000000082526004820152fd5b3461029d57611f0e36612833565b60405191602083019383851067ffffffffffffffff8611176110eb5761029b9460405260008452612e87565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060ff60016040600020015460a01c166040519015158152f35b3461029d5760208060031936011261029d5760043590611fac61399c565b8160005260099081815260ff60016040600020015460a81c16156122715782600052818152604060002060ff600182015460a01c166000146120005760248460405190634a5541ef60e01b82526004820152fd5b5460f81c612259576120288360005260096020526001600160a01b0360406000205416331490565b1561223a5761203683613758565b928060005282825261204e6002604060002001612dc3565b916001600160801b0394858451168682161015612222578260005284825260ff60406000205460f01c161561220a57816120df82888796956120d57ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce796837f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa509b5116612a06565b9701511690612a06565b9383600052868252604060002096875495600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff881617895560038a8216998a156121f0575b01998316998a6fffffffffffffffffffffffffffffffff198254161790556001600160a01b03809716978891600386528860406000205416988994875260016040600020015416946121798d858861467f565b604080518a81526001600160801b0392831660208201529290911690820152606090a4604051838152a1813b6121ab57005b813b1561029d5760006084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af16121e757005b61029b9061295f565b60018101600160a01b60ff60a01b19825416179055612126565b602483604051906339c6dc7360e21b82526004820152fd5b602483604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b815260048101849052336024820152604490fd5b6024836040519063fe19f19f60e01b82526004820152fd5b6024836040519062b8e7e760e51b82526004820152fd5b3461029d5760031960203682011261029d5760043567ffffffffffffffff9182821161029d5761014090823603011261029d576122c361399c565b604051916122d08361290a565b6122dc8260040161281f565b83526122ea6024830161281f565b60208401526122fb604483016129ce565b604084015260648201356001600160a01b038116810361029d576060840152612326608483016128fd565b608084015261233760a483016128fd565b60a084015261234860c48301612c50565b60c084015260e482013590811161029d578101913660238401121561029d57611aa6611ab1926123846020953690602460048201359101612c7a565b60e0840152610104369101612d1a565b3461029d5761029b6123a536612833565b91612a1f565b3461029d57600036600319011261029d576020600754604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757612403906137d0565b6005811015610a4f578060209115908115612424575b506040519015158152f35b600191501482612419565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576020906000908060005260098352604060002060ff815460f01c16806124c2575b612499575b50506001600160801b0360405191168152f35b6124bb92506001600160801b0360026124b59201541691613758565b90612a06565b8280612486565b5060ff600182015460a01c1615612481565b3461029d57604036600319011261029d576124ed6127f3565b6024356124f981613735565b331515806125c2575b80612594575b6125645781906001600160a01b03809416938491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a460005260056020526040600020906001600160a01b0319825416179055600080f35b60246040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152336004820152fd5b506001600160a01b038116600052600660205260406000203360005260205260ff6040600020541615612508565b50336001600160a01b0382161415612502565b3461029d57602036600319011261029d5760206118ba6004356129e2565b3461029d57600036600319011261029d576040516000600190600154918260011c91600184169182156126af575b6020948585108414610c67578587948686529182600014610c475750506001146126525750610bd692500383612990565b84915060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6906000915b858310612697575050610bd6935082010185610bc9565b80548389018501528794508693909201918101612680565b92607f1692612621565b3461029d57600036600319011261029d57602060405167016345785d8a00008152f35b3461029d57602036600319011261029d57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361029d57817f80ac58cd0000000000000000000000000000000000000000000000000000000060209314908115612781575b8115612757575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483612750565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150612749565b60005b8381106127be5750506000910152565b81810151838201526020016127ae565b906020916127e7815180928185528580860191016127ab565b601f01601f1916010190565b600435906001600160a01b038216820361029d57565b602435906001600160a01b038216820361029d57565b35906001600160a01b038216820361029d57565b606090600319011261029d576001600160a01b0390600435828116810361029d5791602435908116810361029d579060443590565b9181601f8401121561029d5782359167ffffffffffffffff831161029d576020808501948460051b01011161029d57565b90815180825260208080930193019160005b8281106128b9575050505090565b835180516001600160801b031686528083015167ffffffffffffffff168684015260409081015164ffffffffff1690860152606090940193928101926001016128ab565b3590811515820361029d57565b610120810190811067ffffffffffffffff8211176110eb57604052565b6060810190811067ffffffffffffffff8211176110eb57604052565b6040810190811067ffffffffffffffff8211176110eb57604052565b67ffffffffffffffff81116110eb57604052565b610140810190811067ffffffffffffffff8211176110eb57604052565b90601f8019910116810190811067ffffffffffffffff8211176110eb57604052565b67ffffffffffffffff81116110eb57601f01601f191660200190565b35906001600160801b038216820361029d57565b6129eb81613735565b5060005260056020526001600160a01b036040600020541690565b6001600160801b03918216908216039190821161175a57565b906001600160a01b03809116801561078d57600091848352602091600383526040928284862054166009825260ff6001868820015460b01c16159081612c46575b5080612c3e575b612c27578685526003815282848620541694873315159384612b77575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7945087612b3f575b808352600484528683206001815401905581835260038452868320816001600160a01b0319825416179055877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef88519480a4878152a183168203612b115750505050565b516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b612b6082600052600560205260406000206001600160a01b03198154169055565b878352600484528683208054600019019055612aad565b91929380915090612be6575b15612b915790878392612a84565b848887612bae576024915190637e27328960e01b82526004820152fd5b90517f177e802f0000000000000000000000000000000000000000000000000000000081523360048201526024810191909152604490fd5b503386148015612c0b575b80612b835750878252600583523384868420541614612b83565b5085825260068352848220338352835260ff8583205416612bf1565b602487855190630da9b01360e01b82526004820152fd5b506001612a67565b9050151538612a60565b359064ffffffffff8216820361029d57565b67ffffffffffffffff81116110eb5760051b60200190565b929192612c8682612c62565b604094612c966040519283612990565b8195848352602080930191606080960285019481861161029d57925b858410612cc25750505050505050565b868483031261029d57825190612cd782612927565b612ce0856129ce565b8252858501359067ffffffffffffffff8216820361029d57828792838b950152612d0b868801612c50565b86820152815201930192612cb2565b919082604091031261029d57604051612d3281612943565b6020808294612d408161281f565b84520135910152565b9190811015612d595760051b0190565b634e487b7160e01b600052603260045260246000fd5b356001600160801b038116810361029d5790565b356001600160a01b038116810361029d5790565b35801515810361029d5790565b60405190612db182612927565b60006040838281528260208201520152565b90604051612dd081612927565b6040819360018154916001600160801b0392838116865260801c6020860152015416910152565b908154612e0381612c62565b92604093612e146040519182612990565b82815280946020809201926000526020600020906000935b858510612e3b57505050505050565b60018481928451612e4b81612927565b64ffffffffff87546001600160801b038116835267ffffffffffffffff8160801c168584015260c01c1686820152815201930194019391612e2c565b9190612e94828285612a1f565b803b612ea1575b50505050565b612efd6001600160a01b03809216946040519384937f150b7a02000000000000000000000000000000000000000000000000000000009687865233600487015216602485015260448401526080606484015260848301906127ce565b03906020816000938185885af190829082612f93575b5050612f4a5782612f22614212565b8051919082612f435760248260405190633250574960e11b82526004820152fd5b9050602001fd5b7fffffffff000000000000000000000000000000000000000000000000000000001603612f7b575038808080612e9b565b60249060405190633250574960e11b82526004820152fd5b909192506020813d602011612ff3575b81612fb060209383612990565b81010312612fef5751907fffffffff0000000000000000000000000000000000000000000000000000000082168203612fec5750903880612f13565b80fd5b5080fd5b3d9150612fa3565b9291909261300761399c565b60009381855260099260209380855260409260ff6001858a20015460a81c16156133905784885281865260ff6001858a20015460a01c16613379576001600160a01b0391828216928315613369576001600160801b039384861691821561335257888c5260038a5280888d205416938483141580613342575b61331f5761308d8a614242565b87811685116132ee57508a8a928e928484528083528b8085209a8c848d54169c6002015460801c906130be9161426a565b878752838652828720600201908282549160801b6fffffffffffffffffffffffffffffffff191691161781556130f390612dc3565b90808683015116918184818351169201511661310e91612a06565b161115946001927f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d966132c1575b8782528552200154169461315181898861467f565b8a51908152a480331415806132b7575b613252575b823314159081613247575b8161323c575b506131ab575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce793945051908152a1565b813b15613238578351636fd110e960e01b8152600481018690523360248201526001600160a01b0390911660448201526001600160801b03909216606483015294957ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79582908183816084810103925af1613229575b85948161317d565b6132329061295f565b38613221565b8780fd5b905082141538613177565b833b15159150613171565b803b156132b3578451636fd110e960e01b8152600481018790523360248201526001600160a01b03831660448201526001600160801b0385166064820152898160848183865af16132a4575b50613166565b6132ad9061295f565b3861329e565b8880fd5b50803b1515613161565b878252808652828220848101600160a01b60ff60a01b1982541617905560ff60f01b19815416905561313c565b895163287ecaef60e21b8152600481018c90526001600160801b038a81166024830152919091166044820152606490fd5b60648a848b519163b34359d360e01b835260048301523360248301526044820152fd5b5061334c8a61412e565b15613080565b60248989519063d2aabcd960e01b82526004820152fd5b6004865163630d074f60e11b8152fd5b602485855190634a5541ef60e01b82526004820152fd5b60248585519062b8e7e760e51b82526004820152fd5b9291909260009381855260099060209382855260409260ff6001858a20015460a81c1615613390578785815281875260ff6001868320015460a01c1661371e576001600160a01b039081851692831561370e576001600160801b03938486169182156136f75789845260038b528489852054169485831415806136e7575b6136c45761344b8b838e61343783614197565b9289525260028c8820015460801c90612a06565b87811685116136935750908b8b928387528282528b808820998b838c54169b6002015460801c9061347b9161426a565b868a52858552828a20600201908282549160801b6fffffffffffffffffffffffffffffffff191691161781556134b090612dc3565b818086830151169381835116920151166134c991612a06565b161115927f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d93613665575b848852825260018c88200154169461350d818c8861467f565b8b51908152a4813314158061365b575b6135f5575b508133141590816135ea575b816135df575b50613567575050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce793945051908152a1565b908188923b156135db578451636fd110e960e01b8152600481018790523360248201526001600160a01b0390941660448501526001600160801b03909116606484015282908183816084810103925af16135c3575b808061317d565b6135cd869161295f565b6135d757846135bc565b8480fd5b8280fd5b905081141538613534565b823b1515915061352e565b813b15612fec578551636fd110e960e01b8152600481018890523360248201526001600160a01b03861660448201526001600160801b0385166064820152818160848183875af1613647575b50613522565b61365391929a5061295f565b973880613641565b50813b151561351d565b8488528083528c882060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556134f4565b8a5163287ecaef60e21b8152600481018d90526001600160801b038a81166024830152919091166044820152606490fd5b60648b848c519163b34359d360e01b835260048301523360248301526044820152fd5b506136f18b61412e565b15613424565b60248a8a519063d2aabcd960e01b82526004820152fd5b6004875163630d074f60e11b8152fd5b602486865190634a5541ef60e01b82526004820152fd5b8060005260036020526001600160a01b0360406000205416908115611e52575090565b64ffffffffff804216826000526009602052604060002091825482828260a01c1610156137c65760c81c1611156137b45750600a6020526001604060002054116000146137ab576137a890614356565b90565b6137a890614285565b6001600160801b039150600201541690565b5050505050600090565b806000526009602052604060002060ff600182015460a01c166000146137f7575050600490565b805460f81c613850575460a01c64ffffffffff16421061384a5761381a81613758565b9060005260096020526001600160801b03806002604060002001541691161060001461384557600190565b600290565b50600090565b5050600390565b916000828152602090600382526001600160a01b036040958187842054166009855260ff6001898620015460b01c16159081613992575b5080613987575b613970579480967ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79596828552600386527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84838720541694859283613938575b169283613922575b84875260038852808720846001600160a01b0319825416179055519580a4948152a1565b83875260048852808720600181540190556138fe565b61395986600052600560205260406000206001600160a01b03198154169055565b8388526004895284882080546000190190556138f6565b602486885190630da9b01360e01b82526004820152fd5b508181161515613895565b905015153861388e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036139ce57565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b805115612d595760200190565b8051821015612d595760209160051b010190565b90613a3b6001600160801b036040840151166020610100850151015190614535565b6001600160801b0381511660e084015164ffffffffff60c08601511682156141045780156140da57815180156140b0577f0000000000000000000000000000000000000000000000000000000000000000811161407f575064ffffffffff6040613aa4846139f8565b510151168110156140285750600090819082815184905b808210613f97575050505064ffffffffff421664ffffffffff8216811015613f575750506001600160801b0316808203613f20575050600754928360005260096020526040600020916001600160801b0381511660028401906fffffffffffffffffffffffffffffffff198254161790556001600160a01b036060830151166001840154750100000000000000000000000000000000000000000060808501511515918654937fffffffffffffffffff0000ff000000000000000000000000000000000000000076ff0000000000000000000000000000000000000000000060a0890151151560b01b16921617171760018601556001600160a01b0384511678ffffffffff000000000000000000000000000000000000000060c086015160a01b169060e0860151937fff000000000000000000000000000000000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007dffffffffff000000000000000000000000000000000000000000000000006040613c578951996000198b0190613a05565b51015160c81b169560f01b16911617171717845560005b818110613e4e575050600185016007556001600160a01b03602083015116801561078d57613ca4866001600160a01b0392613857565b16613e1d57613ccf6001600160a01b036060840151166001600160801b03835116903090339061460e565b6001600160801b0360208201511680613ded575b507f33eb09bbf19ea3fb22c760d5164234f8bf62ca07dcf5a437ad389e96b0bd644360206001600160a01b03845116926001600160a01b038286015116946001600160a01b0360608201511696613de2613dc360808401511515928c60a086015115156001600160a01b0361010060e089015194549864ffffffffff6040519a613d6c8c612943565b818160a01c168c5260c81c168c8b015201515116956001600160801b036040519a8b9a610140958c5233828d01528281511660408d015201511660608a0152608089015260a08801528060c0880152860190612899565b9260e08501906020908164ffffffffff91828151168552015116910152565b6101208301520390a4565b613e17906001600160a01b036060850151166001600160a01b03610100860151511690339061460e565b38613ce3565b60246040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260006004820152fd5b86600052600a602052604060002090613e6b8160e0870151613a05565b518254680100000000000000008110156110eb5760018101808555811015612d5957600193600052602060002001906001600160801b03815116908254917fffffff00000000000000000000000000000000000000000000000000000000007cffffffffff000000000000000000000000000000000000000000000000604077ffffffffffffffff00000000000000000000000000000000602086015160801b1694015160c01b169316171717905501613c6e565b60449250604051917fd90b7e3900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b6040517f210aec0e00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b9193509193613fbb906001600160801b03613fb28588613a05565b5151169061426a565b9364ffffffffff806040613fcf8685613a05565b51015116941680851115613feb57506001849301909291613abb565b8385606492604051927f9588ac09000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b64ffffffffff6040614039846139f8565b5101516040517ff539a17c00000000000000000000000000000000000000000000000000000000815264ffffffffff938416600482015291169091166024820152604490fd5b602490604051907f4757689b0000000000000000000000000000000000000000000000000000000082526004820152fd5b60046040517f3952c64e000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd572dbcb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6095d3bc000000000000000000000000000000000000000000000000000000008152fd5b60009080825260036020526001600160a01b038060408420541692833314938415614173575b5050821561416157505090565b90915061416e33926129e2565b161490565b60ff9294509060409181526006602052818120338252602052205416913880614154565b8060005260096020526141b06002604060002001612dc3565b816000526009602052604060002060ff600182015460a01c166000146141e357506001600160801b039150602001511690565b5460f81c6141f557506137a890613758565b6137a891506001600160801b036040818351169201511690612a06565b3d1561423d573d90614223826129b2565b916142316040519384612990565b82523d6000602084013e565b606090565b6137a89061424f81614197565b90600052600960205260026040600020015460801c90612a06565b9190916001600160801b038080941691160191821161175a57565b64ffffffffff6142ba600091838352600960205280806040852054818160a01c1693849160c81c1603169181421603166146d9565b91808252600a602052604082208054156143425790829167ffffffffffffffff93526143146020832054828452600960205261430f6001600160801b03968760026040882001541696879360801c16906147c9565b614837565b92831361432a57505061432690614921565b1690565b60029350604092508152600960205220015460801c90565b602483634e487b7160e01b81526032600452fd5b64ffffffffff804216600083815260096020526040918282209083519161437c83612973565b80549661012061440260026001600160a01b0394858c168852602088019b8b8160a01c168d528b8160c81c168b8a015260ff8160f01c16151560608a015260f81c1515608089015260ff600196600183015490811660a08b0152818160a01c16151560c08b0152818160a81c16151560e08b015260b01c16151561010089015201612dc3565b94019384528452600a602052614419858520612df7565b9184968087614427866139f8565b5101511692828288955b16106144ff5750916144a561430f928488816144aa98976001600160801b039e8f61445c898c613a05565b5151169d8e9a67ffffffffffffffff60206144778c84613a05565b510151169984836144888385613a05565b510151169650806144e457505050511680925b03169203166146d9565b6147c9565b9283136144c35750506144bd8391614921565b16011690565b5160200151929392831692841683101591506144df9050575090565b905090565b6144f49293506000190190613a05565b51015116809261449b565b8093986001600160801b0390816145168c89613a05565b51511601169801928282808a61452c888a613a05565b51015116614431565b9190916040519061454582612943565b600091828152826020820152936001600160801b03928383169182156145ef5767016345785d8a00008082116145b857506145818591846154e9565b16602087019281845211156145a45750908261459f92511690612a06565b168252565b80634e487b7160e01b602492526001600452fd5b60449250604051917f4fea5c1a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b509394505050506040519061460382612943565b808252602082015290565b9290604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff8411176110eb5761467d9260405261495d565b565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b0392909216602483015260448083019390935291815261467d916146d4606483612990565b61495d565b600160ff1b8082149081156147bf575b5061479557600081121561478c57614712816000035b60008412156147855783600003906149f9565b917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831161474e57600019911813156147485790565b60000390565b60449250604051917fd49c26b300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b83906149f9565b614712816146ff565b60046040517f9fe2b450000000000000000000000000000000000000000000000000000000008152fd5b90508214386146e9565b806147e457506147df57670de0b6b3a764000090565b600090565b90670de0b6b3a7640000808314614831575080614809575050670de0b6b3a764000090565b670de0b6b3a7640000811461482d576148289061430f6137a893614af3565b614c35565b5090565b91505090565b600160ff1b808214908115614917575b506148ed5760008112156148e457614870816000035b60008412156148dd5783600003906154e9565b917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83116148a657600019911813156147485790565b60449250604051917f120b5b4300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b83906154e9565b6148708161485d565b60046040517fa6070c25000000000000000000000000000000000000000000000000000000008152fd5b9050821438614847565b6000811261492c5790565b602490604051907f2463f3d50000000000000000000000000000000000000000000000000000000082526004820152fd5b6001600160a01b031690614988600080836020829551910182875af1614981614212565b9084615598565b9081519182151592836149d1575b5050506149a05750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312612fef576020015190811591821503612fec5750388080614996565b670de0b6b3a7640000916000198383099280830292838086109503948086039514614ab55782851015614a7957908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b82606492604051927f63a05778000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b505080925015614ac3570490565b634e487b7160e01b600052601260045260246000fd5b8015614ac3576ec097ce7bc90715b34b9f10000000000590565b80600080831315614c0457670de0b6b3a764000092838112614be157506001925b808305906001600160801b03821160071b91821c9167ffffffffffffffff831160061b92831c63ffffffff811160051b90811c61ffff811160041b90811c60ff811160031b90811c91600f831160021b92831c93600197600160038711811b96871c11961717171717171781810294811d90828214614bd557506706f05b59d3b20000905b848213614ba95750505050500290565b808391020590671bc16d674ec80000821215614bc8575b831d90614b99565b8091950194831d90614bc0565b93505093925050020290565b6000199392508015614ac3576ec097ce7bc90715b34b9f10000000000591614b14565b602483604051907f059b101b0000000000000000000000000000000000000000000000000000000082526004820152fd5b6000811215614c645768033dd1780914b9711419811261384a57614c5b90600003614c35565b6137a890614ad9565b680a688906bd8affffff81136154b857670de0b6b3a764000080604092831b05907780000000000000000000000000000000000000000000000067ff00000000000000831661539b575b66ff0000000000008316615293575b65ff00000000008316615193575b64ff00000000831661509b575b63ff0000008316614fab575b62ff00008316614ec3575b61ff008316614de3575b60ff8316614d0c575b02911c60bf031c90565b60808316614dd1575b838316614dbf575b60208316614dad575b60108316614d9b575b60088316614d89575b60048316614d77575b60028316614d65575b6001831615614d02576801000000000000000102831c614d02565b6801000000000000000102831c614d4a565b6801000000000000000302831c614d41565b6801000000000000000602831c614d38565b6801000000000000000b02831c614d2f565b6801000000000000001602831c614d26565b6801000000000000002c02831c614d1d565b6801000000000000005902831c614d15565b6180008316614eb1575b6140008316614e9f575b6120008316614e8d575b6110008316614e7b575b6108008316614e69575b6104008316614e57575b6102008316614e45575b610100831615614cf957680100000000000000b102831c614cf9565b6801000000000000016302831c614e29565b680100000000000002c602831c614e1f565b6801000000000000058c02831c614e15565b68010000000000000b1702831c614e0b565b6801000000000000162e02831c614e01565b68010000000000002c5d02831c614df7565b680100000000000058b902831c614ded565b628000008316614f99575b624000008316614f87575b622000008316614f75575b621000008316614f63575b620800008316614f51575b620400008316614f3f575b620200008316614f2d575b62010000831615614cef576801000000000000b17202831c614cef565b680100000000000162e402831c614f10565b6801000000000002c5c802831c614f05565b68010000000000058b9102831c614efa565b680100000000000b172102831c614eef565b68010000000000162e4302831c614ee4565b680100000000002c5c8602831c614ed9565b6801000000000058b90c02831c614ece565b63800000008316615089575b63400000008316615077575b63200000008316615065575b63100000008316615053575b63080000008316615041575b6304000000831661502f575b6302000000831661501d575b6301000000831615614ce45768010000000000b1721802831c614ce4565b6801000000000162e43002831c614fff565b68010000000002c5c86002831c614ff3565b680100000000058b90c002831c614fe7565b6801000000000b17217f02831c614fdb565b680100000000162e42ff02831c614fcf565b6801000000002c5c85fe02831c614fc3565b68010000000058b90bfc02831c614fb7565b6480000000008316615181575b644000000000831661516f575b642000000000831661515d575b641000000000831661514b575b6408000000008316615139575b6404000000008316615127575b6402000000008316615115575b640100000000831615614cd857680100000000b17217f802831c614cd8565b68010000000162e42ff102831c6150f6565b680100000002c5c85fe302831c6150e9565b6801000000058b90bfce02831c6150dc565b68010000000b17217fbb02831c6150cf565b6801000000162e42fff002831c6150c2565b68010000002c5c8601cc02831c6150b5565b680100000058b90c0b4902831c6150a8565b658000000000008316615281575b65400000000000831661526f575b65200000000000831661525d575b65100000000000831661524b575b650800000000008316615239575b650400000000008316615227575b650200000000008316615215575b65010000000000831615614ccb576801000000b17218355102831c614ccb565b680100000162e430e5a202831c6151f5565b6801000002c5c863b73f02831c6151e7565b68010000058b90cf1e6e02831c6151d9565b680100000b1721bcfc9a02831c6151cb565b68010000162e43f4f83102831c6151bd565b680100002c5c89d5ec6d02831c6151af565b6801000058b91b5bc9ae02831c6151a1565b66800000000000008316615389575b66400000000000008316615377575b66200000000000008316615365575b66100000000000008316615353575b66080000000000008316615341575b6604000000000000831661532f575b6602000000000000831661531d575b6601000000000000831615614cbd5768010000b17255775c0402831c614cbd565b6801000162e525ee054702831c6152fc565b68010002c5cc37da949202831c6152ed565b680100058ba01fb9f96d02831c6152de565b6801000b175effdc76ba02831c6152cf565b680100162f3904051fa102831c6152c0565b6801002c605e2e8cec5002831c6152b1565b68010058c86da1c09ea202831c6152a2565b6780000000000000008316615499575b6740000000000000008316615487575b6720000000000000008316615475575b6710000000000000008316615463575b6708000000000000008316615451575b670400000000000000831661543f575b670200000000000000831661542d575b670100000000000000831615614cae57680100b1afa5abcbed6102831c614cae565b68010163da9fb33356d802831c61540b565b680102c9a3e778060ee702831c6153fb565b6801059b0d31585743ae02831c6153eb565b68010b5586cf9890f62a02831c6153db565b6801172b83c7d517adce02831c6153cb565b6801306fe0a31b7152df02831c6153bb565b5077b504f333f9de6484800000000000000000000000000000006153ab565b602490604051907f0360d0280000000000000000000000000000000000000000000000000000000082526004820152fd5b9091906000198382098382029182808310920391808303921461558757670de0b6b3a7640000908183101561555057947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b60449086604051917f5173648d00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5050670de0b6b3a764000090049150565b906155d757508051156155ad57805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b81511580615622575b6155e8575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b156155e056fea164736f6c6343000817000a"; + hex"60c034620003dc576001600160401b0390601f601f1962005a3c3881900383810183168501919086831186841017620002f557808692606094604052833981010312620003dc5782516001600160a01b038082169590929091869003620003dc5760209485810151938416809403620003dc57604001519362000081620003e1565b95601d87527f5361626c696572205632204c6f636b75702044796e616d6963204e465400000081880152620000b5620003e1565b90601182527029a0a116ab1916a627a1a5aaa816a22ca760791b81830152306080528751858111620002f5576001988954908a82811c92168015620003d1575b84831014620002d45781868493116200037b575b50839086831160011462000317576000926200030b575b5050600019600383901b1c191690891b1788555b8151948511620002f557600254938885811c95168015620002ea575b82861014620002d457848487961162000277575b50819385116001146200020d57505060009262000201575b5050600019600383901b1c191690841b176002555b60018060a01b03198481600054161760005560085416176008556040519260007fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a360a05260075561563a9081620004028239608051816139a8015260a051818181610c9f0152613a6f0152f35b0151905038806200017c565b88959392919316600260005283600020936000905b8282106200025d575050841162000243575b505050811b0160025562000191565b015160001960f88460031b161c1916905538808062000234565b8484015186558a9790950194938401939081019062000222565b9091929394506002600052826000208580880160051c820192858910620002ca575b9188978c9297969594930160051c01915b828110620002ba57505062000164565b600081558897508b9101620002aa565b9250819262000299565b634e487b7160e01b600052602260045260246000fd5b94607f169462000150565b634e487b7160e01b600052604160045260246000fd5b01519050388062000120565b90878c94169184600052856000209260005b878282106200036457505084116200034a575b505050811b01885562000134565b015160001960f88460031b161c191690553880806200033c565b8385015186558f9790950194938401930162000329565b9091508a600052836000208680850160051c820192868610620003c7575b918d91869594930160051c01915b828110620003b757505062000109565b600081558594508d9101620003a7565b9250819262000399565b91607f1691620000f5565b600080fd5b60408051919082016001600160401b03811183821017620002f55760405256fe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a7146126d857508063027b6744146126b557806306fdde03146125ef578063081812fc146125d1578063095ea7b3146124d05780631400ecec1461242b5780631c1cdd4c146123c55780631e99d569146123a757806323b872dd1461239057806331df3d481461228457806340e58ee514611f8a578063425d30dd14611f3657806342842e0e14611efc57806342966c6814611d245780634426757014611cfd5780634857501f14611c875780634869e12d14611c4b5780634cc55e1114611b5057806354c02292146118cb5780636352211e1461189c5780636d0cee751461189c57806370a082311461182b57806375829def146117995780637cad6cd11461169e5780637de6b1db146114865780638659c27014611125578063894e9a0d14610d985780638f69b99314610d155780639067b67714610cc25780639188ec8414610c8757806395d89b4114610b77578063a22cb46514610aba578063a80fc07114610a65578063ad35efd414610a02578063b2564569146109ae578063b637b86514610951578063b88d4fde146108c8578063b8a3be6614610891578063b971302a1461083f578063bc2be1be146107ec578063c156a11d146106a8578063c87b56dd14610593578063cc364f48146104f9578063d4dbd20b146104a4578063d511609f14610455578063d975dfed14610408578063e985e9c5146103b1578063ea5ead1914610383578063eac8f5b81461032e578063f590c176146102c9578063f851a440146102a25763fdd46d601461025b57600080fd5b3461029d57606036600319011261029d57610274612805565b6044356001600160801b038116810361029d5761029b9161029361399e565b6004356133a5565b005b600080fd5b3461029d57600036600319011261029d5760206001600160a01b0360005416604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060406000205460f81c6040519015158152f35b6024906040519062b8e7e760e51b82526004820152fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160a01b0360016040600020015416604051908152f35b3461029d57604036600319011261029d5761029b6004356103a2612805565b6103ab82614244565b91612ff3565b3461029d57604036600319011261029d576103ca6127ef565b6103d2612805565b906001600160a01b03809116600052600660205260406000209116600052602052602060ff604060002054166040519015158152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610444602091614244565b6001600160801b0360405191168152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060026040600020015460801c604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160801b0360036040600020015416604051908152f35b3461029d57602036600319011261029d576004356000602060405161051d8161293f565b828152015280600052600960205260ff60016040600020015460a81c16156103175760005260096020526040806000205464ffffffffff8251916105608361293f565b818160a01c16835260c81c166020820152610591825180926020908164ffffffffff91828151168552015116910152565bf35b3461029d5760208060031936011261029d57600435906105b28261373b565b5060006001600160a01b0360085416926044604051809581937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa91821561069c57600092610623575b5061061f6040519282849384528301906127ca565b0390f35b9091503d806000833e610636818361298c565b810190828183031261029d5780519067ffffffffffffffff821161029d570181601f8201121561029d57805161066b816129ae565b92610679604051948561298c565b81845284828401011161029d57610695918480850191016127a7565b908261060a565b6040513d6000823e3d90fd5b3461029d57604036600319011261029d576004356106c4612805565b6106cc61399e565b81600052600960205260ff60016040600020015460a81c16156107d5578160005260036020526001600160a01b038060406000205416918233036107b65761071384614244565b6001600160801b0381166107a5575b508181161561078d57836107359161385d565b908116806107555760248460405190637e27328960e01b82526004820152fd5b820361075d57005b6040516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b6024604051633250574960e11b815260006004820152fd5b6107b0908486612ff3565b84610722565b60405163216caf0d60e01b815260048101859052336024820152604490fd5b6024826040519062b8e7e760e51b82526004820152fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602064ffffffffff60406000205460a01c16604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160a01b0360406000205416604051908152f35b3461029d57602036600319011261029d576004356000526009602052602060ff60016040600020015460a81c166040519015158152f35b3461029d57608036600319011261029d576108e16127ef565b6108e9612805565b6064359167ffffffffffffffff831161029d573660238401121561029d57826004013591610916836129ae565b92610924604051948561298c565b808452366024828701011161029d57602081600092602461029b9801838801378501015260443591612e7f565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600a60205261061f61099a6040600020612def565b604051918291602083526020830190612895565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060ff60016040600020015460b01c166040519015158152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610a3c906137d6565b6040516005821015610a4f576020918152f35b634e487b7160e01b600052602160045260246000fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757600052600960205260206001600160801b0360026040600020015416604051908152f35b3461029d57604036600319011261029d57610ad36127ef565b6024359081151580920361029d576001600160a01b0316908115610b4657336000526006602052604060002082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b602482604051907f5b08ba180000000000000000000000000000000000000000000000000000000082526004820152fd5b3461029d57600036600319011261029d5760405160006002549060018260011c9160018416918215610c7d575b6020948585108414610c67578587948686529182600014610c47575050600114610bea575b50610bd69250038361298c565b61061f6040519282849384528301906127ca565b84915060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace906000915b858310610c2f575050610bd6935082010185610bc9565b80548389018501528794508693909201918101610c18565b60ff191685820152610bd695151560051b8501019250879150610bc99050565b634e487b7160e01b600052602260045260246000fd5b92607f1692610ba4565b3461029d57600036600319011261029d5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602064ffffffffff60406000205460c81c16604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610d4f906137d6565b600581101580610a4f5760028214908115610d8b575b8115610d79575b6020826040519015158152f35b9050610a4f5760046020911482610d6c565b5050600381146000610d65565b3461029d57602036600319011261029d57604051610180810181811067ffffffffffffffff8211176110eb576060916101609160405260008152600060208201526000604082015260008382015260006080820152600060a0820152600060c0820152600060e082015260006101008201526000610120820152610e1a612d9c565b6101408201520152600435600052600960205260ff60016040600020015460a81c161561110d5760043560005260096020526040600020610eeb600260405192610e638461296f565b80546001600160a01b038116855264ffffffffff8160a01c16602086015264ffffffffff8160c81c16604086015260ff8160f01c161515606086015260f81c1515608085015260ff60018201546001600160a01b03811660a0870152818160a01c16151560c0870152818160a81c16151560e087015260b01c16151561010085015201612dbb565b610120820152610efc6004356137d6565b6005811015610a4f57600214611101575b610120810151906001600160a01b0360a0820151169164ffffffffff604083015116606083015115159160c0840151151560e0850151151561010086015115159160043560005260036020526001600160a01b036040600020541697600a6020526040600020956001600160a01b0389511697608064ffffffffff60208c0151169a01511515916040519a8b67ffffffffffffffff6101808281810110920111176110eb576101609c610ffe9b6101808e016040528d5260208d015260408c015260608b015260808a015260a089015260c088015260e0870152610100860152610120850152610140840152612def565b8282015261061f604051928392602084526001600160a01b0381511660208501526001600160a01b03602082015116604085015264ffffffffff604082015116606085015264ffffffffff60608201511660808501526080810151151560a085015260a0810151151560c08501526001600160a01b0360c08201511660e085015260e081015115156101008501526101008101511515610120850152610120810151151561014085015261014081015160406001600160801b03918281511685880152826020820151166101808801520151166101a085015201516101c0808401526101e0830190612895565b634e487b7160e01b600052604160045260246000fd5b60006060820152610f0d565b602460405162b8e7e760e51b81526004356004820152fd5b3461029d5760208060031936011261029d5760043567ffffffffffffffff811161029d57611157903690600401612864565b9061116061399e565b6000915b80831061116d57005b611178838284612d41565b359261118261399e565b83600052600980865260ff90600182816040600020015460a81c161561146f57866000528188526040600020838282015460a01c166000146111d65760248860405190634a5541ef60e01b82526004820152fd5b969495965460f81c611457576112028560005260096020526001600160a01b0360406000205416331490565b15611438576112108561375e565b91856000528089526112286002604060002001612dbb565b926001600160801b03948585511686831610156114205787600052828b5260406000205460f01c16156114085780858b6112686112729483895116612a02565b9601511690612a02565b86600052818a528960406000207f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa50815496600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89161783558a6113578a8716998a156113ef575b60038096019b84169b8c6fffffffffffffffffffffffffffffffff198254161790556001600160a01b03809116998a9688528160406000205416998a985260406000200154169661132d8c878a614681565b60405193849384916040919493606084019584526001600160801b03809216602085015216910152565b0390a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce789604051888152a1803b61139a575b5050505060019150019190611164565b803b1561029d5760019560006084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af16113e0575b80808061138a565b6113e99061295b565b856113d8565b898601600160a01b60ff60a01b198254161790556112db565b602487604051906339c6dc7360e21b82526004820152fd5b602488604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b815260048101869052336024820152604490fd5b6024856040519063fe19f19f60e01b82526004820152fd5b6024876040519062b8e7e760e51b82526004820152fd5b3461029d5760208060031936011261029d57600435906114a461399e565b816000526009815260ff60016040600020015460a81c16156107d5576114c9826137d6565b6005811015610a4f57600481036114f25760248360405190634a5541ef60e01b82526004820152fd5b60038103611512576024836040519063fe19f19f60e01b82526004820152fd5b600214611686576115398260005260096020526001600160a01b0360406000205416331490565b1561166757816000526009815260ff60406000205460f01c161561164f578160005260098152604060002060ff60f01b19815416905560405191807f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f600080a2600382526001600160a01b036040600020541692833b6115e0575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78383604051908152a1005b833b1561029d57600081602481837ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7987f450154640000000000000000000000000000000000000000000000000000000083528760048401525af1156115b4576116499061295b565b836115b4565b602482604051906339c6dc7360e21b82526004820152fd5b60405163216caf0d60e01b815260048101839052336024820152604490fd5b602482604051906322cad1af60e11b82526004820152fd5b3461029d57602036600319011261029d576004356001600160a01b039081811680910361029d578160005416338103611770575060085491816001600160a01b03198416176008556040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a2600754600019810190811161175a5760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a1005b634e487b7160e01b600052601160045260246000fd5b6040516331b339a960e21b81526001600160a01b03919091166004820152336024820152604490fd5b3461029d57602036600319011261029d576117b26127ef565b6000546001600160a01b0380821692338403611804576001600160a01b03199350169182911617600055337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf80600080a3005b6040516331b339a960e21b81526001600160a01b0385166004820152336024820152604490fd5b3461029d57602036600319011261029d576001600160a01b0361184c6127ef565b16801561186b5760005260046020526020604060002054604051908152f35b60246040517f89c62b6400000000000000000000000000000000000000000000000000000000815260006004820152fd5b3461029d57602036600319011261029d5760206118ba60043561373b565b6001600160a01b0360405191168152f35b3461029d576020600319818136011261029d5760043567ffffffffffffffff9182821161029d576101208236039182011261029d5761190861399e565b60c4820135906022190181121561029d57810160048101359083821161029d57602401606082023603811361029d57611942913691612c72565b9182519161194f83612c5a565b9261195d604051948561298c565b808452601f1961196c82612c5a565b018660005b828110611b3a5750505064ffffffffff90814216936001600160801b039687611999826139fa565b515116828a6119a7846139fa565b51015116858060406119b8866139fa565b5101511689011690604051926119cd84612923565b83528b83015260408201526119e1886139fa565b526119eb876139fa565b506001938760015b8a8c878310611ab95790838b8b611a0c81600401612d7b565b92611a1960248301612d7b565b92611a2660448401612d67565b946064840135946001600160a01b039586811680910361029d57611ab198611a7198611aa698611a5860848a01612d8f565b9481611a6660a48c01612d8f565b976040519d8e612906565b168c52168c8b0152166040890152606088015215156080870152151560a086015260c085015260e084015260e4369101612d12565b610100820152613a1b565b604051908152f35b889385806040611aed8b86611add8a8e9a611ad4828d613a07565b5151169a613a07565b5101511694600019890190613a07565b51015116816040611afe888c613a07565b5101511601169160405193611b1285612923565b84528301526040820152611b26828c613a07565b52611b31818b613a07565b500188906119f3565b611b42612d9c565b828289010152018790611971565b3461029d57604036600319011261029d5767ffffffffffffffff60043581811161029d57611b82903690600401612864565b9160243590811161029d57611b9b903690600401612864565b9091611ba561399e565b818403611c145760005b848110611bb857005b80611c0e611bc96001938886612d41565b35611bd5838987612d41565b3560005260036020526001600160a01b0360406000205416611c00611bfb85898b612d41565b612d67565b91611c0961399e565b6133a5565b01611baf565b60448483604051917faec9344000000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c161561031757610444602091614199565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000611cc3826137d6565b6005811015610a4f57600203611ce1575b6020906040519015158152f35b506000526009602052602060ff60406000205460f01c16611cd4565b3461029d57600036600319011261029d5760206001600160a01b0360085416604051908152f35b3461029d5760208060031936011261029d5760043590611d4261399e565b816000526009815260ff60016040600020015460a81c16156107d557816000526009815260ff60016040600020015460a01c1615611ecb57611d8382614130565b156116675781600052600381526001600160a01b038060406000205416151580611ec3575b80611ea9575b611e91577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790836000526003835260406000205416918215928315611e56575b846000526003825260406000206001600160a01b03198154169055846000604051927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4848152a1611e3e57005b60249060405190637e27328960e01b82526004820152fd5b611e7785600052600560205260406000206001600160a01b03198154169055565b806000526004825260406000206000198154019055611dee565b60248360405190630da9b01360e01b82526004820152fd5b506009825260ff60016040600020015460b01c1615611dae565b506000611da8565b602482604051907f817cd6390000000000000000000000000000000000000000000000000000000082526004820152fd5b3461029d57611f0a3661282f565b60405191602083019383851067ffffffffffffffff8611176110eb5761029b9460405260008452612e7f565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576000526009602052602060ff60016040600020015460a01c166040519015158152f35b3461029d5760208060031936011261029d5760043590611fa861399e565b8160005260099081815260ff60016040600020015460a81c161561226d5782600052818152604060002060ff600182015460a01c16600014611ffc5760248460405190634a5541ef60e01b82526004820152fd5b5460f81c612255576120248360005260096020526001600160a01b0360406000205416331490565b15612236576120328361375e565b928060005282825261204a6002604060002001612dbb565b916001600160801b039485845116868216101561221e578260005284825260ff60406000205460f01c161561220657816120db82888796956120d17ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce796837f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa509b5116612a02565b9701511690612a02565b9383600052868252604060002096875495600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff881617895560038a8216998a156121ec575b01998316998a6fffffffffffffffffffffffffffffffff198254161790556001600160a01b03809716978891600386528860406000205416988994875260016040600020015416946121758d8588614681565b604080518a81526001600160801b0392831660208201529290911690820152606090a4604051838152a1813b6121a757005b813b1561029d5760006084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af16121e357005b61029b9061295b565b60018101600160a01b60ff60a01b19825416179055612122565b602483604051906339c6dc7360e21b82526004820152fd5b602483604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b815260048101849052336024820152604490fd5b6024836040519063fe19f19f60e01b82526004820152fd5b6024836040519062b8e7e760e51b82526004820152fd5b3461029d5760031960203682011261029d5760043567ffffffffffffffff9182821161029d5761014090823603011261029d576122bf61399e565b604051916122cc83612906565b6122d88260040161281b565b83526122e66024830161281b565b60208401526122f7604483016129ca565b604084015260648201356001600160a01b038116810361029d576060840152612322608483016128f9565b608084015261233360a483016128f9565b60a084015261234460c48301612c48565b60c084015260e482013590811161029d578101913660238401121561029d57611aa6611ab1926123806020953690602460048201359101612c72565b60e0840152610104369101612d12565b3461029d5761029b6123a13661282f565b91612a1b565b3461029d57600036600319011261029d576020600754604051908152f35b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576123ff906137d6565b6005811015610a4f578060209115908115612420575b506040519015158152f35b600191501482612415565b3461029d57602036600319011261029d5760043580600052600960205260ff60016040600020015460a81c1615610317576020906000908060005260098352604060002060ff815460f01c16806124be575b612495575b50506001600160801b0360405191168152f35b6124b792506001600160801b0360026124b1920154169161375e565b90612a02565b8280612482565b5060ff600182015460a01c161561247d565b3461029d57604036600319011261029d576124e96127ef565b6024356124f58161373b565b331515806125be575b80612590575b6125605781906001600160a01b03809416938491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a460005260056020526040600020906001600160a01b0319825416179055600080f35b60246040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152336004820152fd5b506001600160a01b038116600052600660205260406000203360005260205260ff6040600020541615612504565b50336001600160a01b03821614156124fe565b3461029d57602036600319011261029d5760206118ba6004356129de565b3461029d57600036600319011261029d576040516000600190600154918260011c91600184169182156126ab575b6020948585108414610c67578587948686529182600014610c4757505060011461264e5750610bd69250038361298c565b84915060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6906000915b858310612693575050610bd6935082010185610bc9565b8054838901850152879450869390920191810161267c565b92607f169261261d565b3461029d57600036600319011261029d57602060405167016345785d8a00008152f35b3461029d57602036600319011261029d57600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361029d57817f80ac58cd000000000000000000000000000000000000000000000000000000006020931490811561277d575b8115612753575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148361274c565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150612745565b60005b8381106127ba5750506000910152565b81810151838201526020016127aa565b906020916127e3815180928185528580860191016127a7565b601f01601f1916010190565b600435906001600160a01b038216820361029d57565b602435906001600160a01b038216820361029d57565b35906001600160a01b038216820361029d57565b606090600319011261029d576001600160a01b0390600435828116810361029d5791602435908116810361029d579060443590565b9181601f8401121561029d5782359167ffffffffffffffff831161029d576020808501948460051b01011161029d57565b90815180825260208080930193019160005b8281106128b5575050505090565b835180516001600160801b031686528083015167ffffffffffffffff168684015260409081015164ffffffffff1690860152606090940193928101926001016128a7565b3590811515820361029d57565b610120810190811067ffffffffffffffff8211176110eb57604052565b6060810190811067ffffffffffffffff8211176110eb57604052565b6040810190811067ffffffffffffffff8211176110eb57604052565b67ffffffffffffffff81116110eb57604052565b610140810190811067ffffffffffffffff8211176110eb57604052565b90601f8019910116810190811067ffffffffffffffff8211176110eb57604052565b67ffffffffffffffff81116110eb57601f01601f191660200190565b35906001600160801b038216820361029d57565b6129e78161373b565b5060005260056020526001600160a01b036040600020541690565b6001600160801b03918216908216039190821161175a57565b906001600160a01b03809116801561078d5760009184835260209160038352604092828486205416151580612c40575b80612c28575b612c11578685526003815282848620541694873315159384612b61575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7945087612b29575b808352600484528683206001815401905581835260038452868320816001600160a01b0319825416179055877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef88519480a4878152a183168203612afb5750505050565b516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b612b4a82600052600560205260406000206001600160a01b03198154169055565b878352600484528683208054600019019055612a97565b91929380915090612bd0575b15612b7b5790878392612a6e565b848887612b98576024915190637e27328960e01b82526004820152fd5b90517f177e802f0000000000000000000000000000000000000000000000000000000081523360048201526024810191909152604490fd5b503386148015612bf5575b80612b6d5750878252600583523384868420541614612b6d565b5085825260068352848220338352835260ff8583205416612bdb565b602487855190630da9b01360e01b82526004820152fd5b506009815260ff6001858720015460b01c1615612a51565b506001612a4b565b359064ffffffffff8216820361029d57565b67ffffffffffffffff81116110eb5760051b60200190565b929192612c7e82612c5a565b604094612c8e604051928361298c565b8195848352602080930191606080960285019481861161029d57925b858410612cba5750505050505050565b868483031261029d57825190612ccf82612923565b612cd8856129ca565b8252858501359067ffffffffffffffff8216820361029d57828792838b950152612d03868801612c48565b86820152815201930192612caa565b919082604091031261029d57604051612d2a8161293f565b6020808294612d388161281b565b84520135910152565b9190811015612d515760051b0190565b634e487b7160e01b600052603260045260246000fd5b356001600160801b038116810361029d5790565b356001600160a01b038116810361029d5790565b35801515810361029d5790565b60405190612da982612923565b60006040838281528260208201520152565b90604051612dc881612923565b6040819360018154916001600160801b0392838116865260801c6020860152015416910152565b908154612dfb81612c5a565b92604093612e0c604051918261298c565b82815280946020809201926000526020600020906000935b858510612e3357505050505050565b60018481928451612e4381612923565b64ffffffffff87546001600160801b038116835267ffffffffffffffff8160801c168584015260c01c1686820152815201930194019391612e24565b9190612e8c828285612a1b565b803b612e99575b50505050565b612ef56001600160a01b03809216946040519384937f150b7a02000000000000000000000000000000000000000000000000000000009687865233600487015216602485015260448401526080606484015260848301906127ca565b03906020816000938185885af190829082612f8b575b5050612f425782612f1a614214565b8051919082612f3b5760248260405190633250574960e11b82526004820152fd5b9050602001fd5b7fffffffff000000000000000000000000000000000000000000000000000000001603612f73575038808080612e93565b60249060405190633250574960e11b82526004820152fd5b909192506020813d602011612feb575b81612fa86020938361298c565b81010312612fe75751907fffffffff0000000000000000000000000000000000000000000000000000000082168203612fe45750903880612f0b565b80fd5b5080fd5b3d9150612f9b565b92919092612fff61399e565b60009381855260099260209380855260409260ff6001858a20015460a81c161561338f5784885281865260ff6001858a20015460a01c16613378576001600160a01b0391828216928315613361576001600160801b039384861691821561334a57888c5260038a5280888d20541693848314158061333a575b613317576130858a614244565b87811685116132e657508a8a928e928484528083528b8085209a8c848d54169c6002015460801c906130b69161426c565b878752838652828720600201908282549160801b6fffffffffffffffffffffffffffffffff191691161781556130eb90612dbb565b90808683015116918184818351169201511661310691612a02565b161115946001927f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d966132b9575b87825285522001541694613149818988614681565b8a51908152a480331415806132af575b61324a575b82331415908161323f575b81613234575b506131a3575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce793945051908152a1565b813b15613230578351636fd110e960e01b8152600481018690523360248201526001600160a01b0390911660448201526001600160801b03909216606483015294957ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79582908183816084810103925af1613221575b859481613175565b61322a9061295b565b38613219565b8780fd5b90508214153861316f565b833b15159150613169565b803b156132ab578451636fd110e960e01b8152600481018790523360248201526001600160a01b03831660448201526001600160801b0385166064820152898160848183865af161329c575b5061315e565b6132a59061295b565b38613296565b8880fd5b50803b1515613159565b878252808652828220848101600160a01b60ff60a01b1982541617905560ff60f01b198154169055613134565b895163287ecaef60e21b8152600481018c90526001600160801b038a81166024830152919091166044820152606490fd5b60648a848b519163b34359d360e01b835260048301523360248301526044820152fd5b506133448a614130565b15613078565b60248989519063d2aabcd960e01b82526004820152fd5b602487875190630ff7ee2d60e31b82526004820152fd5b602485855190634a5541ef60e01b82526004820152fd5b60248585519062b8e7e760e51b82526004820152fd5b9291909260009381855260099060209382855260409260ff6001858a20015460a81c161561338f578785815281875260ff6001868320015460a01c16613724576001600160a01b039081851692831561370d576001600160801b03938486169182156136f65789845260038b528489852054169485831415806136e6575b6136c35761344a8b838e61343683614199565b9289525260028c8820015460801c90612a02565b87811685116136925750908b8b928387528282528b808820998b838c54169b6002015460801c9061347a9161426c565b868a52858552828a20600201908282549160801b6fffffffffffffffffffffffffffffffff191691161781556134af90612dbb565b818086830151169381835116920151166134c891612a02565b161115927f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d93613664575b848852825260018c88200154169461350c818c88614681565b8b51908152a4813314158061365a575b6135f4575b508133141590816135e9575b816135de575b50613566575050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce793945051908152a1565b908188923b156135da578451636fd110e960e01b8152600481018790523360248201526001600160a01b0390941660448501526001600160801b03909116606484015282908183816084810103925af16135c2575b8080613175565b6135cc869161295b565b6135d657846135bb565b8480fd5b8280fd5b905081141538613533565b823b1515915061352d565b813b15612fe4578551636fd110e960e01b8152600481018890523360248201526001600160a01b03861660448201526001600160801b0385166064820152818160848183875af1613646575b50613521565b61365291929a5061295b565b973880613640565b50813b151561351c565b8488528083528c882060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556134f3565b8a5163287ecaef60e21b8152600481018d90526001600160801b038a81166024830152919091166044820152606490fd5b60648b848c519163b34359d360e01b835260048301523360248301526044820152fd5b506136f08b614130565b15613423565b60248a8a519063d2aabcd960e01b82526004820152fd5b602488885190630ff7ee2d60e31b82526004820152fd5b602486865190634a5541ef60e01b82526004820152fd5b8060005260036020526001600160a01b0360406000205416908115611e3e575090565b64ffffffffff804216826000526009602052604060002091825482828260a01c1610156137cc5760c81c1611156137ba5750600a6020526001604060002054116000146137b1576137ae90614358565b90565b6137ae90614287565b6001600160801b039150600201541690565b5050505050600090565b806000526009602052604060002060ff600182015460a01c166000146137fd575050600490565b805460f81c613856575460a01c64ffffffffff164210613850576138208161375e565b9060005260096020526001600160801b03806002604060002001541691161060001461384b57600190565b600290565b50600090565b5050600390565b916000828152602090600382526001600160a01b03604095818784205416151580613993575b8061397b575b613964579480967ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79596828552600386527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8483872054169485928361392c575b169283613916575b84875260038852808720846001600160a01b0319825416179055519580a4948152a1565b83875260048852808720600181540190556138f2565b61394d86600052600560205260406000206001600160a01b03198154169055565b8388526004895284882080546000190190556138ea565b602486885190630da9b01360e01b82526004820152fd5b506009845260ff6001888520015460b01c1615613889565b508181161515613883565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036139d057565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b805115612d515760200190565b8051821015612d515760209160051b010190565b90613a3d6001600160801b036040840151166020610100850151015190614537565b6001600160801b0381511660e084015164ffffffffff60c08601511682156141065780156140dc57815180156140b2577f00000000000000000000000000000000000000000000000000000000000000008111614081575064ffffffffff6040613aa6846139fa565b5101511681101561402a5750600090819082815184905b808210613f99575050505064ffffffffff421664ffffffffff8216811015613f595750506001600160801b0316808203613f22575050600754928360005260096020526040600020916001600160801b0381511660028401906fffffffffffffffffffffffffffffffff198254161790556001600160a01b036060830151166001840154750100000000000000000000000000000000000000000060808501511515918654937fffffffffffffffffff0000ff000000000000000000000000000000000000000076ff0000000000000000000000000000000000000000000060a0890151151560b01b16921617171760018601556001600160a01b0384511678ffffffffff000000000000000000000000000000000000000060c086015160a01b169060e0860151937fff000000000000000000000000000000000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007dffffffffff000000000000000000000000000000000000000000000000006040613c598951996000198b0190613a07565b51015160c81b169560f01b16911617171717845560005b818110613e50575050600185016007556001600160a01b03602083015116801561078d57613ca6866001600160a01b039261385d565b16613e1f57613cd16001600160a01b036060840151166001600160801b038351169030903390614610565b6001600160801b0360208201511680613def575b507f33eb09bbf19ea3fb22c760d5164234f8bf62ca07dcf5a437ad389e96b0bd644360206001600160a01b03845116926001600160a01b038286015116946001600160a01b0360608201511696613de4613dc560808401511515928c60a086015115156001600160a01b0361010060e089015194549864ffffffffff6040519a613d6e8c61293f565b818160a01c168c5260c81c168c8b015201515116956001600160801b036040519a8b9a610140958c5233828d01528281511660408d015201511660608a0152608089015260a08801528060c0880152860190612895565b9260e08501906020908164ffffffffff91828151168552015116910152565b6101208301520390a4565b613e19906001600160a01b036060850151166001600160a01b036101008601515116903390614610565b38613ce5565b60246040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260006004820152fd5b86600052600a602052604060002090613e6d8160e0870151613a07565b518254680100000000000000008110156110eb5760018101808555811015612d5157600193600052602060002001906001600160801b03815116908254917fffffff00000000000000000000000000000000000000000000000000000000007cffffffffff000000000000000000000000000000000000000000000000604077ffffffffffffffff00000000000000000000000000000000602086015160801b1694015160c01b169316171717905501613c70565b60449250604051917fd90b7e3900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b6040517f210aec0e00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b9193509193613fbd906001600160801b03613fb48588613a07565b5151169061426c565b9364ffffffffff806040613fd18685613a07565b51015116941680851115613fed57506001849301909291613abd565b8385606492604051927f9588ac09000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b64ffffffffff604061403b846139fa565b5101516040517ff539a17c00000000000000000000000000000000000000000000000000000000815264ffffffffff938416600482015291169091166024820152604490fd5b602490604051907f4757689b0000000000000000000000000000000000000000000000000000000082526004820152fd5b60046040517f3952c64e000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd572dbcb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6095d3bc000000000000000000000000000000000000000000000000000000008152fd5b60009080825260036020526001600160a01b038060408420541692833314938415614175575b5050821561416357505090565b90915061417033926129de565b161490565b60ff9294509060409181526006602052818120338252602052205416913880614156565b8060005260096020526141b26002604060002001612dbb565b816000526009602052604060002060ff600182015460a01c166000146141e557506001600160801b039150602001511690565b5460f81c6141f757506137ae9061375e565b6137ae91506001600160801b036040818351169201511690612a02565b3d1561423f573d90614225826129ae565b91614233604051938461298c565b82523d6000602084013e565b606090565b6137ae9061425181614199565b90600052600960205260026040600020015460801c90612a02565b9190916001600160801b038080941691160191821161175a57565b64ffffffffff6142bc600091838352600960205280806040852054818160a01c1693849160c81c1603169181421603166146db565b91808252600a602052604082208054156143445790829167ffffffffffffffff9352614316602083205482845260096020526143116001600160801b03968760026040882001541696879360801c16906147cb565b614839565b92831361432c57505061432890614923565b1690565b60029350604092508152600960205220015460801c90565b602483634e487b7160e01b81526032600452fd5b64ffffffffff804216600083815260096020526040918282209083519161437e8361296f565b80549661012061440460026001600160a01b0394858c168852602088019b8b8160a01c168d528b8160c81c168b8a015260ff8160f01c16151560608a015260f81c1515608089015260ff600196600183015490811660a08b0152818160a01c16151560c08b0152818160a81c16151560e08b015260b01c16151561010089015201612dbb565b94019384528452600a60205261441b858520612def565b9184968087614429866139fa565b5101511692828288955b16106145015750916144a7614311928488816144ac98976001600160801b039e8f61445e898c613a07565b5151169d8e9a67ffffffffffffffff60206144798c84613a07565b5101511699848361448a8385613a07565b510151169650806144e657505050511680925b03169203166146db565b6147cb565b9283136144c55750506144bf8391614923565b16011690565b5160200151929392831692841683101591506144e19050575090565b905090565b6144f69293506000190190613a07565b51015116809261449d565b8093986001600160801b0390816145188c89613a07565b51511601169801928282808a61452e888a613a07565b51015116614433565b919091604051906145478261293f565b600091828152826020820152936001600160801b03928383169182156145f15767016345785d8a00008082116145ba57506145838591846154eb565b16602087019281845211156145a6575090826145a192511690612a02565b168252565b80634e487b7160e01b602492526001600452fd5b60449250604051917f4fea5c1a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b50939450505050604051906146058261293f565b808252602082015290565b9290604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff8411176110eb5761467f9260405261495f565b565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b0392909216602483015260448083019390935291815261467f916146d660648361298c565b61495f565b600160ff1b8082149081156147c1575b5061479757600081121561478e57614714816000035b60008412156147875783600003906149fb565b917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311614750576000199118131561474a5790565b60000390565b60449250604051917fd49c26b300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b83906149fb565b61471481614701565b60046040517f9fe2b450000000000000000000000000000000000000000000000000000000008152fd5b90508214386146eb565b806147e657506147e157670de0b6b3a764000090565b600090565b90670de0b6b3a764000080831461483357508061480b575050670de0b6b3a764000090565b670de0b6b3a7640000811461482f5761482a906143116137ae93614af5565b614c37565b5090565b91505090565b600160ff1b808214908115614919575b506148ef5760008112156148e657614872816000035b60008412156148df5783600003906154eb565b917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83116148a8576000199118131561474a5790565b60449250604051917f120b5b4300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b83906154eb565b6148728161485f565b60046040517fa6070c25000000000000000000000000000000000000000000000000000000008152fd5b9050821438614849565b6000811261492e5790565b602490604051907f2463f3d50000000000000000000000000000000000000000000000000000000082526004820152fd5b6001600160a01b03169061498a600080836020829551910182875af1614983614214565b908461559a565b9081519182151592836149d3575b5050506149a25750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312612fe7576020015190811591821503612fe45750388080614998565b670de0b6b3a7640000916000198383099280830292838086109503948086039514614ab75782851015614a7b57908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b82606492604051927f63a05778000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b505080925015614ac5570490565b634e487b7160e01b600052601260045260246000fd5b8015614ac5576ec097ce7bc90715b34b9f10000000000590565b80600080831315614c0657670de0b6b3a764000092838112614be357506001925b808305906001600160801b03821160071b91821c9167ffffffffffffffff831160061b92831c63ffffffff811160051b90811c61ffff811160041b90811c60ff811160031b90811c91600f831160021b92831c93600197600160038711811b96871c11961717171717171781810294811d90828214614bd757506706f05b59d3b20000905b848213614bab5750505050500290565b808391020590671bc16d674ec80000821215614bca575b831d90614b9b565b8091950194831d90614bc2565b93505093925050020290565b6000199392508015614ac5576ec097ce7bc90715b34b9f10000000000591614b16565b602483604051907f059b101b0000000000000000000000000000000000000000000000000000000082526004820152fd5b6000811215614c665768033dd1780914b9711419811261385057614c5d90600003614c37565b6137ae90614adb565b680a688906bd8affffff81136154ba57670de0b6b3a764000080604092831b05907780000000000000000000000000000000000000000000000067ff00000000000000831661539d575b66ff0000000000008316615295575b65ff00000000008316615195575b64ff00000000831661509d575b63ff0000008316614fad575b62ff00008316614ec5575b61ff008316614de5575b60ff8316614d0e575b02911c60bf031c90565b60808316614dd3575b838316614dc1575b60208316614daf575b60108316614d9d575b60088316614d8b575b60048316614d79575b60028316614d67575b6001831615614d04576801000000000000000102831c614d04565b6801000000000000000102831c614d4c565b6801000000000000000302831c614d43565b6801000000000000000602831c614d3a565b6801000000000000000b02831c614d31565b6801000000000000001602831c614d28565b6801000000000000002c02831c614d1f565b6801000000000000005902831c614d17565b6180008316614eb3575b6140008316614ea1575b6120008316614e8f575b6110008316614e7d575b6108008316614e6b575b6104008316614e59575b6102008316614e47575b610100831615614cfb57680100000000000000b102831c614cfb565b6801000000000000016302831c614e2b565b680100000000000002c602831c614e21565b6801000000000000058c02831c614e17565b68010000000000000b1702831c614e0d565b6801000000000000162e02831c614e03565b68010000000000002c5d02831c614df9565b680100000000000058b902831c614def565b628000008316614f9b575b624000008316614f89575b622000008316614f77575b621000008316614f65575b620800008316614f53575b620400008316614f41575b620200008316614f2f575b62010000831615614cf1576801000000000000b17202831c614cf1565b680100000000000162e402831c614f12565b6801000000000002c5c802831c614f07565b68010000000000058b9102831c614efc565b680100000000000b172102831c614ef1565b68010000000000162e4302831c614ee6565b680100000000002c5c8602831c614edb565b6801000000000058b90c02831c614ed0565b6380000000831661508b575b63400000008316615079575b63200000008316615067575b63100000008316615055575b63080000008316615043575b63040000008316615031575b6302000000831661501f575b6301000000831615614ce65768010000000000b1721802831c614ce6565b6801000000000162e43002831c615001565b68010000000002c5c86002831c614ff5565b680100000000058b90c002831c614fe9565b6801000000000b17217f02831c614fdd565b680100000000162e42ff02831c614fd1565b6801000000002c5c85fe02831c614fc5565b68010000000058b90bfc02831c614fb9565b6480000000008316615183575b6440000000008316615171575b642000000000831661515f575b641000000000831661514d575b640800000000831661513b575b6404000000008316615129575b6402000000008316615117575b640100000000831615614cda57680100000000b17217f802831c614cda565b68010000000162e42ff102831c6150f8565b680100000002c5c85fe302831c6150eb565b6801000000058b90bfce02831c6150de565b68010000000b17217fbb02831c6150d1565b6801000000162e42fff002831c6150c4565b68010000002c5c8601cc02831c6150b7565b680100000058b90c0b4902831c6150aa565b658000000000008316615283575b654000000000008316615271575b65200000000000831661525f575b65100000000000831661524d575b65080000000000831661523b575b650400000000008316615229575b650200000000008316615217575b65010000000000831615614ccd576801000000b17218355102831c614ccd565b680100000162e430e5a202831c6151f7565b6801000002c5c863b73f02831c6151e9565b68010000058b90cf1e6e02831c6151db565b680100000b1721bcfc9a02831c6151cd565b68010000162e43f4f83102831c6151bf565b680100002c5c89d5ec6d02831c6151b1565b6801000058b91b5bc9ae02831c6151a3565b6680000000000000831661538b575b66400000000000008316615379575b66200000000000008316615367575b66100000000000008316615355575b66080000000000008316615343575b66040000000000008316615331575b6602000000000000831661531f575b6601000000000000831615614cbf5768010000b17255775c0402831c614cbf565b6801000162e525ee054702831c6152fe565b68010002c5cc37da949202831c6152ef565b680100058ba01fb9f96d02831c6152e0565b6801000b175effdc76ba02831c6152d1565b680100162f3904051fa102831c6152c2565b6801002c605e2e8cec5002831c6152b3565b68010058c86da1c09ea202831c6152a4565b678000000000000000831661549b575b6740000000000000008316615489575b6720000000000000008316615477575b6710000000000000008316615465575b6708000000000000008316615453575b6704000000000000008316615441575b670200000000000000831661542f575b670100000000000000831615614cb057680100b1afa5abcbed6102831c614cb0565b68010163da9fb33356d802831c61540d565b680102c9a3e778060ee702831c6153fd565b6801059b0d31585743ae02831c6153ed565b68010b5586cf9890f62a02831c6153dd565b6801172b83c7d517adce02831c6153cd565b6801306fe0a31b7152df02831c6153bd565b5077b504f333f9de6484800000000000000000000000000000006153ad565b602490604051907f0360d0280000000000000000000000000000000000000000000000000000000082526004820152fd5b9091906000198382098382029182808310920391808303921461558957670de0b6b3a7640000908183101561555257947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b60449086604051917f5173648d00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5050670de0b6b3a764000090049150565b906155d957508051156155af57805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b81511580615624575b6155ea575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b156155e256fea164736f6c6343000817000a"; bytes public constant BYTECODE_LOCKUP_LINEAR = - hex"60a034620003b757601f19906001600160401b0390601f6200499e3881900382810186168401919085831185841017620002d0578085926040948552833981010312620003b75781516001600160a01b038082169490929091859003620003b757602080940151928316809303620003b7576200007b620003bc565b93601c85527f5361626c696572205632204c6f636b7570204c696e656172204e46540000000081860152620000af620003bc565b96601188527029a0a116ab1916a627a1a5aaa816a624a760791b82890152306080528551848111620002d0576001968754908882811c92168015620003ac575b85831014620002af57818684931162000356575b508490868311600114620002f257600092620002e6575b5050600019600383901b1c191690871b1786555b8751938411620002d0576002548681811c91168015620002c5575b83821014620002af5783811162000263575b5081928411600114620001f65750508192939495600092620001ea575b5050600019600383901b1c191690831b176002555b60018060a01b03198381600054161760005560085416176008556040519160007fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a36007556145c19081620003dd8239608051816139430152f35b01519050388062000178565b839291921696600260005282600020926000905b8982106200024b575050838697989695961062000231575b505050811b016002556200018d565b015160001960f88460031b161c1916905538808062000222565b8088859682949686015181550195019301906200020a565b6002600052826000208480870160051c820192858810620002a5575b0160051c019087905b828110620002985750506200015b565b6000815501879062000288565b925081926200027f565b634e487b7160e01b600052602260045260246000fd5b90607f169062000149565b634e487b7160e01b600052604160045260246000fd5b0151905038806200011a565b90848a94169184600052866000209260005b888282106200033f575050841162000325575b505050811b0186556200012e565b015160001960f88460031b161c1916905538808062000317565b8385015186558d9790950194938401930162000304565b90915088600052846000208680850160051c820192878610620003a2575b918b91869594930160051c01915b8281106200039257505062000103565b600081558594508b910162000382565b9250819262000374565b91607f1691620000ef565b600080fd5b60408051919082016001600160401b03811183821017620002d05760405256fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a714612f5a57508063027b674414612f3757806306fdde0314612e72578063081812fc14612e53578063095ea7b314612d5a5780631400ecec14612cba5780631c1cdd4c14612c555780631e99d56914612c3757806323b872dd14612c1f57806340e58ee5146129a1578063425d30dd1461295057806342842e0e1461290057806342966c681461272557806344267570146126fe5780634857501f146126885780634869e12d1461264d5780634cc55e11146121bd57806353b157271461209e5780636352211e1461206e5780636d0cee751461206e57806370a0823114611ffe57806375829def14611f6b578063780a82c814611f1e5780637cad6cd114611e245780637de6b1db14611bfd5780638659c270146118ac578063894e9a0d1461158c5780638f69b993146114f05780639067b677146114a057806395d89b4114611391578063a22cb465146112d4578063a80fc07114611282578063ab167ccc14611138578063ad35efd4146110d6578063b256456914611085578063b88d4fde14610ff8578063b8a3be6614610fc3578063b971302a14610f74578063bc2be1be14610f24578063c156a11d14610a77578063c87b56dd1461095b578063cc364f4814610890578063d4dbd20b1461083e578063d511609f146107f2578063d975dfed146107a6578063e985e9c514610751578063ea5ead1914610729578063eac8f5b8146106d7578063f590c17614610675578063f851a4401461064f5763fdd46d601461025257600080fd5b3461064c57606036600319011261064c576004359061026f613089565b916102786131e6565b92610281613939565b818352600960209181835260ff600160408720015460a81c16156106355783855281835260ff600160408720015460a01c1661061d576001600160a01b03958682169283156105f3576001600160801b03938483169081156105db57878952600387528960408a2054169283821415806105cb575b6105a7576103038961412a565b87811684116105755750888a5280885260408a20968360028d8a541699015460801c0181811161056157988b9c8b9c9a937f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d936103958e96859f8f6040816103909360029352878a5220019182906001600160801b036001600160801b031983549260801b169116179055565b6134dd565b906103b181868401511692826040818351169201511690613220565b161115610532575b848c528252600160408c20015416946103d3818a88614152565b604051908152a48033141580610528575b6104ba575b8333141590816104af575b816104a4575b5061042e575b837ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78688604051908152a180f35b823b156104a057604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af1610488575b8080610400565b61049190613105565b61049c578238610481565b8280fd5b8380fd5b9050831415386103fa565b843b151591506103f4565b803b1561052457604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af1610510575b50506103e9565b61051990613105565b610524578438610509565b8480fd5b50803b15156103e4565b848c5280835260408c2060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556103b9565b60248c634e487b7160e01b81526011600452fd5b60405163287ecaef60e21b8152600481018b90526001600160801b038781166024830152919091166044820152606490fd5b606489836040519163b34359d360e01b835260048301523360248301526044820152fd5b506105d589613995565b156102f6565b6024886040519063d2aabcd960e01b82526004820152fd5b60046040517fc61a0e9e000000000000000000000000000000000000000000000000000000008152fd5b60248460405190634a5541ef60e01b82526004820152fd5b6024846040519062b8e7e760e51b82526004820152fd5b80fd5b503461064c578060031936011261064c576001600160a01b036020915416604051908152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c057816040916020935260098352205460f81c6040519015158152f35b6024906040519062b8e7e760e51b82526004820152fd5b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05760016040836001600160a01b0393602095526009855220015416604051908152f35b503461064c57604036600319011261064c5760043590610747613089565b916102788161412a565b503461064c57604036600319011261064c5761076b613073565b6040610775613089565b926001600160a01b0380931681526006602052209116600052602052602060ff604060002054166040519015158152f35b503461064c57602036600319011261064c5760ff6001604060043593848152600960205220015460a81c16156106c0576107e160209161412a565b6001600160801b0360405191168152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c057604082600292602094526009845220015460801c604051908152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05760036040836001600160801b0393602095526009855220015416604051908152f35b503461064c576020908160031936011261064c57600435916108b06134be565b508282526009815260ff600160408420015460a81c16156109445760609282526009815264ffffffffff9182604082205460a01c1692600a835260408181842054169260098552205460c81c16916040519361090b85613136565b8452830152604082015261094260405180926040908164ffffffffff91828151168552826020820151166020860152015116910152565bf35b6024836040519062b8e7e760e51b82526004820152fd5b503461064c57602080600319360112610a675760043561097a81613692565b50826001600160a01b0360085416916044604051809481937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa928315610a6b5780936109ea575b50506109e660405192828493845283019061304e565b0390f35b909192503d8082843e6109fd81846131a8565b8201918381840312610a675780519067ffffffffffffffff821161049c570182601f82011215610a6757805191610a33836131ca565b93610a4160405195866131a8565b83855285848401011161064c575090610a5f9184808501910161302b565b9038806109d0565b5080fd5b604051903d90823e3d90fd5b503461064c57604036600319011261064c57600435610a94613089565b610a9c613939565b81835260099060209082825260ff600160408720015460a81c161561063557838552600382526001600160a01b03918260408720541693843303610f0557610ae38661412a565b906001600160801b039081831680158015610b83575b50505050505081811615610b6b5783610b11916137f4565b90811680610b315760248460405190637e27328960e01b82526004820152fd5b8203610b3b578380f35b6040516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b60248560405190633250574960e11b82526004820152fd5b610b8b613939565b898b5282865260ff600160408d20015460a81c1615610eee57898b5282865260ff600160408d20015460a01c16610ed65788156105f357610ebe57888a52600385528660408b205416918289141580610eae575b610e8a57610bec8a61412a565b8481168311610e585750898b5280865260408b20938260028a87541696015460801c01818111610e445790610c538d9796959493928d8952838a52610390600260408b20019182906001600160801b036001600160801b031983549260801b169116179055565b90610c6f818a8401511692826040818351169201511690613220565b161115610e15575b8a86528652888a7f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d888b600160408b2001541694610cb6818688614152565b604051908152a48033141580610e0b575b610da1575b813314159081610d96575b81610d8b575b50610d1a575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790604051868152a1388080808080610af9565b803b1561049c57604051636fd110e960e01b8152600481018990523360248201526001600160a01b03881660448201526001600160801b0392909216606483015282908290608490829084905af1610d73575b80610ce3565b610d7c90613105565b610d87578538610d6d565b8580fd5b905081141538610cdd565b823b15159150610cd7565b803b156104a057604051636fd110e960e01b8152600481018a90523360248201526001600160a01b03891660448201526001600160801b03841660648201528490818160848183875af1610df7575b5050610ccc565b610e0090613105565b6104a0578338610df0565b50803b1515610cc7565b8a86528087526040862060018101600160a01b60ff60a01b1982541617905560ff60f01b198154169055610c77565b60248d634e487b7160e01b81526011600452fd5b60405163287ecaef60e21b8152600481018c90526001600160801b038781166024830152919091166044820152606490fd5b60648a8a6040519163b34359d360e01b835260048301523360248301526044820152fd5b50610eb88a613995565b15610bdf565b6024896040519063d2aabcd960e01b82526004820152fd5b60248a60405190634a5541ef60e01b82526004820152fd5b60248a6040519062b8e7e760e51b82526004820152fd5b60405163216caf0d60e01b815260048101879052336024820152604490fd5b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05760408264ffffffffff926020945260098452205460a01c16604051908152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c0576040826001600160a01b03926020945260098452205416604051908152f35b503461064c57602036600319011261064c5760ff6001604060209360043581526009855220015460a81c166040519015158152f35b503461064c57608036600319011261064c57611012613073565b61101a613089565b906064359067ffffffffffffffff82116104a057366023830112156104a05781600401359284611049856131ca565b9361105760405195866131a8565b8585523660248783010111610a67578561108296602460209301838801378501015260443591613525565b80f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c057600160408360ff93602095526009855220015460b01c166040519015158152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05761110f9061376d565b60405190600581101561112457602092508152f35b602483634e487b7160e01b81526021600452fd5b503461064c5761014036600319011261064c57611153613939565b61115b6134be565b9064ffffffffff80421680845281611171613511565b1661126c575b60e4359082821682036112675701166040830152600435916001600160a01b0391828416809403611267576024359083821680920361126757604435906001600160801b038216809203611267576064359085821680920361064c5750608435918215158093036112675760a4359384151580950361126757604051976111fd89613119565b8852602088015260408701526060860152608085015260a084015260c083015260406101031936011261126757604051916112378361318c565b610104359182168203611267578261125f9260209452610124358482015260e0820152613a7c565b604051908152f35b600080fd5b81611275613511565b8201166020850152611177565b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05760026040836001600160801b0393602095526009855220015416604051908152f35b503461064c57604036600319011261064c576112ee613073565b60243590811515809203611267576001600160a01b03169081156113605733835260066020526040832082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602482604051907f5b08ba180000000000000000000000000000000000000000000000000000000082526004820152fd5b503461064c578060031936011261064c5760405190806002549160018360011c9260018516948515611496575b602095868610811461148257858852879493929187908215611460575050600114611406575b50506113f2925003836131a8565b6109e660405192828493845283019061304e565b90859250600282527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b8583106114485750506113f2935082010138806113e4565b80548389018501528794508693909201918101611430565b92509350506113f294915060ff191682840152151560051b82010138806113e4565b602483634e487b7160e01b81526022600452fd5b93607f16936113be565b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05760408264ffffffffff926020945260098452205460c81c16604051908152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c0576115299061376d565b906005821015908161156a576002831491821561157e575b8215611555575b6020836040519015158152f35b90915061156a57506004602091143880611548565b80634e487b7160e01b602492526021600452fd5b506003831491506000611541565b503461064c57602036600319011261064c57806101606040516115ae81613152565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e082015282610100820152826101208201526115f16134be565b61014082015201526004358152600960205260ff600160408320015460a81c1615611894576004358152600960205260408120906116bf6002604051936116378561316f565b80546001600160a01b038116865264ffffffffff8160a01c16602087015264ffffffffff8160c81c16604087015260ff8160f01c161515606087015260f81c1515608086015260ff60018201546001600160a01b03811660a0880152818160a01c16151560c0880152818160a81c16151560e088015260b01c161515610100860152016134dd565b6101208301526116d060043561376d565b6005811015611880576101606101c093600264ffffffffff9314611875575b610120810151936001600160a01b0360a083015116946004358252600a60205284604083205416918560408501511690606085015115159761010086015115159260c08701511515916001600160a01b03604060e08a015115159560036020522054166001600160a01b038951169b8960808d8f9c60200151169101511515926040519b61177c8d613152565b8c5260208c015260408b015260608a0152608089015260a088015260c087015260e0860152610100850152610120840152610140830152828201526040519384526001600160a01b0360208201511660208501528260408201511660408501526060810151151560608501526080810151151560808501526001600160a01b0360a08201511660a08501528260c08201511660c085015260e0810151151560e08501526101008101511515610100850152610120810151151561012085015261014081015160406001600160801b03918281511661014088015282602082015116858801520151166101808501520151166101a0820152f35b8360608201526116ef565b602482634e487b7160e01b81526021600452fd5b602460405162b8e7e760e51b81526004356004820152fd5b503461064c57602080600319360112610a675760043567ffffffffffffffff811161049c576118df9036906004016130d4565b91906118e9613939565b83925b8084106118f7578480f35b611902848284613498565b359361190c613939565b848652600980855260ff90600190828260408b20015460a81c1615611be657878952808752604089208281015460a01c84161561195b5760248960405190634a5541ef60e01b82526004820152fd5b9790919293949596975460f81c611bce5761198c8160005260096020526001600160a01b0360406000205416331490565b15611bae5761199a816136b5565b818a528289526119af600260408c20016134dd565b906001600160801b0395868351168783161015611b9657838c52848b5260408c205460f01c1615611b7e5791818a611a0085898f9a9998966119f68c998387935116613220565b9501511690613220565b8386528482527f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5060408720916040835499600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c161785558b83169a8b15611b65575b60038096019c88169c8d6001600160801b03198254161790556001600160a01b0392838092169b8c9789522054169889965260408d2001541694611aaa8b8588614152565b604080518881526001600160801b0392831660208201529290911690820152606090a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78a604051838152a1813b611b0e575b5050505050506001019291906118ec565b813b15610d8757856084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1611b51575b80808080611afd565b611b5a90613105565b610524578438611b48565b818601600160a01b60ff60a01b19825416179055611a65565b602483604051906339c6dc7360e21b82526004820152fd5b602484604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b81526004810191909152336024820152604490fd5b6024906040519063fe19f19f60e01b82526004820152fd5b6024886040519062b8e7e760e51b82526004820152fd5b503461064c57602080600319360112610a675760043590611c1c613939565b8183526009815260ff600160408520015460a81c1615611e0d57611c3f8261376d565b6005811015611df95760048103611c685760248360405190634a5541ef60e01b82526004820152fd5b60038103611c88576024836040519063fe19f19f60e01b82526004820152fd5b600214611de157611caf8260005260096020526001600160a01b0360406000205416331490565b15611dc2578183526009815260ff604084205460f01c1615611daa57818352600981526040832060ff60f01b19815416905582604051837f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f8380a2600383526001600160a01b03604083205416803b611d52575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791604051908152a180f35b803b1561049c57816024818580947f450154640000000000000000000000000000000000000000000000000000000083528960048401525af1611d96575b80611d23565b611d9f90613105565b61049c578238611d90565b602482604051906339c6dc7360e21b82526004820152fd5b60405163216caf0d60e01b815260048101839052336024820152604490fd5b602482604051906322cad1af60e11b82526004820152fd5b602484634e487b7160e01b81526021600452fd5b6024826040519062b8e7e760e51b82526004820152fd5b503461064c57602036600319011261064c576004356001600160a01b039081811680910361049c5781835416338103611ef5575060085491816001600160a01b03198416176008556040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a26007546000198101908111611ee15760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a180f35b602482634e487b7160e01b81526011600452fd5b6040516331b339a960e21b81526001600160a01b03919091166004820152336024820152604490fd5b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c05760408264ffffffffff9260209452600a8452205416604051908152f35b503461064c57602036600319011261064c57611f85613073565b9080546001600160a01b0380821693338503611fd7576001600160a01b03199394501691829116178255337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808380a380f35b6040516331b339a960e21b81526001600160a01b0386166004820152336024820152604490fd5b503461064c57602036600319011261064c576001600160a01b03612020613073565b16801561203d578160409160209352600483522054604051908152f35b602482604051907f89c62b640000000000000000000000000000000000000000000000000000000082526004820152fd5b503461064c57602036600319011261064c57602061208d600435613692565b6001600160a01b0360405191168152f35b503461064c5761016036600319011261064c576120b9613939565b604051906120c682613119565b6120ce613073565b82526120d8613089565b60208301526120e56131e6565b60408301526001600160a01b03906064358281168103610a67576060840152608435801515810361126757608084015260a43580151581036112675760a084015260603660c319011261064c575060405161213f81613136565b64ffffffffff60c435818116810361126757825260e435818116810361126757602083015261010435908116810361126757604082015260c083015260406101231936011261126757604051916121958361318c565b610124359182168203611267578261125f9260209452610144358482015260e0820152613a7c565b503461064c57604036600319011261064c5767ffffffffffffffff60043581811161049c576121f09036906004016130d4565b90916024359081116104a05761220a9036906004016130d4565b612212613939565b80830361261657845b838110612226578580f35b612231818587613498565b359061223e818688613498565b35875260036020526001600160a01b0360408820541661225f828587613498565b35906001600160801b038216820361126757612279613939565b838952600960205260ff600160408b20015460a81c161561063557838952600960205260ff600160408b20015460a01c1661061d5780156105f3576001600160801b038216156125fe5783895260036020526001600160a01b0360408a2054169182821415806125ee575b6125ca576122f18561412a565b6001600160801b0381166001600160801b0383161161259a5750848a52600960205260408a20926001600160a01b038454169360026001600160801b03841691015460801c016001600160801b03811161056157906123828c959493928887526009602052610390600260408920019182906001600160801b036001600160801b031983549260801b169116179055565b6001600160801b036123a68160208401511692826040818351169201511690613220565b161115612569575b86855260096020526001600160a01b036001604087200154166123db6001600160801b0384168583614152565b83887f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d60206040516001600160801b0388168152a4803314158061255f575b6124f5575b8333141590816124ea575b816124df575b5061246d575b505050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020600193604051908152a10161221b565b823b156104a057604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af16124c7575b8080612436565b6124d090613105565b6124db5786386124c0565b8680fd5b905083141538612430565b843b1515915061242a565b803b1561052457604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af161254b575b505061241f565b61255490613105565b610524578438612544565b50803b151561241a565b86855260096020526040852060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556123ae565b60405163287ecaef60e21b8152600481018790526001600160801b03928316602482015291166044820152606490fd5b606485836040519163b34359d360e01b835260048301523360248301526044820152fd5b506125f885613995565b156122e4565b6024846040519063d2aabcd960e01b82526004820152fd5b82604491604051917faec9344000000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b503461064c57602036600319011261064c5760ff6001604060043593848152600960205220015460a81c16156106c0576107e16020916139fe565b503461064c57602036600319011261064c5760043590818152600960205260ff600160408320015460a81c1615611e0d57806126c38361376d565b926005841015611880576002602094036126e4575b50506040519015158152f35b815260098352604090205460f01c60ff16905038806126d8565b503461064c578060031936011261064c5760206001600160a01b0360085416604051908152f35b503461064c57602080600319360112610a675760043590612744613939565b8183526009815260ff600160408520015460a81c1615611e0d578183526009815260ff600160408520015460a01c16156128cf5761278182613995565b15611dc25781600052600381526001600160a01b0380604060002054166009835260ff60016040600020015460b01c161590816128c5575b50806128bd575b6128a5577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79083600052600383526040600020541691821592831561286a575b846000526003825260406000206001600160a01b03198154169055846000604051927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4848152a1612852575080f35b60249060405190637e27328960e01b82526004820152fd5b61288b85600052600560205260406000206001600160a01b03198154169055565b806000526004825260406000206000198154019055612800565b60248360405190630da9b01360e01b82526004820152fd5b5060006127c0565b90501515386127b9565b602482604051907f817cd6390000000000000000000000000000000000000000000000000000000082526004820152fd5b503461064c5761290f3661309f565b60405191602083019383851067ffffffffffffffff86111761293a5761108294604052858452613525565b634e487b7160e01b600052604160045260246000fd5b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c057600160408360ff93602095526009855220015460a01c166040519015158152f35b503461064c576020908160031936011261064c57600435906129c1613939565b81815260099283815260ff600160408420015460a81c16156109445782825283815260408220600181015460a01c60ff1615612a0f5760248460405190634a5541ef60e01b82526004820152fd5b9284935460f81c611bce57612a3a8160005260096020526001600160a01b0360406000205416331490565b15611bae57612a48816136b5565b93818452808352612a5e600260408620016134dd565b916001600160801b0393848451168588161015611de15781865282815260ff604087205460f01c1615611daa57612aac878683612aa28a9b838a9c9b9c5116613220565b9701511690613220565b908286528381526040862091825494600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87161784556003898316948515612c05575b01988716988981546001600160801b0319161790556001600160a01b038096168097600385528760408b205416978893865260408b20600101541693612b388c8487614152565b604080518981526001600160801b03938416602082015292909116908201528060608101037f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5091a4604051908382527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791a1823b612bb4578480f35b823b15610524576084928591604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1612bf6575b81818080808480f35b612bff90613105565b81612bed565b60018101600160a01b60ff60a01b19825416179055612af1565b503461064c57611082612c313661309f565b9161324f565b503461064c578060031936011261064c576020600754604051908152f35b503461064c57602036600319011261064c57600435808252600960205260ff600160408420015460a81c16156106c057612c8e9061376d565b90600582101561156a5760208215838115612caf575b506040519015158152f35b600191501482612ca4565b503461064c57602036600319011261064c5760043590818152600960205260ff600160408320015460a81c1615611e0d57602091604082828152600985522060ff815460f01c1680612d48575b612d1f575b50506001600160801b0360405191168152f35b612d4192506001600160801b036002612d3b92015416916136b5565b90613220565b3880612d0c565b5060ff600182015460a01c1615612d07565b503461064c57604036600319011261064c57612d74613073565b602435612d8081613692565b33151580612e40575b80612e16575b612de65781906001600160a01b03809416938491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258680a48252600560205260408220906001600160a01b031982541617905580f35b60246040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152336004820152fd5b506001600160a01b038116845260066020526040842033855260205260ff60408520541615612d8f565b50336001600160a01b0382161415612d89565b503461064c57602036600319011261064c57602061208d6004356131fc565b503461064c578060031936011261064c576040519080600191600154928360011c9260018516948515612f2d575b602095868610811461148257858852879493929187908215611460575050600114612ed35750506113f2925003836131a8565b90859250600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b858310612f155750506113f2935082010138806113e4565b80548389018501528794508693909201918101612efd565b93607f1693612ea0565b503461064c578060031936011261064c57602060405167016345785d8a00008152f35b905034610a67576020366003190112610a67576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361049c57602092507f80ac58cd000000000000000000000000000000000000000000000000000000008114908115613001575b8115612fd7575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438612fd0565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150612fc9565b60005b83811061303e5750506000910152565b818101518382015260200161302e565b906020916130678151809281855285808601910161302b565b601f01601f1916010190565b600435906001600160a01b038216820361126757565b602435906001600160a01b038216820361126757565b6060906003190112611267576001600160a01b0390600435828116810361126757916024359081168103611267579060443590565b9181601f840112156112675782359167ffffffffffffffff8311611267576020808501948460051b01011161126757565b67ffffffffffffffff811161293a57604052565b610100810190811067ffffffffffffffff82111761293a57604052565b6060810190811067ffffffffffffffff82111761293a57604052565b610180810190811067ffffffffffffffff82111761293a57604052565b610140810190811067ffffffffffffffff82111761293a57604052565b6040810190811067ffffffffffffffff82111761293a57604052565b90601f8019910116810190811067ffffffffffffffff82111761293a57604052565b67ffffffffffffffff811161293a57601f01601f191660200190565b604435906001600160801b038216820361126757565b61320581613692565b5060005260056020526001600160a01b036040600020541690565b6001600160801b03918216908216039190821161323957565b634e487b7160e01b600052601160045260246000fd5b906001600160a01b03809116801561348057600091848352602091600383526040928284862054166009825260ff6001868820015460b01c16159081613476575b508061346e575b6134575786855260038152828486205416948733151593846133a7575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce794508761336f575b808352600484528683206001815401905581835260038452868320816001600160a01b0319825416179055877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef88519480a4878152a1831682036133415750505050565b516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b61339082600052600560205260406000206001600160a01b03198154169055565b8783526004845286832080546000190190556132dd565b91929380915090613416575b156133c157908783926132b4565b8488876133de576024915190637e27328960e01b82526004820152fd5b90517f177e802f0000000000000000000000000000000000000000000000000000000081523360048201526024810191909152604490fd5b50338614801561343b575b806133b357508782526005835233848684205416146133b3565b5085825260068352848220338352835260ff8583205416613421565b602487855190630da9b01360e01b82526004820152fd5b506001613297565b9050151538613290565b6024604051633250574960e11b815260006004820152fd5b91908110156134a85760051b0190565b634e487b7160e01b600052603260045260246000fd5b604051906134cb82613136565b60006040838281528260208201520152565b906040516134ea81613136565b6040819360018154916001600160801b0392838116865260801c6020860152015416910152565b60c43564ffffffffff811681036112675790565b919061353282828561324f565b803b61353f575b50505050565b61359b6001600160a01b03809216946040519384937f150b7a020000000000000000000000000000000000000000000000000000000096878652336004870152166024850152604484015260806064840152608483019061304e565b03906020816000938185885af190829082613631575b50506135e857826135c06140fa565b80519190826135e15760248260405190633250574960e11b82526004820152fd5b9050602001fd5b7fffffffff000000000000000000000000000000000000000000000000000000001603613619575038808080613539565b60249060405190633250574960e11b82526004820152fd5b909192506020813d60201161368a575b8161364e602093836131a8565b81010312610a675751907fffffffff000000000000000000000000000000000000000000000000000000008216820361064c57509038806135b1565b3d9150613641565b8060005260036020526001600160a01b0360406000205416908115612852575090565b600090808252600a60205264ffffffffff918260408220541642106137675760096020526040812092835490808260c81c169182421015613751576137069394955060a01c168091039042036142f6565b9082815260096020526001600160801b039261372c8460026040852001541680946143d6565b9283116137395750501690565b60029350604092508152600960205220015460801c90565b505050505060026001600160801b039101541690565b91505090565b806000526009602052604060002060ff600182015460a01c16600014613794575050600490565b805460f81c6137ed575460a01c64ffffffffff1642106137e7576137b7816136b5565b9060005260096020526001600160801b0380600260406000200154169116106000146137e257600190565b600290565b50600090565b5050600390565b916000828152602090600382526001600160a01b036040958187842054166009855260ff6001898620015460b01c1615908161392f575b5080613924575b61390d579480967ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79596828552600386527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef848387205416948592836138d5575b1692836138bf575b84875260038852808720846001600160a01b0319825416179055519580a4948152a1565b838752600488528087206001815401905561389b565b6138f686600052600560205260406000206001600160a01b03198154169055565b838852600489528488208054600019019055613893565b602486885190630da9b01360e01b82526004820152fd5b508181161515613832565b905015153861382b565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361396b57565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b60009080825260036020526001600160a01b0380604084205416928333149384156139da575b505082156139c857505090565b9091506139d533926131fc565b161490565b60ff92945090604091815260066020528181203382526020522054169138806139bb565b806000526009602052613a1760026040600020016134dd565b816000526009602052604060002060ff600182015460a01c16600014613a4a57506001600160801b039150602001511690565b5460f81c613a5f5750613a5c906136b5565b90565b613a5c91506001600160801b036040818351169201511690613220565b90613a9d6001600160801b03604084015116602060e08501510151906141ae565b916001600160801b0383511660c082015190156140d05764ffffffffff815116156140a65764ffffffffff81511690604081019164ffffffffff8351169081811015614066575050602081019064ffffffffff8251169081151580614054575b61401357505064ffffffffff90511664ffffffffff8251169081811015613fd357505064ffffffffff8042169151169081811015613f93575050600754926001600160801b0381511660405190613b5382613136565b815260006020820152600060408201526001600160a01b036060840151169060c08401519164ffffffffff604084015116906080860151151560a087015115159264ffffffffff6001600160a01b0389511696511660405196613bb58861316f565b87526020870152604086015260608501526000608085015260a0840152600060c0840152600160e08401526101008301526101208201528460005260096020526040600020906001600160a01b0381511678ffffffffff0000000000000000000000000000000000000000602083015160a01b16907dffffffffff00000000000000000000000000000000000000000000000000604084015160c81b167eff0000000000000000000000000000000000000000000000000000000000006060850151151560f01b16917fff000000000000000000000000000000000000000000000000000000000000006080860151151560f81b1693171717178255600182016001600160a01b0360a08301511681549074ff000000000000000000000000000000000000000060c0850151151560a01b1675ff00000000000000000000000000000000000000000060e0860151151560a81b16917fffffffffffffffffff000000000000000000000000000000000000000000000076ff00000000000000000000000000000000000000000000610100880151151560b01b1694161717171790556001600160801b03604060036101206002860194015194613dad84875116956001600160801b03199687825416178155856020890151166001600160801b036001600160801b031983549260801b169116179055565b01930151169082541617905564ffffffffff602060c084015101511680613f75575b50600184016007556001600160a01b03602083015116801561348057613dfd856001600160a01b03926137f4565b16613f4457613e286001600160a01b036060840151166001600160801b038351169030903390614287565b6001600160801b0360208201511680613f15575b506001600160a01b038251167f44cb432df42caa86b7ec73644ab8aec922bc44c71c98fc330addc75b88adbc7c610140866001600160a01b0360208701511694613f0c6001600160a01b03606089015116976080810151151560a08201511515906001600160801b0360206001600160a01b0360e060c087015196015151169660405198895233828a01528281511660408a01520151166060870152608086015260a085015260c08401906040908164ffffffffff91828151168552826020820151166020860152015116910152565b610120820152a4565b613f3e906001600160a01b036060850151166001600160a01b0360e08601515116903390614287565b38613e3c565b60246040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260006004820152fd5b600a60205260406000209064ffffffffff1982541617905538613dcf565b6040517f210aec0e00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b6040517f9fee269100000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b516040517fb39831ea00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b508164ffffffffff8251161015613afd565b6040517f5057f08400000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b60046040517fd572dbcb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6095d3bc000000000000000000000000000000000000000000000000000000008152fd5b3d15614125573d9061410b826131ca565b9161411960405193846131a8565b82523d6000602084013e565b606090565b613a5c90614137816139fe565b90600052600960205260026040600020015460801c90613220565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b039290921660248301526044808301939093529181526141ac916141a76064836131a8565b614485565b565b919091604051906141be8261318c565b600091828152826020820152936001600160801b03928383169182156142685767016345785d8a000080821161423157506141fa8591846143d6565b166020870192818452111561421d5750908261421892511690613220565b168252565b80634e487b7160e01b602492526001600452fd5b60449250604051917f4fea5c1a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b509394505050506040519061427c8261318c565b808252602082015290565b9290604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff84111761293a576141ac92604052614485565b670de0b6b3a76400009160001983830992808302928380861095039480860395146143b2578285101561437657908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b82606492604051927f63a05778000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b5050809250156143c0570490565b634e487b7160e01b600052601260045260246000fd5b9091906000198382098382029182808310920391808303921461447457670de0b6b3a7640000908183101561443d57947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b60449086604051917f5173648d00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5050670de0b6b3a764000090049150565b6001600160a01b0316906144b0600080836020829551910182875af16144a96140fa565b9084614521565b9081519182151592836144f9575b5050506144c85750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312610a6757602001519081159182150361064c57503880806144be565b90614560575080511561453657805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b815115806145ab575b614571575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b1561456956fea164736f6c6343000817000a"; + hex"60a034620003b757601f19906001600160401b0390601f620049a63881900382810186168401919085831185841017620002d0578085926040948552833981010312620003b75781516001600160a01b038082169490929091859003620003b757602080940151928316809303620003b7576200007b620003bc565b93601c85527f5361626c696572205632204c6f636b7570204c696e656172204e46540000000081860152620000af620003bc565b96601188527029a0a116ab1916a627a1a5aaa816a624a760791b82890152306080528551848111620002d0576001968754908882811c92168015620003ac575b85831014620002af57818684931162000356575b508490868311600114620002f257600092620002e6575b5050600019600383901b1c191690871b1786555b8751938411620002d0576002548681811c91168015620002c5575b83821014620002af5783811162000263575b5081928411600114620001f65750508192939495600092620001ea575b5050600019600383901b1c191690831b176002555b60018060a01b03198381600054161760005560085416176008556040519160007fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a36007556145c99081620003dd8239608051816139550152f35b01519050388062000178565b839291921696600260005282600020926000905b8982106200024b575050838697989695961062000231575b505050811b016002556200018d565b015160001960f88460031b161c1916905538808062000222565b8088859682949686015181550195019301906200020a565b6002600052826000208480870160051c820192858810620002a5575b0160051c019087905b828110620002985750506200015b565b6000815501879062000288565b925081926200027f565b634e487b7160e01b600052602260045260246000fd5b90607f169062000149565b634e487b7160e01b600052604160045260246000fd5b0151905038806200011a565b90848a94169184600052866000209260005b888282106200033f575050841162000325575b505050811b0186556200012e565b015160001960f88460031b161c1916905538808062000317565b8385015186558d9790950194938401930162000304565b90915088600052846000208680850160051c820192878610620003a2575b918b91869594930160051c01915b8281106200039257505062000103565b600081558594508b910162000382565b9250819262000374565b91607f1691620000ef565b600080fd5b60408051919082016001600160401b03811183821017620002d05760405256fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a714612f7457508063027b674414612f5157806306fdde0314612e8c578063081812fc14612e6d578063095ea7b314612d745780631400ecec14612cd45780631c1cdd4c14612c6f5780631e99d56914612c5157806323b872dd14612c3957806340e58ee5146129bb578063425d30dd1461296a57806342842e0e1461291a57806342966c6814612743578063442675701461271c5780634857501f146126a65780634869e12d1461266b5780634cc55e11146121c357806353b15727146120a45780636352211e146120745780636d0cee751461207457806370a082311461200457806375829def14611f71578063780a82c814611f245780637cad6cd114611e2a5780637de6b1db14611c035780638659c270146118b2578063894e9a0d146115925780638f69b993146114f65780639067b677146114a657806395d89b4114611397578063a22cb465146112da578063a80fc07114611288578063ab167ccc1461113e578063ad35efd4146110dc578063b25645691461108b578063b88d4fde14610ffe578063b8a3be6614610fc9578063b971302a14610f7a578063bc2be1be14610f2a578063c156a11d14610a65578063c87b56dd14610949578063cc364f481461087e578063d4dbd20b1461082c578063d511609f146107e0578063d975dfed14610794578063e985e9c51461073f578063ea5ead1914610717578063eac8f5b8146106c5578063f590c17614610663578063f851a4401461063d5763fdd46d601461025257600080fd5b3461063a57606036600319011261063a576004359061026f6130a3565b91610278613200565b9261028161394b565b818352600960209181835260ff600160408720015460a81c16156106235783855281835260ff600160408720015460a01c1661060b576001600160a01b03958682169283156105f3576001600160801b03938483169081156105db57878952600387528960408a2054169283821415806105cb575b6105a75761030389614132565b87811684116105755750888a5280885260408a20968360028d8a541699015460801c0181811161056157988b9c8b9c9a937f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d936103958e96859f8f6040816103909360029352878a5220019182906001600160801b036001600160801b031983549260801b169116179055565b6134f3565b906103b18186840151169282604081835116920151169061323a565b161115610532575b848c528252600160408c20015416946103d3818a8861415a565b604051908152a48033141580610528575b6104ba575b8333141590816104af575b816104a4575b5061042e575b837ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78688604051908152a180f35b823b156104a057604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af1610488575b8080610400565b6104919061311f565b61049c578238610481565b8280fd5b8380fd5b9050831415386103fa565b843b151591506103f4565b803b1561052457604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af1610510575b50506103e9565b6105199061311f565b610524578438610509565b8480fd5b50803b15156103e4565b848c5280835260408c2060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556103b9565b60248c634e487b7160e01b81526011600452fd5b60405163287ecaef60e21b8152600481018b90526001600160801b038781166024830152919091166044820152606490fd5b606489836040519163b34359d360e01b835260048301523360248301526044820152fd5b506105d5896139a7565b156102f6565b6024886040519063d2aabcd960e01b82526004820152fd5b60248660405190630ff7ee2d60e31b82526004820152fd5b60248460405190634a5541ef60e01b82526004820152fd5b6024846040519062b8e7e760e51b82526004820152fd5b80fd5b503461063a578060031936011261063a576001600160a01b036020915416604051908152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae57816040916020935260098352205460f81c6040519015158152f35b6024906040519062b8e7e760e51b82526004820152fd5b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5760016040836001600160a01b0393602095526009855220015416604051908152f35b503461063a57604036600319011261063a57600435906107356130a3565b9161027881614132565b503461063a57604036600319011261063a5761075961308d565b60406107636130a3565b926001600160a01b0380931681526006602052209116600052602052602060ff604060002054166040519015158152f35b503461063a57602036600319011261063a5760ff6001604060043593848152600960205220015460a81c16156106ae576107cf602091614132565b6001600160801b0360405191168152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae57604082600292602094526009845220015460801c604051908152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5760036040836001600160801b0393602095526009855220015416604051908152f35b503461063a576020908160031936011261063a576004359161089e6134d4565b508282526009815260ff600160408420015460a81c16156109325760609282526009815264ffffffffff9182604082205460a01c1692600a835260408181842054169260098552205460c81c1691604051936108f985613150565b8452830152604082015261093060405180926040908164ffffffffff91828151168552826020820151166020860152015116910152565bf35b6024836040519062b8e7e760e51b82526004820152fd5b503461063a57602080600319360112610a5557600435610968816136a8565b50826001600160a01b0360085416916044604051809481937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa928315610a595780936109d8575b50506109d4604051928284938452830190613068565b0390f35b909192503d8082843e6109eb81846131c2565b8201918381840312610a555780519067ffffffffffffffff821161049c570182601f82011215610a5557805191610a21836131e4565b93610a2f60405195866131c2565b83855285848401011161063a575090610a4d91848085019101613045565b9038806109be565b5080fd5b604051903d90823e3d90fd5b503461063a57604036600319011261063a57600435610a826130a3565b610a8a61394b565b81835260099060209082825260ff600160408720015460a81c161561062357838552600382526001600160a01b03918260408720541693843303610f0b57610ad186614132565b906001600160801b039081831680158015610b71575b50505050505081811615610b595783610aff9161380a565b90811680610b1f5760248460405190637e27328960e01b82526004820152fd5b8203610b29578380f35b6040516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b60248560405190633250574960e11b82526004820152fd5b610b7961394b565b898b5282865260ff600160408d20015460a81c1615610ef457898b5282865260ff600160408d20015460a01c16610edc578815610ec457610eac57888a52600385528660408b205416918289141580610e9c575b610e7857610bda8a614132565b8481168311610e465750898b5280865260408b20938260028a87541696015460801c01818111610e325790610c418d9796959493928d8952838a52610390600260408b20019182906001600160801b036001600160801b031983549260801b169116179055565b90610c5d818a840151169282604081835116920151169061323a565b161115610e03575b8a86528652888a7f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d888b600160408b2001541694610ca481868861415a565b604051908152a48033141580610df9575b610d8f575b813314159081610d84575b81610d79575b50610d08575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790604051868152a1388080808080610ae7565b803b1561049c57604051636fd110e960e01b8152600481018990523360248201526001600160a01b03881660448201526001600160801b0392909216606483015282908290608490829084905af1610d61575b80610cd1565b610d6a9061311f565b610d75578538610d5b565b8580fd5b905081141538610ccb565b823b15159150610cc5565b803b156104a057604051636fd110e960e01b8152600481018a90523360248201526001600160a01b03891660448201526001600160801b03841660648201528490818160848183875af1610de5575b5050610cba565b610dee9061311f565b6104a0578338610dde565b50803b1515610cb5565b8a86528087526040862060018101600160a01b60ff60a01b1982541617905560ff60f01b198154169055610c65565b60248d634e487b7160e01b81526011600452fd5b60405163287ecaef60e21b8152600481018c90526001600160801b038781166024830152919091166044820152606490fd5b60648a8a6040519163b34359d360e01b835260048301523360248301526044820152fd5b50610ea68a6139a7565b15610bcd565b6024896040519063d2aabcd960e01b82526004820152fd5b60248a60405190630ff7ee2d60e31b82526004820152fd5b60248a60405190634a5541ef60e01b82526004820152fd5b60248a6040519062b8e7e760e51b82526004820152fd5b60405163216caf0d60e01b815260048101879052336024820152604490fd5b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5760408264ffffffffff926020945260098452205460a01c16604051908152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae576040826001600160a01b03926020945260098452205416604051908152f35b503461063a57602036600319011261063a5760ff6001604060209360043581526009855220015460a81c166040519015158152f35b503461063a57608036600319011261063a5761101861308d565b6110206130a3565b906064359067ffffffffffffffff82116104a057366023830112156104a0578160040135928461104f856131e4565b9361105d60405195866131c2565b8585523660248783010111610a5557856110889660246020930183880137850101526044359161353b565b80f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae57600160408360ff93602095526009855220015460b01c166040519015158152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5761111590613783565b60405190600581101561112a57602092508152f35b602483634e487b7160e01b81526021600452fd5b503461063a5761014036600319011261063a5761115961394b565b6111616134d4565b9064ffffffffff80421680845281611177613527565b16611272575b60e43590828216820361126d5701166040830152600435916001600160a01b039182841680940361126d576024359083821680920361126d57604435906001600160801b03821680920361126d576064359085821680920361063a57506084359182151580930361126d5760a4359384151580950361126d576040519761120389613133565b8852602088015260408701526060860152608085015260a084015260c083015260406101031936011261126d576040519161123d836131a6565b61010435918216820361126d57826112659260209452610124358482015260e0820152613a8e565b604051908152f35b600080fd5b8161127b613527565b820116602085015261117d565b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5760026040836001600160801b0393602095526009855220015416604051908152f35b503461063a57604036600319011261063a576112f461308d565b6024359081151580920361126d576001600160a01b03169081156113665733835260066020526040832082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602482604051907f5b08ba180000000000000000000000000000000000000000000000000000000082526004820152fd5b503461063a578060031936011261063a5760405190806002549160018360011c926001851694851561149c575b60209586861081146114885785885287949392918790821561146657505060011461140c575b50506113f8925003836131c2565b6109d4604051928284938452830190613068565b90859250600282527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b85831061144e5750506113f8935082010138806113ea565b80548389018501528794508693909201918101611436565b92509350506113f894915060ff191682840152151560051b82010138806113ea565b602483634e487b7160e01b81526022600452fd5b93607f16936113c4565b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5760408264ffffffffff926020945260098452205460c81c16604051908152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5761152f90613783565b90600582101590816115705760028314918215611584575b821561155b575b6020836040519015158152f35b9091506115705750600460209114388061154e565b80634e487b7160e01b602492526021600452fd5b506003831491506000611547565b503461063a57602036600319011261063a57806101606040516115b48161316c565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e082015282610100820152826101208201526115f76134d4565b61014082015201526004358152600960205260ff600160408320015460a81c161561189a576004358152600960205260408120906116c560026040519361163d85613189565b80546001600160a01b038116865264ffffffffff8160a01c16602087015264ffffffffff8160c81c16604087015260ff8160f01c161515606087015260f81c1515608086015260ff60018201546001600160a01b03811660a0880152818160a01c16151560c0880152818160a81c16151560e088015260b01c161515610100860152016134f3565b6101208301526116d6600435613783565b6005811015611886576101606101c093600264ffffffffff931461187b575b610120810151936001600160a01b0360a083015116946004358252600a60205284604083205416918560408501511690606085015115159761010086015115159260c08701511515916001600160a01b03604060e08a015115159560036020522054166001600160a01b038951169b8960808d8f9c60200151169101511515926040519b6117828d61316c565b8c5260208c015260408b015260608a0152608089015260a088015260c087015260e0860152610100850152610120840152610140830152828201526040519384526001600160a01b0360208201511660208501528260408201511660408501526060810151151560608501526080810151151560808501526001600160a01b0360a08201511660a08501528260c08201511660c085015260e0810151151560e08501526101008101511515610100850152610120810151151561012085015261014081015160406001600160801b03918281511661014088015282602082015116858801520151166101808501520151166101a0820152f35b8360608201526116f5565b602482634e487b7160e01b81526021600452fd5b602460405162b8e7e760e51b81526004356004820152fd5b503461063a57602080600319360112610a555760043567ffffffffffffffff811161049c576118e59036906004016130ee565b91906118ef61394b565b83925b8084106118fd578480f35b6119088482846134ae565b359361191261394b565b848652600980855260ff90600190828260408b20015460a81c1615611bec57878952808752604089208281015460a01c8416156119615760248960405190634a5541ef60e01b82526004820152fd5b9790919293949596975460f81c611bd4576119928160005260096020526001600160a01b0360406000205416331490565b15611bb4576119a0816136cb565b818a528289526119b5600260408c20016134f3565b906001600160801b0395868351168783161015611b9c57838c52848b5260408c205460f01c1615611b845791818a611a0685898f9a9998966119fc8c99838793511661323a565b950151169061323a565b8386528482527f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5060408720916040835499600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c161785558b83169a8b15611b6b575b60038096019c88169c8d6001600160801b03198254161790556001600160a01b0392838092169b8c9789522054169889965260408d2001541694611ab08b858861415a565b604080518881526001600160801b0392831660208201529290911690820152606090a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78a604051838152a1813b611b14575b5050505050506001019291906118f2565b813b15610d7557856084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1611b57575b80808080611b03565b611b609061311f565b610524578438611b4e565b818601600160a01b60ff60a01b19825416179055611a6b565b602483604051906339c6dc7360e21b82526004820152fd5b602484604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b81526004810191909152336024820152604490fd5b6024906040519063fe19f19f60e01b82526004820152fd5b6024886040519062b8e7e760e51b82526004820152fd5b503461063a57602080600319360112610a555760043590611c2261394b565b8183526009815260ff600160408520015460a81c1615611e1357611c4582613783565b6005811015611dff5760048103611c6e5760248360405190634a5541ef60e01b82526004820152fd5b60038103611c8e576024836040519063fe19f19f60e01b82526004820152fd5b600214611de757611cb58260005260096020526001600160a01b0360406000205416331490565b15611dc8578183526009815260ff604084205460f01c1615611db057818352600981526040832060ff60f01b19815416905582604051837f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f8380a2600383526001600160a01b03604083205416803b611d58575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791604051908152a180f35b803b1561049c57816024818580947f450154640000000000000000000000000000000000000000000000000000000083528960048401525af1611d9c575b80611d29565b611da59061311f565b61049c578238611d96565b602482604051906339c6dc7360e21b82526004820152fd5b60405163216caf0d60e01b815260048101839052336024820152604490fd5b602482604051906322cad1af60e11b82526004820152fd5b602484634e487b7160e01b81526021600452fd5b6024826040519062b8e7e760e51b82526004820152fd5b503461063a57602036600319011261063a576004356001600160a01b039081811680910361049c5781835416338103611efb575060085491816001600160a01b03198416176008556040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a26007546000198101908111611ee75760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a180f35b602482634e487b7160e01b81526011600452fd5b6040516331b339a960e21b81526001600160a01b03919091166004820152336024820152604490fd5b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae5760408264ffffffffff9260209452600a8452205416604051908152f35b503461063a57602036600319011261063a57611f8b61308d565b9080546001600160a01b0380821693338503611fdd576001600160a01b03199394501691829116178255337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808380a380f35b6040516331b339a960e21b81526001600160a01b0386166004820152336024820152604490fd5b503461063a57602036600319011261063a576001600160a01b0361202661308d565b168015612043578160409160209352600483522054604051908152f35b602482604051907f89c62b640000000000000000000000000000000000000000000000000000000082526004820152fd5b503461063a57602036600319011261063a5760206120936004356136a8565b6001600160a01b0360405191168152f35b503461063a5761016036600319011261063a576120bf61394b565b604051906120cc82613133565b6120d461308d565b82526120de6130a3565b60208301526120eb613200565b60408301526001600160a01b03906064358281168103610a55576060840152608435801515810361126d57608084015260a435801515810361126d5760a084015260603660c319011261063a575060405161214581613150565b64ffffffffff60c435818116810361126d57825260e435818116810361126d57602083015261010435908116810361126d57604082015260c083015260406101231936011261126d576040519161219b836131a6565b61012435918216820361126d57826112659260209452610144358482015260e0820152613a8e565b503461063a57604036600319011261063a5767ffffffffffffffff60043581811161049c576121f69036906004016130ee565b90916024359081116104a0576122109036906004016130ee565b61221861394b565b80830361263457845b83811061222c578580f35b6122378185876134ae565b35906122448186886134ae565b35875260036020526001600160a01b036040882054166122658285876134ae565b35906001600160801b038216820361126d5761227f61394b565b838952600960205260ff600160408b20015460a81c161561062357838952600960205260ff600160408b20015460a01c1661060b57801561261c576001600160801b038216156126045783895260036020526001600160a01b0360408a2054169182821415806125f4575b6125d0576122f785614132565b6001600160801b0381166001600160801b038316116125a05750848a52600960205260408a20926001600160a01b038454169360026001600160801b03841691015460801c016001600160801b03811161056157906123888c959493928887526009602052610390600260408920019182906001600160801b036001600160801b031983549260801b169116179055565b6001600160801b036123ac816020840151169282604081835116920151169061323a565b16111561256f575b86855260096020526001600160a01b036001604087200154166123e16001600160801b038416858361415a565b83887f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d60206040516001600160801b0388168152a48033141580612565575b6124fb575b8333141590816124f0575b816124e5575b50612473575b505050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020600193604051908152a101612221565b823b156104a057604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af16124cd575b808061243c565b6124d69061311f565b6124e15786386124c6565b8680fd5b905083141538612436565b843b15159150612430565b803b1561052457604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af1612551575b5050612425565b61255a9061311f565b61052457843861254a565b50803b1515612420565b86855260096020526040852060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556123b4565b60405163287ecaef60e21b8152600481018790526001600160801b03928316602482015291166044820152606490fd5b606485836040519163b34359d360e01b835260048301523360248301526044820152fd5b506125fe856139a7565b156122ea565b6024846040519063d2aabcd960e01b82526004820152fd5b60248460405190630ff7ee2d60e31b82526004820152fd5b82604491604051917faec9344000000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b503461063a57602036600319011261063a5760ff6001604060043593848152600960205220015460a81c16156106ae576107cf602091613a10565b503461063a57602036600319011261063a5760043590818152600960205260ff600160408320015460a81c1615611e1357806126e183613783565b92600584101561188657600260209403612702575b50506040519015158152f35b815260098352604090205460f01c60ff16905038806126f6565b503461063a578060031936011261063a5760206001600160a01b0360085416604051908152f35b503461063a57602080600319360112610a55576004359061276261394b565b8183526009815260ff600160408520015460a81c1615611e13578183526009815260ff600160408520015460a01c16156128e95761279f826139a7565b15611dc85781600052600381526001600160a01b0380604060002054161515806128e1575b806128c7575b6128af577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790836000526003835260406000205416918215928315612874575b846000526003825260406000206001600160a01b03198154169055846000604051927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4848152a161285c575080f35b60249060405190637e27328960e01b82526004820152fd5b61289585600052600560205260406000206001600160a01b03198154169055565b80600052600482526040600020600019815401905561280a565b60248360405190630da9b01360e01b82526004820152fd5b506009825260ff60016040600020015460b01c16156127ca565b5060006127c4565b602482604051907f817cd6390000000000000000000000000000000000000000000000000000000082526004820152fd5b503461063a57612929366130b9565b60405191602083019383851067ffffffffffffffff861117612954576110889460405285845261353b565b634e487b7160e01b600052604160045260246000fd5b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae57600160408360ff93602095526009855220015460a01c166040519015158152f35b503461063a576020908160031936011261063a57600435906129db61394b565b81815260099283815260ff600160408420015460a81c16156109325782825283815260408220600181015460a01c60ff1615612a295760248460405190634a5541ef60e01b82526004820152fd5b9284935460f81c611bd457612a548160005260096020526001600160a01b0360406000205416331490565b15611bb457612a62816136cb565b93818452808352612a78600260408620016134f3565b916001600160801b0393848451168588161015611de75781865282815260ff604087205460f01c1615611db057612ac6878683612abc8a9b838a9c9b9c511661323a565b970151169061323a565b908286528381526040862091825494600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87161784556003898316948515612c1f575b01988716988981546001600160801b0319161790556001600160a01b038096168097600385528760408b205416978893865260408b20600101541693612b528c848761415a565b604080518981526001600160801b03938416602082015292909116908201528060608101037f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5091a4604051908382527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791a1823b612bce578480f35b823b15610524576084928591604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1612c10575b81818080808480f35b612c199061311f565b81612c07565b60018101600160a01b60ff60a01b19825416179055612b0b565b503461063a57611088612c4b366130b9565b91613269565b503461063a578060031936011261063a576020600754604051908152f35b503461063a57602036600319011261063a57600435808252600960205260ff600160408420015460a81c16156106ae57612ca890613783565b9060058210156115705760208215838115612cc9575b506040519015158152f35b600191501482612cbe565b503461063a57602036600319011261063a5760043590818152600960205260ff600160408320015460a81c1615611e1357602091604082828152600985522060ff815460f01c1680612d62575b612d39575b50506001600160801b0360405191168152f35b612d5b92506001600160801b036002612d5592015416916136cb565b9061323a565b3880612d26565b5060ff600182015460a01c1615612d21565b503461063a57604036600319011261063a57612d8e61308d565b602435612d9a816136a8565b33151580612e5a575b80612e30575b612e005781906001600160a01b03809416938491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258680a48252600560205260408220906001600160a01b031982541617905580f35b60246040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152336004820152fd5b506001600160a01b038116845260066020526040842033855260205260ff60408520541615612da9565b50336001600160a01b0382161415612da3565b503461063a57602036600319011261063a576020612093600435613216565b503461063a578060031936011261063a576040519080600191600154928360011c9260018516948515612f47575b602095868610811461148857858852879493929187908215611466575050600114612eed5750506113f8925003836131c2565b90859250600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b858310612f2f5750506113f8935082010138806113ea565b80548389018501528794508693909201918101612f17565b93607f1693612eba565b503461063a578060031936011261063a57602060405167016345785d8a00008152f35b905034610a55576020366003190112610a55576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361049c57602092507f80ac58cd00000000000000000000000000000000000000000000000000000000811490811561301b575b8115612ff1575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438612fea565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150612fe3565b60005b8381106130585750506000910152565b8181015183820152602001613048565b9060209161308181518092818552858086019101613045565b601f01601f1916010190565b600435906001600160a01b038216820361126d57565b602435906001600160a01b038216820361126d57565b606090600319011261126d576001600160a01b0390600435828116810361126d5791602435908116810361126d579060443590565b9181601f8401121561126d5782359167ffffffffffffffff831161126d576020808501948460051b01011161126d57565b67ffffffffffffffff811161295457604052565b610100810190811067ffffffffffffffff82111761295457604052565b6060810190811067ffffffffffffffff82111761295457604052565b610180810190811067ffffffffffffffff82111761295457604052565b610140810190811067ffffffffffffffff82111761295457604052565b6040810190811067ffffffffffffffff82111761295457604052565b90601f8019910116810190811067ffffffffffffffff82111761295457604052565b67ffffffffffffffff811161295457601f01601f191660200190565b604435906001600160801b038216820361126d57565b61321f816136a8565b5060005260056020526001600160a01b036040600020541690565b6001600160801b03918216908216039190821161325357565b634e487b7160e01b600052601160045260246000fd5b906001600160a01b038091168015613496576000918483526020916003835260409282848620541615158061348e575b80613476575b61345f5786855260038152828486205416948733151593846133af575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7945087613377575b808352600484528683206001815401905581835260038452868320816001600160a01b0319825416179055877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef88519480a4878152a1831682036133495750505050565b516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b61339882600052600560205260406000206001600160a01b03198154169055565b8783526004845286832080546000190190556132e5565b9192938091509061341e575b156133c957908783926132bc565b8488876133e6576024915190637e27328960e01b82526004820152fd5b90517f177e802f0000000000000000000000000000000000000000000000000000000081523360048201526024810191909152604490fd5b503386148015613443575b806133bb57508782526005835233848684205416146133bb565b5085825260068352848220338352835260ff8583205416613429565b602487855190630da9b01360e01b82526004820152fd5b506009815260ff6001858720015460b01c161561329f565b506001613299565b6024604051633250574960e11b815260006004820152fd5b91908110156134be5760051b0190565b634e487b7160e01b600052603260045260246000fd5b604051906134e182613150565b60006040838281528260208201520152565b9060405161350081613150565b6040819360018154916001600160801b0392838116865260801c6020860152015416910152565b60c43564ffffffffff8116810361126d5790565b9190613548828285613269565b803b613555575b50505050565b6135b16001600160a01b03809216946040519384937f150b7a0200000000000000000000000000000000000000000000000000000000968786523360048701521660248501526044840152608060648401526084830190613068565b03906020816000938185885af190829082613647575b50506135fe57826135d6614102565b80519190826135f75760248260405190633250574960e11b82526004820152fd5b9050602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000160361362f57503880808061354f565b60249060405190633250574960e11b82526004820152fd5b909192506020813d6020116136a0575b81613664602093836131c2565b81010312610a555751907fffffffff000000000000000000000000000000000000000000000000000000008216820361063a57509038806135c7565b3d9150613657565b8060005260036020526001600160a01b036040600020541690811561285c575090565b600090808252600a60205264ffffffffff9182604082205416421061377d5760096020526040812092835490808260c81c1691824210156137675761371c9394955060a01c168091039042036142fe565b9082815260096020526001600160801b03926137428460026040852001541680946143de565b92831161374f5750501690565b60029350604092508152600960205220015460801c90565b505050505060026001600160801b039101541690565b91505090565b806000526009602052604060002060ff600182015460a01c166000146137aa575050600490565b805460f81c613803575460a01c64ffffffffff1642106137fd576137cd816136cb565b9060005260096020526001600160801b0380600260406000200154169116106000146137f857600190565b600290565b50600090565b5050600390565b916000828152602090600382526001600160a01b03604095818784205416151580613940575b80613928575b613911579480967ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79596828552600386527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef848387205416948592836138d9575b1692836138c3575b84875260038852808720846001600160a01b0319825416179055519580a4948152a1565b838752600488528087206001815401905561389f565b6138fa86600052600560205260406000206001600160a01b03198154169055565b838852600489528488208054600019019055613897565b602486885190630da9b01360e01b82526004820152fd5b506009845260ff6001888520015460b01c1615613836565b508181161515613830565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361397d57565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b60009080825260036020526001600160a01b0380604084205416928333149384156139ec575b505082156139da57505090565b9091506139e73392613216565b161490565b60ff92945090604091815260066020528181203382526020522054169138806139cd565b806000526009602052613a2960026040600020016134f3565b816000526009602052604060002060ff600182015460a01c16600014613a5c57506001600160801b039150602001511690565b5460f81c613a715750613a6e906136cb565b90565b613a6e91506001600160801b03604081835116920151169061323a565b90613aaf6001600160801b03604084015116602060e08501510151906141b6565b916001600160801b0383511660c082015190156140d85764ffffffffff815116156140ae576020810164ffffffffff81511680613ffe575b5050604064ffffffffff82511691019064ffffffffff8251169081811015613fbe57505064ffffffffff8042169151169081811015613f7e575050600754926001600160801b0381511660405190613b3e82613150565b815260006020820152600060408201526001600160a01b036060840151169060c08401519164ffffffffff604084015116906080860151151560a087015115159264ffffffffff6001600160a01b0389511696511660405196613ba088613189565b87526020870152604086015260608501526000608085015260a0840152600060c0840152600160e08401526101008301526101208201528460005260096020526040600020906001600160a01b0381511678ffffffffff0000000000000000000000000000000000000000602083015160a01b16907dffffffffff00000000000000000000000000000000000000000000000000604084015160c81b167eff0000000000000000000000000000000000000000000000000000000000006060850151151560f01b16917fff000000000000000000000000000000000000000000000000000000000000006080860151151560f81b1693171717178255600182016001600160a01b0360a08301511681549074ff000000000000000000000000000000000000000060c0850151151560a01b1675ff00000000000000000000000000000000000000000060e0860151151560a81b16917fffffffffffffffffff000000000000000000000000000000000000000000000076ff00000000000000000000000000000000000000000000610100880151151560b01b1694161717171790556001600160801b03604060036101206002860194015194613d9884875116956001600160801b03199687825416178155856020890151166001600160801b036001600160801b031983549260801b169116179055565b01930151169082541617905564ffffffffff602060c084015101511680613f60575b50600184016007556001600160a01b03602083015116801561349657613de8856001600160a01b039261380a565b16613f2f57613e136001600160a01b036060840151166001600160801b03835116903090339061428f565b6001600160801b0360208201511680613f00575b506001600160a01b038251167f44cb432df42caa86b7ec73644ab8aec922bc44c71c98fc330addc75b88adbc7c610140866001600160a01b0360208701511694613ef76001600160a01b03606089015116976080810151151560a08201511515906001600160801b0360206001600160a01b0360e060c087015196015151169660405198895233828a01528281511660408a01520151166060870152608086015260a085015260c08401906040908164ffffffffff91828151168552826020820151166020860152015116910152565b610120820152a4565b613f29906001600160a01b036060850151166001600160a01b0360e0860151511690339061428f565b38613e27565b60246040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260006004820152fd5b600a60205260406000209064ffffffffff1982541617905538613dba565b6040517f210aec0e00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b6040517f5057f08400000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b64ffffffffff8351168181101561406e57505064ffffffffff90511664ffffffffff60408301511690818110613ae7576040517f9fee269100000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b6040517fb39831ea00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b60046040517fd572dbcb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6095d3bc000000000000000000000000000000000000000000000000000000008152fd5b3d1561412d573d90614113826131e4565b9161412160405193846131c2565b82523d6000602084013e565b606090565b613a6e9061413f81613a10565b90600052600960205260026040600020015460801c9061323a565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b039290921660248301526044808301939093529181526141b4916141af6064836131c2565b61448d565b565b919091604051906141c6826131a6565b600091828152826020820152936001600160801b03928383169182156142705767016345785d8a000080821161423957506142028591846143de565b1660208701928184521115614225575090826142209251169061323a565b168252565b80634e487b7160e01b602492526001600452fd5b60449250604051917f4fea5c1a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5093945050505060405190614284826131a6565b808252602082015290565b9290604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff841117612954576141b49260405261448d565b670de0b6b3a76400009160001983830992808302928380861095039480860395146143ba578285101561437e57908291096001821901821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b82606492604051927f63a05778000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b5050809250156143c8570490565b634e487b7160e01b600052601260045260246000fd5b9091906000198382098382029182808310920391808303921461447c57670de0b6b3a7640000908183101561444557947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b60449086604051917f5173648d00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5050670de0b6b3a764000090049150565b6001600160a01b0316906144b8600080836020829551910182875af16144b1614102565b9084614529565b908151918215159283614501575b5050506144d05750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312610a5557602001519081159182150361063a57503880806144c6565b90614568575080511561453e57805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b815115806145b3575b614579575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b1561457156fea164736f6c6343000817000a"; bytes public constant BYTECODE_LOCKUP_TRANCHED = - hex"60c034620003dc576001600160401b0390601f601f1962004dc23881900383810183168501919086831186841017620002f557808692606094604052833981010312620003dc5782516001600160a01b038082169590929091869003620003dc5760209485810151938416809403620003dc57604001519362000081620003e1565b95601e87527f5361626c696572205632204c6f636b7570205472616e63686564204e4654000081880152620000b5620003e1565b9060118252705341422d56322d4c4f434b55502d54524160781b81830152306080528751858111620002f5576001988954908a82811c92168015620003d1575b84831014620002d45781868493116200037b575b50839086831160011462000317576000926200030b575b5050600019600383901b1c191690891b1788555b8151948511620002f557600254938885811c95168015620002ea575b82861014620002d457848487961162000277575b50819385116001146200020d57505060009262000201575b5050600019600383901b1c191690841b176002555b60018060a01b03198481600054161760005560085416176008556040519260007fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a360a0526007556149c0908162000402823960805181613da2015260a051818181612eb80152613e480152f35b0151905038806200017c565b88959392919316600260005283600020936000905b8282106200025d575050841162000243575b505050811b0160025562000191565b015160001960f88460031b161c1916905538808062000234565b8484015186558a9790950194938401939081019062000222565b9091929394506002600052826000208580880160051c820192858910620002ca575b9188978c9297969594930160051c01915b828110620002ba57505062000164565b600081558897508b9101620002aa565b9250819262000299565b634e487b7160e01b600052602260045260246000fd5b94607f169462000150565b634e487b7160e01b600052604160045260246000fd5b01519050388062000120565b90878c94169184600052856000209260005b878282106200036457505084116200034a575b505050811b01885562000134565b015160001960f88460031b161c191690553880806200033c565b8385015186558f9790950194938401930162000329565b9091508a600052836000208680850160051c820192868610620003c7575b918d91869594930160051c01915b828110620003b757505062000109565b600081558594508d9101620003a7565b9250819262000399565b91607f1691620000f5565b600080fd5b60408051919082016001600160401b03811183821017620002f55760405256fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461321657508063027b6744146131f357806306fdde031461312e578063081812fc1461310f578063095ea7b3146130165780631400ecec14612f765780631c1cdd4c14612f115780631e99d56914612ef357806323b872dd14612edb5780632fe4304114612ea057806332fbe22b14612d4857806340e58ee514612aaa578063425d30dd14612a5957806342842e0e14612a1f57806342966c6814612844578063442675701461281d5780634857501f146127a75780634869e12d1461276c5780634cc55e11146122f05780636352211e146122c05780636d0cee75146122c057806370a082311461225057806375829def146121bd5780637cad6cd1146120c35780637de6b1db14611e9c5780637f5799f914611e415780638659c27014611ae7578063894e9a0d1461175b578063897f362b146114ab5780638f69b9931461140f5780639067b677146113bf57806395d89b41146112b0578063a22cb465146111f3578063a80fc071146111a1578063ad35efd41461113f578063b2564569146110ee578063b88d4fde14611061578063b8a3be661461102c578063b971302a14610fdd578063bc2be1be14610f8d578063c156a11d14610af6578063c87b56dd146109da578063cc364f4814610942578063d4dbd20b146108f0578063d511609f146108a4578063d975dfed14610858578063e985e9c514610803578063ea5ead1914610721578063eac8f5b8146106cf578063f590c1761461066d578063f851a440146106475763fdd46d601461025d57600080fd5b34610644576060366003190112610644576004359061027a613345565b91604435926001600160801b038085169182860361063f5761029a613d98565b83855260099560209387855260ff600160408920015460a81c16156106285785875287855260ff600160408920015460a01c16610610576001600160a01b039081841680156105e65781156105ce57878952600387528260408a2054169283821415806105be575b61059a5761030f896145f3565b8781168411610568575097899a888b999a83809d5282825260408b209988828c54169b6002015460801c906103439161461b565b858d5284845260408d20600201908282549160801b6fffffffffffffffffffffffffffffffff19169116178155610379906138ec565b908084830151169181808251169160400151166103959161352d565b161115927f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d93610539575b848c528252600160408c20015416946103da818a88614780565b604051908152a4803314158061052f575b6104c1575b8333141590816104b6575b816104ab575b50610435575b837ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78688604051908152a180f35b823b156104a757604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af161048f575b8080610407565b6104989061344e565b6104a3578238610488565b8280fd5b8380fd5b905083141538610401565b843b151591506103fb565b803b1561052b57604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af1610517575b50506103f0565b6105209061344e565b61052b578438610510565b8480fd5b50803b15156103eb565b848c5280835260408c2060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556103c0565b60405163287ecaef60e21b8152600481018b90526001600160801b038781166024830152919091166044820152606490fd5b606489836040519163b34359d360e01b835260048301523360248301526044820152fd5b506105c8896144dc565b15610302565b6024886040519063d2aabcd960e01b82526004820152fd5b60046040517fc61a0e9e000000000000000000000000000000000000000000000000000000008152fd5b60248660405190634a5541ef60e01b82526004820152fd5b6024866040519062b8e7e760e51b82526004820152fd5b600080fd5b80fd5b50346106445780600319360112610644576001600160a01b036020915416604051908152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b857816040916020935260098352205460f81c6040519015158152f35b6024906040519062b8e7e760e51b82526004820152fd5b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85760016040836001600160a01b0393602095526009855220015416604051908152f35b5034610644576040366003190112610644576004359061073f613345565b91610749816145f3565b92610752613d98565b81835260099360209185835260ff600160408720015460a81c16156107ec5783855285835260ff600160408720015460a01c166107d4576001600160a01b03918282169283156105e6576001600160801b03938483169081156105ce57878952600387528260408a2054169283821415806105be5761059a5761030f896145f3565b60248460405190634a5541ef60e01b82526004820152fd5b6024846040519062b8e7e760e51b82526004820152fd5b50346106445760403660031901126106445761081d61332f565b6040610827613345565b926001600160a01b0380931681526006602052209116600052602052602060ff604060002054166040519015158152f35b50346106445760203660031901126106445760ff6001604060043593848152600960205220015460a81c16156106b8576108936020916145f3565b6001600160801b0360405191168152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b857604082600292602094526009845220015460801c604051908152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85760036040836001600160801b0393602095526009855220015416604051908152f35b503461064457602036600319011261064457600435600060206040516109678161349b565b8281520152808252600960205260ff600160408420015460a81c16156106b857604082819281526009602052205464ffffffffff8251916109a78361349b565b818160a01c16835260c81c1660208201526109d8825180926020908164ffffffffff91828151168552015116910152565bf35b503461064457602080600319360112610ae6576004356109f981613aae565b50826001600160a01b0360085416916044604051809481937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa928315610aea578093610a69575b5050610a6560405192828493845283019061330a565b0390f35b909192503d8082843e610a7c81846134b7565b8201918381840312610ae65780519067ffffffffffffffff82116104a3570182601f82011215610ae657805191610ab2836134d9565b93610ac060405195866134b7565b838552858484010111610644575090610ade918480850191016132e7565b903880610a4f565b5080fd5b604051903d90823e3d90fd5b503461064457604036600319011261064457600435610b13613345565b610b1b613d98565b81835260099060209082825260ff600160408720015460a81c16156107ec57838552600382526001600160a01b03918260408720541693843303610f6e57610b62866145f3565b906001600160801b039081831680158015610c02575b50505050505081811615610bea5783610b9091613c53565b90811680610bb05760248460405190637e27328960e01b82526004820152fd5b8203610bba578380f35b6040516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b60248560405190633250574960e11b82526004820152fd5b610c0a613d98565b898b5282865260ff600160408d20015460a81c1615610f5757898b5282865260ff600160408d20015460a01c16610f3f5788156105e657610f2757888a52600385528660408b205416918289141580610f17575b610ef357610c6b8a6145f3565b8481168311610ec15750908a949392918a86528087526040862093610cd0610c9e8760028d89541698015460801c61461b565b8d8952838a52600260408a200190836fffffffffffffffffffffffffffffffff1983549260801b1691161781556138ec565b90610cec818a840151169282604081835116920151169061352d565b161115610e92575b8a86528652888a7f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d888b600160408b2001541694610d33818688614780565b604051908152a48033141580610e88575b610e1e575b813314159081610e13575b81610e08575b50610d97575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790604051868152a1388080808080610b78565b803b156104a357604051636fd110e960e01b8152600481018990523360248201526001600160a01b03881660448201526001600160801b0392909216606483015282908290608490829084905af1610df0575b80610d60565b610df99061344e565b610e04578538610dea565b8580fd5b905081141538610d5a565b823b15159150610d54565b803b156104a757604051636fd110e960e01b8152600481018a90523360248201526001600160a01b03891660448201526001600160801b03841660648201528490818160848183875af1610e74575b5050610d49565b610e7d9061344e565b6104a7578338610e6d565b50803b1515610d44565b8a86528087526040862060018101600160a01b60ff60a01b1982541617905560ff60f01b198154169055610cf4565b60405163287ecaef60e21b8152600481018c90526001600160801b038781166024830152919091166044820152606490fd5b60648a8a6040519163b34359d360e01b835260048301523360248301526044820152fd5b50610f218a6144dc565b15610c5e565b6024896040519063d2aabcd960e01b82526004820152fd5b60248a60405190634a5541ef60e01b82526004820152fd5b60248a6040519062b8e7e760e51b82526004820152fd5b60405163216caf0d60e01b815260048101879052336024820152604490fd5b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85760408264ffffffffff926020945260098452205460a01c16604051908152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b8576040826001600160a01b03926020945260098452205416604051908152f35b50346106445760203660031901126106445760ff6001604060209360043581526009855220015460a81c166040519015158152f35b50346106445760803660031901126106445761107b61332f565b611083613345565b906064359067ffffffffffffffff82116104a757366023830112156104a757816004013592846110b2856134d9565b936110c060405195866134b7565b8585523660248783010111610ae657856110eb96602460209301838801378501015260443591613941565b80f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b857600160408360ff93602095526009855220015460b01c166040519015158152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85761117890613bcc565b60405190600581101561118d57602092508152f35b602483634e487b7160e01b81526021600452fd5b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85760026040836001600160801b0393602095526009855220015416604051908152f35b50346106445760403660031901126106445761120d61332f565b6024359081151580920361063f576001600160a01b031690811561127f5733835260066020526040832082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602482604051907f5b08ba180000000000000000000000000000000000000000000000000000000082526004820152fd5b503461064457806003193601126106445760405190806002549160018360011c92600185169485156113b5575b60209586861081146113a15785885287949392918790821561137f575050600114611325575b5050611311925003836134b7565b610a6560405192828493845283019061330a565b90859250600282527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b85831061136757505061131193508201013880611303565b8054838901850152879450869390920191810161134f565b925093505061131194915060ff191682840152151560051b8201013880611303565b602483634e487b7160e01b81526022600452fd5b93607f16936112dd565b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85760408264ffffffffff926020945260098452205460c81c16604051908152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b85761144890613bcc565b9060058210159081611489576002831491821561149d575b8215611474575b6020836040519015158152f35b90915061148957506004602091143880611467565b80634e487b7160e01b602492526021600452fd5b506003831491506000611460565b5034610644576020906003198281360112610ae6576004359167ffffffffffffffff91828411610ae65761012084360391820112610ae6576114eb613d98565b60c48401359060221901811215610ae65783016004810135928311610ae65760248101908360061b80360383136104a757602490611528866137b7565b9561153660405197886134b7565b8652878601920101913683116104a757905b868383106117435750505050815190611560826137b7565b9261156e60405194856134b7565b828452601f1961157d846137b7565b0186835b82811061171f5750505064ffffffffff804216936001600160801b0392836115a882613ad1565b51511683808b6115b785613ad1565b51015116880116604051916115cb8361349b565b82528a8201526115da88613ad1565b526115e487613ad1565b5060019260015b8381106116b657505050505061160385600401613920565b9161161060248701613920565b9161161d6044880161385a565b6064880135926001600160a01b039081851680950361064457509288959261166e9895926116a3989561165560846116ae9d01613934565b948161166360a48c01613934565b976040519d8e613431565b168c52168c8b0152166040890152606088015215156080870152151560a086015260c085015260e084015260e4369101613805565b610100820152613df4565b604051908152f35b8089838d8180826116db8d6116cc8e9a8d613ade565b51511696600019890190613ade565b51015116916116ea868a613ade565b510151160116604051916116fd8361349b565b82528d82015261170d828c613ade565b52611718818b613ade565b50016115eb565b60405161172b8161349b565b60008152600083820152828289010152018790611581565b60409161175036856137cf565b815201910190611548565b503461064457602036600319011261064457606061016060405161177e81613462565b83815283602082015283604082015283838201528360808201528360a08201528360c08201528360e082015283610100820152836101208201526040516117c48161347f565b84815284602082015284604082015261014082015201526004358152600960205260ff600160408320015460a81c1615611acf5760043581526009602052604081209060405191610140830183811067ffffffffffffffff821117611ab9576118b59160029160405280546001600160a01b038116865264ffffffffff8160a01c16602087015264ffffffffff8160c81c16604087015260ff8160f01c161515606087015260f81c1515608086015260ff60018201546001600160a01b03811660a0880152818160a01c16151560c0880152818160a81c16151560e088015260b01c161515610100860152016138ec565b6101208301526118c6600435613bcc565b6005811015611aa557610160926119719260026119ad9314611a9a575b610120820151906001600160a01b0360a0840151169064ffffffffff60408501511660608501511515928561010081015115159460c082015115159360e0830151151595600435815260036020526001600160a01b036040822054166080604064ffffffffff60206001600160a01b038951169801511693600a602052209b01511515946040519d8e613462565b8d5260208d015260408c015260608b015260808a015260a089015260c088015260e087015261010086015261012085015261014084015261386e565b82820152610a65604051928392602084526001600160a01b0381511660208501526001600160a01b03602082015116604085015264ffffffffff604082015116606085015264ffffffffff60608201511660808501526080810151151560a085015260a0810151151560c08501526001600160a01b0360c08201511660e085015260e081015115156101008501526101008101511515610120850152610120810151151561014085015261014081015160406001600160801b03918281511685880152826020820151166101808801520151166101a085015201516101c0808401526101e08301906133d5565b8060608301526118e3565b602482634e487b7160e01b81526021600452fd5b634e487b7160e01b600052604160045260246000fd5b602460405162b8e7e760e51b81526004356004820152fd5b503461064457602080600319360112610ae65760043567ffffffffffffffff81116104a357611b1a9036906004016133a4565b9190611b24613d98565b83925b808410611b32578480f35b611b3d848284613834565b3593611b47613d98565b848652600980855260ff90600190828260408b20015460a81c1615611e2a57878952808752604089208281015460a01c841615611b965760248960405190634a5541ef60e01b82526004820152fd5b9790919293949596975460f81c611e1257611bc78160005260096020526001600160a01b0360406000205416331490565b15611df257611bd581613af2565b818a52828952611bea600260408c20016138ec565b906001600160801b0395868351168783161015611dda57838c52848b5260408c205460f01c1615611dc25791818a611c3b85898f9a999896611c318c99838793511661352d565b950151169061352d565b8386528482527f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5060408720916040835499600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c161785558b83169a8b15611da9575b60038096019c88169c8d6fffffffffffffffffffffffffffffffff198254161790556001600160a01b0392838092169b8c9789522054169889965260408d2001541694611cee8b8588614780565b604080518881526001600160801b0392831660208201529290911690820152606090a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78a604051838152a1813b611d52575b505050505050600101929190611b27565b813b15610e0457856084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1611d95575b80808080611d41565b611d9e9061344e565b61052b578438611d8c565b818601600160a01b60ff60a01b19825416179055611ca0565b602483604051906339c6dc7360e21b82526004820152fd5b602484604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b81526004810191909152336024820152604490fd5b6024906040519063fe19f19f60e01b82526004820152fd5b6024886040519062b8e7e760e51b82526004820152fd5b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b857604082611e8892610a659452600a6020522061386e565b6040519182916020835260208301906133d5565b503461064457602080600319360112610ae65760043590611ebb613d98565b8183526009815260ff600160408520015460a81c16156120ac57611ede82613bcc565b60058110156120985760048103611f075760248360405190634a5541ef60e01b82526004820152fd5b60038103611f27576024836040519063fe19f19f60e01b82526004820152fd5b60021461208057611f4e8260005260096020526001600160a01b0360406000205416331490565b15612061578183526009815260ff604084205460f01c161561204957818352600981526040832060ff60f01b19815416905582604051837f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f8380a2600383526001600160a01b03604083205416803b611ff1575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791604051908152a180f35b803b156104a357816024818580947f450154640000000000000000000000000000000000000000000000000000000083528960048401525af1612035575b80611fc2565b61203e9061344e565b6104a357823861202f565b602482604051906339c6dc7360e21b82526004820152fd5b60405163216caf0d60e01b815260048101839052336024820152604490fd5b602482604051906322cad1af60e11b82526004820152fd5b602484634e487b7160e01b81526021600452fd5b6024826040519062b8e7e760e51b82526004820152fd5b5034610644576020366003190112610644576004356001600160a01b03908181168091036104a35781835416338103612194575060085491816001600160a01b03198416176008556040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a260075460001981019081116121805760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a180f35b602482634e487b7160e01b81526011600452fd5b6040516331b339a960e21b81526001600160a01b03919091166004820152336024820152604490fd5b5034610644576020366003190112610644576121d761332f565b9080546001600160a01b0380821693338503612229576001600160a01b03199394501691829116178255337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808380a380f35b6040516331b339a960e21b81526001600160a01b0386166004820152336024820152604490fd5b5034610644576020366003190112610644576001600160a01b0361227261332f565b16801561228f578160409160209352600483522054604051908152f35b602482604051907f89c62b640000000000000000000000000000000000000000000000000000000082526004820152fd5b50346106445760203660031901126106445760206122df600435613aae565b6001600160a01b0360405191168152f35b50346106445760403660031901126106445767ffffffffffffffff6004358181116104a3576123239036906004016133a4565b90916024359081116104a75761233d9036906004016133a4565b612345613d98565b80830361273557845b838110612359578580f35b612364818587613834565b3590612371818688613834565b35875260036020526001600160a01b0360408820541661239a612395838688613834565b61385a565b906123a3613d98565b838952600960205260ff600160408b20015460a81c16156107ec57838952600960205260ff600160408b20015460a01c166107d45780156105e6576001600160801b0382161561271d5783895260036020526001600160a01b0360408a20541691828214158061270d575b6126e95761241b856145f3565b6001600160801b0381166001600160801b038316116126b9575090899291858452600960205260408420926124a16001600160a01b03855416946002809101546001600160801b036fffffffffffffffffffffffffffffffff1961248387608094851c61461b565b938c8b52600960205260408b2001938454931b1691161781556138ec565b6001600160801b036124c5816020840151169282604081835116920151169061352d565b161115612688575b86855260096020526001600160a01b036001604087200154166124fa6001600160801b0384168583614780565b83887f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d60206040516001600160801b0388168152a4803314158061267e575b612614575b833314159081612609575b816125fe575b5061258c575b505050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020600193604051908152a10161234e565b823b156104a757604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af16125e6575b8080612555565b6125ef9061344e565b6125fa5786386125df565b8680fd5b90508314153861254f565b843b15159150612549565b803b1561052b57604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af161266a575b505061253e565b6126739061344e565b61052b578438612663565b50803b1515612539565b86855260096020526040852060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556124cd565b60405163287ecaef60e21b8152600481018790526001600160801b03928316602482015291166044820152606490fd5b606485836040519163b34359d360e01b835260048301523360248301526044820152fd5b50612717856144dc565b1561240e565b6024846040519063d2aabcd960e01b82526004820152fd5b82604491604051917faec9344000000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b50346106445760203660031901126106445760ff6001604060043593848152600960205220015460a81c16156106b857610893602091614545565b50346106445760203660031901126106445760043590818152600960205260ff600160408320015460a81c16156120ac57806127e283613bcc565b926005841015611aa557600260209403612803575b50506040519015158152f35b815260098352604090205460f01c60ff16905038806127f7565b503461064457806003193601126106445760206001600160a01b0360085416604051908152f35b503461064457602080600319360112610ae65760043590612863613d98565b8183526009815260ff600160408520015460a81c16156120ac578183526009815260ff600160408520015460a01c16156129ee576128a0826144dc565b156120615781600052600381526001600160a01b0380604060002054166009835260ff60016040600020015460b01c161590816129e4575b50806129dc575b6129c4577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790836000526003835260406000205416918215928315612989575b846000526003825260406000206001600160a01b03198154169055846000604051927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4848152a1612971575080f35b60249060405190637e27328960e01b82526004820152fd5b6129aa85600052600560205260406000206001600160a01b03198154169055565b80600052600482526040600020600019815401905561291f565b60248360405190630da9b01360e01b82526004820152fd5b5060006128df565b90501515386128d8565b602482604051907f817cd6390000000000000000000000000000000000000000000000000000000082526004820152fd5b503461064457612a2e3661336f565b60405191602083019383851067ffffffffffffffff861117611ab9576110eb94604052858452613941565b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b857600160408360ff93602095526009855220015460a01c166040519015158152f35b503461064457602090816003193601126106445760043590612aca613d98565b81815260099283815260ff600160408420015460a81c1615612d315782825283815260408220600181015460a01c60ff1615612b185760248460405190634a5541ef60e01b82526004820152fd5b9284935460f81c611e1257612b438160005260096020526001600160a01b0360406000205416331490565b15611df257612b5181613af2565b93818452808352612b67600260408620016138ec565b916001600160801b03938484511685881610156120805781865282815260ff604087205460f01c161561204957612bb5878683612bab8a9b838a9c9b9c511661352d565b970151169061352d565b908286528381526040862091825494600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87161784556003898316948515612d17575b01988716988981546fffffffffffffffffffffffffffffffff19161790556001600160a01b038096168097600385528760408b205416978893865260408b20600101541693612c4a8c8487614780565b604080518981526001600160801b03938416602082015292909116908201528060608101037f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5091a4604051908382527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791a1823b612cc6578480f35b823b1561052b576084928591604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1612d08575b81818080808480f35b612d119061344e565b81612cff565b60018101600160a01b60ff60a01b19825416179055612bfa565b6024836040519062b8e7e760e51b82526004820152fd5b5034610644576003199060203683018113610ae6576004359167ffffffffffffffff93848411610ae65761014090843603011261064457612d87613d98565b60405193612d9485613431565b612da08460040161335b565b8552612dae6024850161335b565b6020860152612dbf604485016134f5565b604086015260648401356001600160a01b03811681036104a3576060860152612dea60848501613424565b6080860152612dfb60a48501613424565b60a0860152612e0c60c485016137a5565b60c086015260e4840135908111610ae65783019136602384011215610ae6576004830135612e39816137b7565b93612e4760405195866134b7565b8185526024602086019260061b820101933685116106445750602401905b838210612e875760206116ae886116a3898960e0840152610104369101613805565b82604091612e9536856137cf565b815201910190612e65565b503461064457806003193601126106445760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b5034610644576110eb612eed3661336f565b9161355c565b50346106445780600319360112610644576020600754604051908152f35b503461064457602036600319011261064457600435808252600960205260ff600160408420015460a81c16156106b857612f4a90613bcc565b9060058210156114895760208215838115612f6b575b506040519015158152f35b600191501482612f60565b50346106445760203660031901126106445760043590818152600960205260ff600160408320015460a81c16156120ac57602091604082828152600985522060ff815460f01c1680613004575b612fdb575b50506001600160801b0360405191168152f35b612ffd92506001600160801b036002612ff79201541691613af2565b9061352d565b3880612fc8565b5060ff600182015460a01c1615612fc3565b50346106445760403660031901126106445761303061332f565b60243561303c81613aae565b331515806130fc575b806130d2575b6130a25781906001600160a01b03809416938491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258680a48252600560205260408220906001600160a01b031982541617905580f35b60246040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152336004820152fd5b506001600160a01b038116845260066020526040842033855260205260ff6040852054161561304b565b50336001600160a01b0382161415613045565b50346106445760203660031901126106445760206122df600435613509565b50346106445780600319360112610644576040519080600191600154928360011c92600185169485156131e9575b60209586861081146113a15785885287949392918790821561137f57505060011461318f575050611311925003836134b7565b90859250600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8583106131d157505061131193508201013880611303565b805483890185015287945086939092019181016131b9565b93607f169361315c565b5034610644578060031936011261064457602060405167016345785d8a00008152f35b905034610ae6576020366003190112610ae6576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036104a357602092507f80ac58cd0000000000000000000000000000000000000000000000000000000081149081156132bd575b8115613293575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150143861328c565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150613285565b60005b8381106132fa5750506000910152565b81810151838201526020016132ea565b90602091613323815180928185528580860191016132e7565b601f01601f1916010190565b600435906001600160a01b038216820361063f57565b602435906001600160a01b038216820361063f57565b35906001600160a01b038216820361063f57565b606090600319011261063f576001600160a01b0390600435828116810361063f5791602435908116810361063f579060443590565b9181601f8401121561063f5782359167ffffffffffffffff831161063f576020808501948460051b01011161063f57565b90815180825260208080930193019160005b8281106133f5575050505090565b835180516001600160801b0316865282015164ffffffffff1685830152604090940193928101926001016133e7565b3590811515820361063f57565b610120810190811067ffffffffffffffff821117611ab957604052565b67ffffffffffffffff8111611ab957604052565b610180810190811067ffffffffffffffff821117611ab957604052565b6060810190811067ffffffffffffffff821117611ab957604052565b6040810190811067ffffffffffffffff821117611ab957604052565b90601f8019910116810190811067ffffffffffffffff821117611ab957604052565b67ffffffffffffffff8111611ab957601f01601f191660200190565b35906001600160801b038216820361063f57565b61351281613aae565b5060005260056020526001600160a01b036040600020541690565b6001600160801b03918216908216039190821161354657565b634e487b7160e01b600052601160045260246000fd5b906001600160a01b03809116801561378d57600091848352602091600383526040928284862054166009825260ff6001868820015460b01c16159081613783575b508061377b575b6137645786855260038152828486205416948733151593846136b4575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce794508761367c575b808352600484528683206001815401905581835260038452868320816001600160a01b0319825416179055877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef88519480a4878152a18316820361364e5750505050565b516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b61369d82600052600560205260406000206001600160a01b03198154169055565b8783526004845286832080546000190190556135ea565b91929380915090613723575b156136ce57908783926135c1565b8488876136eb576024915190637e27328960e01b82526004820152fd5b90517f177e802f0000000000000000000000000000000000000000000000000000000081523360048201526024810191909152604490fd5b503386148015613748575b806136c057508782526005835233848684205416146136c0565b5085825260068352848220338352835260ff858320541661372e565b602487855190630da9b01360e01b82526004820152fd5b5060016135a4565b905015153861359d565b6024604051633250574960e11b815260006004820152fd5b359064ffffffffff8216820361063f57565b67ffffffffffffffff8111611ab95760051b60200190565b919082604091031261063f576040516137e78161349b565b60206138008183956137f8816134f5565b8552016137a5565b910152565b919082604091031261063f5760405161381d8161349b565b602080829461382b8161335b565b84520135910152565b91908110156138445760051b0190565b634e487b7160e01b600052603260045260246000fd5b356001600160801b038116810361063f5790565b90815461387a816137b7565b9260409361388b60405191826134b7565b82815280946020809201926000526020600020906000935b8585106138b257505050505050565b600184819284516138c28161349b565b64ffffffffff87546001600160801b038116835260801c16838201528152019301940193916138a3565b906040516138f98161347f565b6040819360018154916001600160801b0392838116865260801c6020860152015416910152565b356001600160a01b038116810361063f5790565b35801515810361063f5790565b919061394e82828561355c565b803b61395b575b50505050565b6139b76001600160a01b03809216946040519384937f150b7a020000000000000000000000000000000000000000000000000000000096878652336004870152166024850152604484015260806064840152608483019061330a565b03906020816000938185885af190829082613a4d575b5050613a0457826139dc6145c3565b80519190826139fd5760248260405190633250574960e11b82526004820152fd5b9050602001fd5b7fffffffff000000000000000000000000000000000000000000000000000000001603613a35575038808080613955565b60249060405190633250574960e11b82526004820152fd5b909192506020813d602011613aa6575b81613a6a602093836134b7565b81010312610ae65751907fffffffff000000000000000000000000000000000000000000000000000000008216820361064457509038806139cd565b3d9150613a5d565b8060005260036020526001600160a01b0360406000205416908115612971575090565b8051156138445760200190565b80518210156138445760209160051b010190565b64ffffffffff8042169180600052602090600a602052613b15604060002061386e565b9084846020613b2385613ad1565b5101511611613bc257600052600960205260406000208484825460c81c161115613bad57506001600160801b039081613b5b82613ad1565b515116946001948594855b613b75575b5050505050505090565b828282613b828a88613ade565b5101511611613ba8578585889981613b9b849b89613ade565b5151160116980196613b66565b613b6b565b600201546001600160801b0316949350505050565b5050505050600090565b806000526009602052604060002060ff600182015460a01c16600014613bf3575050600490565b805460f81c613c4c575460a01c64ffffffffff164210613c4657613c1681613af2565b9060005260096020526001600160801b038060026040600020015416911610600014613c4157600190565b600290565b50600090565b5050600390565b916000828152602090600382526001600160a01b036040958187842054166009855260ff6001898620015460b01c16159081613d8e575b5080613d83575b613d6c579480967ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79596828552600386527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84838720541694859283613d34575b169283613d1e575b84875260038852808720846001600160a01b0319825416179055519580a4948152a1565b8387526004885280872060018154019055613cfa565b613d5586600052600560205260406000206001600160a01b03198154169055565b838852600489528488208054600019019055613cf2565b602486885190630da9b01360e01b82526004820152fd5b508181161515613c91565b9050151538613c8a565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003613dca57565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b90613e166001600160801b036040840151166020610100850151015190614636565b6001600160801b0381511660e084015164ffffffffff60c08601511682156144b2578015614488578151801561445e577f0000000000000000000000000000000000000000000000000000000000000000811161442d575064ffffffffff6020613e7f84613ad1565b510151168110156143d65750600090819082815184905b808210614345575050505064ffffffffff421664ffffffffff82168110156143055750506001600160801b03168082036142ce575050600754928360005260096020526040600020916001600160801b0381511660028401906fffffffffffffffffffffffffffffffff198254161790556001600160a01b036060830151166001840154750100000000000000000000000000000000000000000060808501511515918654937fffffffffffffffffff0000ff000000000000000000000000000000000000000076ff0000000000000000000000000000000000000000000060a0890151151560b01b16921617171760018601556001600160a01b0384511678ffffffffff000000000000000000000000000000000000000060c086015160a01b169060e0860151937fff000000000000000000000000000000000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007dffffffffff0000000000000000000000000000000000000000000000000060206140328951996000198b0190613ade565b51015160c81b169560f01b16911617171717845560005b818110614229575050600185016007556001600160a01b03602083015116801561378d5761407f866001600160a01b0392613c53565b166141f8576140aa6001600160a01b036060840151166001600160801b03835116903090339061470f565b6001600160801b03602082015116806141c8575b507ffeb1cb9ce021c8bd5fb1eb836e6284c68866fa32d1d844238de19955238f807660206001600160a01b03845116926001600160a01b038286015116946001600160a01b03606082015116966141bd61419e60808401511515928c60a086015115156001600160a01b0361010060e089015194549864ffffffffff6040519a6141478c61349b565b818160a01c168c5260c81c168c8b015201515116956001600160801b036040519a8b9a610140958c5233828d01528281511660408d015201511660608a0152608089015260a08801528060c08801528601906133d5565b9260e08501906020908164ffffffffff91828151168552015116910152565b6101208301520390a4565b6141f2906001600160a01b036060850151166001600160a01b03610100860151511690339061470f565b386140be565b60246040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260006004820152fd5b86600052600a6020526040600020906142468160e0870151613ade565b51825468010000000000000000811015611ab9576001810180855581101561384457600193600052602060002001906001600160801b038151167fffffffffffffffffffffff00000000000000000000000000000000000000000074ffffffffff000000000000000000000000000000006020855494015160801b1692161717905501614049565b60449250604051917f6375ff1300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b6040517f210aec0e00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b9193509193614369906001600160801b036143608588613ade565b5151169061461b565b9364ffffffffff80602061437d8685613ade565b5101511694168085111561439957506001849301909291613e96565b8385606492604051927fd97494c6000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b64ffffffffff60206143e784613ad1565b5101516040517ff1fb2cc500000000000000000000000000000000000000000000000000000000815264ffffffffff938416600482015291169091166024820152604490fd5b602490604051907f73627f740000000000000000000000000000000000000000000000000000000082526004820152fd5b60046040517f7ea4ccdf000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd572dbcb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6095d3bc000000000000000000000000000000000000000000000000000000008152fd5b60009080825260036020526001600160a01b038060408420541692833314938415614521575b5050821561450f57505090565b90915061451c3392613509565b161490565b60ff9294509060409181526006602052818120338252602052205416913880614502565b80600052600960205261455e60026040600020016138ec565b816000526009602052604060002060ff600182015460a01c1660001461459157506001600160801b039150602001511690565b5460f81c6145a657506145a390613af2565b90565b6145a391506001600160801b03604081835116920151169061352d565b3d156145ee573d906145d4826134d9565b916145e260405193846134b7565b82523d6000602084013e565b606090565b6145a39061460081614545565b90600052600960205260026040600020015460801c9061352d565b9190916001600160801b038080941691160191821161354657565b919091604051906146468261349b565b600091828152826020820152936001600160801b03928383169182156146f05767016345785d8a00008082116146b95750614682859184614871565b16602087019281845211156146a5575090826146a09251169061352d565b168252565b80634e487b7160e01b602492526001600452fd5b60449250604051917f4fea5c1a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b50939450505050604051906147048261349b565b808252602082015290565b9290604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff841117611ab95761477e926040526147d5565b565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b0392909216602483015260448083019390935291815261477e916147d56064836134b7565b6001600160a01b031690614800600080836020829551910182875af16147f96145c3565b9084614920565b908151918215159283614849575b5050506148185750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312610ae6576020015190811591821503610644575038808061480e565b9091906000198382098382029182808310920391808303921461490f57670de0b6b3a764000090818310156148d857947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b60449086604051917f5173648d00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5050670de0b6b3a764000090049150565b9061495f575080511561493557805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b815115806149aa575b614970575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b1561496856fea164736f6c6343000817000a"; + hex"60c034620003dc576001600160401b0390601f601f1962004e243881900383810183168501919086831186841017620002f557808692606094604052833981010312620003dc5782516001600160a01b038082169590929091869003620003dc5760209485810151938416809403620003dc57604001519362000081620003e1565b95601e87527f5361626c696572205632204c6f636b7570205472616e63686564204e4654000081880152620000b5620003e1565b9060118252705341422d56322d4c4f434b55502d54524160781b81830152306080528751858111620002f5576001988954908a82811c92168015620003d1575b84831014620002d45781868493116200037b575b50839086831160011462000317576000926200030b575b5050600019600383901b1c191690891b1788555b8151948511620002f557600254938885811c95168015620002ea575b82861014620002d457848487961162000277575b50819385116001146200020d57505060009262000201575b5050600019600383901b1c191690841b176002555b60018060a01b03198481600054161760005560085416176008556040519260007fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a360a052600755614a22908162000402823960805181613e04015260a051818181612f190152613eaa0152f35b0151905038806200017c565b88959392919316600260005283600020936000905b8282106200025d575050841162000243575b505050811b0160025562000191565b015160001960f88460031b161c1916905538808062000234565b8484015186558a9790950194938401939081019062000222565b9091929394506002600052826000208580880160051c820192858910620002ca575b9188978c9297969594930160051c01915b828110620002ba57505062000164565b600081558897508b9101620002aa565b9250819262000299565b634e487b7160e01b600052602260045260246000fd5b94607f169462000150565b634e487b7160e01b600052604160045260246000fd5b01519050388062000120565b90878c94169184600052856000209260005b878282106200036457505084116200034a575b505050811b01885562000134565b015160001960f88460031b161c191690553880806200033c565b8385015186558f9790950194938401930162000329565b9091508a600052836000208680850160051c820192868610620003c7575b918d91869594930160051c01915b828110620003b757505062000109565b600081558594508d9101620003a7565b9250819262000399565b91607f1691620000f5565b600080fd5b60408051919082016001600160401b03811183821017620002f55760405256fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461327757508063027b67441461325457806306fdde031461318f578063081812fc14613170578063095ea7b3146130775780631400ecec14612fd75780631c1cdd4c14612f725780631e99d56914612f5457806323b872dd14612f3c5780632fe4304114612f0157806332fbe22b14612da957806340e58ee514612b0b578063425d30dd14612aba57806342842e0e14612a8057806342966c68146128a957806344267570146128825780634857501f1461280c5780634869e12d146127d15780634cc55e111461230e5780636352211e146122de5780636d0cee75146122de57806370a082311461226e57806375829def146121db5780637cad6cd1146120e15780637de6b1db14611eba5780637f5799f914611e5f5780638659c27014611b05578063894e9a0d14611779578063897f362b146114c95780638f69b9931461142d5780639067b677146113dd57806395d89b41146112ce578063a22cb46514611211578063a80fc071146111bf578063ad35efd41461115d578063b25645691461110c578063b88d4fde1461107f578063b8a3be661461104a578063b971302a14610ffb578063bc2be1be14610fab578063c156a11d14610afc578063c87b56dd146109e0578063cc364f4814610948578063d4dbd20b146108f6578063d511609f146108aa578063d975dfed1461085e578063e985e9c514610809578063ea5ead191461070f578063eac8f5b8146106bd578063f590c1761461065b578063f851a440146106355763fdd46d601461025d57600080fd5b34610632576060366003190112610632576004359061027a6133a6565b91604435926001600160801b038085169182860361062d5761029a613dfa565b83855260099560209387855260ff600160408920015460a81c16156106165785875287855260ff600160408920015460a01c166105fe576001600160a01b039081841680156105e65781156105ce57878952600387528260408a2054169283821415806105be575b61059a5761030f89614655565b8781168411610568575097899a888b999a83809d5282825260408b209988828c54169b6002015460801c906103439161467d565b858d5284845260408d20600201908282549160801b6fffffffffffffffffffffffffffffffff1916911617815561037990613949565b908084830151169181808251169160400151166103959161358e565b161115927f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d93610539575b848c528252600160408c20015416946103da818a886147e2565b604051908152a4803314158061052f575b6104c1575b8333141590816104b6575b816104ab575b50610435575b837ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78688604051908152a180f35b823b156104a757604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af161048f575b8080610407565b610498906134af565b6104a3578238610488565b8280fd5b8380fd5b905083141538610401565b843b151591506103fb565b803b1561052b57604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af1610517575b50506103f0565b610520906134af565b61052b578438610510565b8480fd5b50803b15156103eb565b848c5280835260408c2060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556103c0565b60405163287ecaef60e21b8152600481018b90526001600160801b038781166024830152919091166044820152606490fd5b606489836040519163b34359d360e01b835260048301523360248301526044820152fd5b506105c88961453e565b15610302565b6024886040519063d2aabcd960e01b82526004820152fd5b60248860405190630ff7ee2d60e31b82526004820152fd5b60248660405190634a5541ef60e01b82526004820152fd5b6024866040519062b8e7e760e51b82526004820152fd5b600080fd5b80fd5b50346106325780600319360112610632576001600160a01b036020915416604051908152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a657816040916020935260098352205460f81c6040519015158152f35b6024906040519062b8e7e760e51b82526004820152fd5b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65760016040836001600160a01b0393602095526009855220015416604051908152f35b5034610632576040366003190112610632576004359061072d6133a6565b9161073781614655565b92610740613dfa565b81835260099360209185835260ff600160408720015460a81c16156107f25783855285835260ff600160408720015460a01c166107da576001600160a01b03918282169283156107c2576001600160801b03938483169081156105ce57878952600387528260408a2054169283821415806105be5761059a5761030f89614655565b60248660405190630ff7ee2d60e31b82526004820152fd5b60248460405190634a5541ef60e01b82526004820152fd5b6024846040519062b8e7e760e51b82526004820152fd5b503461063257604036600319011261063257610823613390565b604061082d6133a6565b926001600160a01b0380931681526006602052209116600052602052602060ff604060002054166040519015158152f35b50346106325760203660031901126106325760ff6001604060043593848152600960205220015460a81c16156106a657610899602091614655565b6001600160801b0360405191168152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a657604082600292602094526009845220015460801c604051908152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65760036040836001600160801b0393602095526009855220015416604051908152f35b5034610632576020366003190112610632576004356000602060405161096d816134fc565b8281520152808252600960205260ff600160408420015460a81c16156106a657604082819281526009602052205464ffffffffff8251916109ad836134fc565b818160a01c16835260c81c1660208201526109de825180926020908164ffffffffff91828151168552015116910152565bf35b503461063257602080600319360112610aec576004356109ff81613b0b565b50826001600160a01b0360085416916044604051809481937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa928315610af0578093610a6f575b5050610a6b60405192828493845283019061336b565b0390f35b909192503d8082843e610a828184613518565b8201918381840312610aec5780519067ffffffffffffffff82116104a3570182601f82011215610aec57805191610ab88361353a565b93610ac66040519586613518565b838552858484010111610632575090610ae491848085019101613348565b903880610a55565b5080fd5b604051903d90823e3d90fd5b503461063257604036600319011261063257600435610b196133a6565b610b21613dfa565b81835260099060209082825260ff600160408720015460a81c16156107f257838552600382526001600160a01b03918260408720541693843303610f8c57610b6886614655565b906001600160801b039081831680158015610c08575b50505050505081811615610bf05783610b9691613cb9565b90811680610bb65760248460405190637e27328960e01b82526004820152fd5b8203610bc0578380f35b6040516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b60248560405190633250574960e11b82526004820152fd5b610c10613dfa565b898b5282865260ff600160408d20015460a81c1615610f7557898b5282865260ff600160408d20015460a01c16610f5d578815610f4557610f2d57888a52600385528660408b205416918289141580610f1d575b610ef957610c718a614655565b8481168311610ec75750908a949392918a86528087526040862093610cd6610ca48760028d89541698015460801c61467d565b8d8952838a52600260408a200190836fffffffffffffffffffffffffffffffff1983549260801b169116178155613949565b90610cf2818a840151169282604081835116920151169061358e565b161115610e98575b8a86528652888a7f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d888b600160408b2001541694610d398186886147e2565b604051908152a48033141580610e8e575b610e24575b813314159081610e19575b81610e0e575b50610d9d575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce790604051868152a1388080808080610b7e565b803b156104a357604051636fd110e960e01b8152600481018990523360248201526001600160a01b03881660448201526001600160801b0392909216606483015282908290608490829084905af1610df6575b80610d66565b610dff906134af565b610e0a578538610df0565b8580fd5b905081141538610d60565b823b15159150610d5a565b803b156104a757604051636fd110e960e01b8152600481018a90523360248201526001600160a01b03891660448201526001600160801b03841660648201528490818160848183875af1610e7a575b5050610d4f565b610e83906134af565b6104a7578338610e73565b50803b1515610d4a565b8a86528087526040862060018101600160a01b60ff60a01b1982541617905560ff60f01b198154169055610cfa565b60405163287ecaef60e21b8152600481018c90526001600160801b038781166024830152919091166044820152606490fd5b60648a8a6040519163b34359d360e01b835260048301523360248301526044820152fd5b50610f278a61453e565b15610c64565b6024896040519063d2aabcd960e01b82526004820152fd5b60248a60405190630ff7ee2d60e31b82526004820152fd5b60248a60405190634a5541ef60e01b82526004820152fd5b60248a6040519062b8e7e760e51b82526004820152fd5b60405163216caf0d60e01b815260048101879052336024820152604490fd5b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65760408264ffffffffff926020945260098452205460a01c16604051908152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a6576040826001600160a01b03926020945260098452205416604051908152f35b50346106325760203660031901126106325760ff6001604060209360043581526009855220015460a81c166040519015158152f35b503461063257608036600319011261063257611099613390565b6110a16133a6565b906064359067ffffffffffffffff82116104a757366023830112156104a757816004013592846110d08561353a565b936110de6040519586613518565b8585523660248783010111610aec57856111099660246020930183880137850101526044359161399e565b80f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a657600160408360ff93602095526009855220015460b01c166040519015158152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65761119690613c32565b6040519060058110156111ab57602092508152f35b602483634e487b7160e01b81526021600452fd5b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65760026040836001600160801b0393602095526009855220015416604051908152f35b50346106325760403660031901126106325761122b613390565b6024359081151580920361062d576001600160a01b031690811561129d5733835260066020526040832082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602482604051907f5b08ba180000000000000000000000000000000000000000000000000000000082526004820152fd5b503461063257806003193601126106325760405190806002549160018360011c92600185169485156113d3575b60209586861081146113bf5785885287949392918790821561139d575050600114611343575b505061132f92500383613518565b610a6b60405192828493845283019061336b565b90859250600282527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace5b85831061138557505061132f93508201013880611321565b8054838901850152879450869390920191810161136d565b925093505061132f94915060ff191682840152151560051b8201013880611321565b602483634e487b7160e01b81526022600452fd5b93607f16936112fb565b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65760408264ffffffffff926020945260098452205460c81c16604051908152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a65761146690613c32565b90600582101590816114a757600283149182156114bb575b8215611492575b6020836040519015158152f35b9091506114a757506004602091143880611485565b80634e487b7160e01b602492526021600452fd5b50600383149150600061147e565b5034610632576020906003198281360112610aec576004359167ffffffffffffffff91828411610aec5761012084360391820112610aec57611509613dfa565b60c48401359060221901811215610aec5783016004810135928311610aec5760248101908360061b80360383136104a75760249061154686613814565b956115546040519788613518565b8652878601920101913683116104a757905b86838310611761575050505081519061157e82613814565b9261158c6040519485613518565b828452601f1961159b84613814565b0186835b82811061173d5750505064ffffffffff804216936001600160801b0392836115c682613b2e565b51511683808b6115d585613b2e565b51015116880116604051916115e9836134fc565b82528a8201526115f888613b2e565b5261160287613b2e565b5060019260015b8381106116d45750505050506116218560040161397d565b9161162e6024870161397d565b9161163b604488016138b7565b6064880135926001600160a01b039081851680950361063257509288959261168c9895926116c1989561167360846116cc9d01613991565b948161168160a48c01613991565b976040519d8e613492565b168c52168c8b0152166040890152606088015215156080870152151560a086015260c085015260e084015260e4369101613862565b610100820152613e56565b604051908152f35b8089838d8180826116f98d6116ea8e9a8d613b3b565b51511696600019890190613b3b565b5101511691611708868a613b3b565b5101511601166040519161171b836134fc565b82528d82015261172b828c613b3b565b52611736818b613b3b565b5001611609565b604051611749816134fc565b6000815260008382015282828901015201879061159f565b60409161176e368561382c565b815201910190611566565b503461063257602036600319011261063257606061016060405161179c816134c3565b83815283602082015283604082015283838201528360808201528360a08201528360c08201528360e082015283610100820152836101208201526040516117e2816134e0565b84815284602082015284604082015261014082015201526004358152600960205260ff600160408320015460a81c1615611aed5760043581526009602052604081209060405191610140830183811067ffffffffffffffff821117611ad7576118d39160029160405280546001600160a01b038116865264ffffffffff8160a01c16602087015264ffffffffff8160c81c16604087015260ff8160f01c161515606087015260f81c1515608086015260ff60018201546001600160a01b03811660a0880152818160a01c16151560c0880152818160a81c16151560e088015260b01c16151561010086015201613949565b6101208301526118e4600435613c32565b6005811015611ac3576101609261198f9260026119cb9314611ab8575b610120820151906001600160a01b0360a08401511664ffffffffff6040850151169060608501511515908560c081015115159260e0820151151594610100830151151596600435815260036020526001600160a01b036040822054166080604064ffffffffff60206001600160a01b038951169801511693600a602052209b01511515946040519d8e6134c3565b8d5260208d015260408c015260608b015260808a015260a089015260c088015260e08701526101008601526101208501526101408401526138cb565b82820152610a6b604051928392602084526001600160a01b0381511660208501526001600160a01b03602082015116604085015264ffffffffff604082015116606085015264ffffffffff60608201511660808501526080810151151560a085015260a0810151151560c08501526001600160a01b0360c08201511660e085015260e081015115156101008501526101008101511515610120850152610120810151151561014085015261014081015160406001600160801b03918281511685880152826020820151166101808801520151166101a085015201516101c0808401526101e0830190613436565b806060830152611901565b602482634e487b7160e01b81526021600452fd5b634e487b7160e01b600052604160045260246000fd5b602460405162b8e7e760e51b81526004356004820152fd5b503461063257602080600319360112610aec5760043567ffffffffffffffff81116104a357611b38903690600401613405565b9190611b42613dfa565b83925b808410611b50578480f35b611b5b848284613891565b3593611b65613dfa565b848652600980855260ff90600190828260408b20015460a81c1615611e4857878952808752604089208281015460a01c841615611bb45760248960405190634a5541ef60e01b82526004820152fd5b9790919293949596975460f81c611e3057611be58160005260096020526001600160a01b0360406000205416331490565b15611e1057611bf381613b4f565b818a52828952611c08600260408c2001613949565b906001600160801b0395868351168783161015611df857838c52848b5260408c205460f01c1615611de05791818a611c5985898f9a999896611c4f8c99838793511661358e565b950151169061358e565b8386528482527f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5060408720916040835499600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c161785558b83169a8b15611dc7575b60038096019c88169c8d6fffffffffffffffffffffffffffffffff198254161790556001600160a01b0392838092169b8c9789522054169889965260408d2001541694611d0c8b85886147e2565b604080518881526001600160801b0392831660208201529290911690820152606090a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78a604051838152a1813b611d70575b505050505050600101929190611b45565b813b15610e0a57856084928195604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1611db3575b80808080611d5f565b611dbc906134af565b61052b578438611daa565b818601600160a01b60ff60a01b19825416179055611cbe565b602483604051906339c6dc7360e21b82526004820152fd5b602484604051906322cad1af60e11b82526004820152fd5b60405163216caf0d60e01b81526004810191909152336024820152604490fd5b6024906040519063fe19f19f60e01b82526004820152fd5b6024886040519062b8e7e760e51b82526004820152fd5b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a657604082611ea692610a6b9452600a602052206138cb565b604051918291602083526020830190613436565b503461063257602080600319360112610aec5760043590611ed9613dfa565b8183526009815260ff600160408520015460a81c16156120ca57611efc82613c32565b60058110156120b65760048103611f255760248360405190634a5541ef60e01b82526004820152fd5b60038103611f45576024836040519063fe19f19f60e01b82526004820152fd5b60021461209e57611f6c8260005260096020526001600160a01b0360406000205416331490565b1561207f578183526009815260ff604084205460f01c161561206757818352600981526040832060ff60f01b19815416905582604051837f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f8380a2600383526001600160a01b03604083205416803b61200f575b5050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791604051908152a180f35b803b156104a357816024818580947f450154640000000000000000000000000000000000000000000000000000000083528960048401525af1612053575b80611fe0565b61205c906134af565b6104a357823861204d565b602482604051906339c6dc7360e21b82526004820152fd5b60405163216caf0d60e01b815260048101839052336024820152604490fd5b602482604051906322cad1af60e11b82526004820152fd5b602484634e487b7160e01b81526021600452fd5b6024826040519062b8e7e760e51b82526004820152fd5b5034610632576020366003190112610632576004356001600160a01b03908181168091036104a357818354163381036121b2575060085491816001600160a01b03198416176008556040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a2600754600019810190811161219e5760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a180f35b602482634e487b7160e01b81526011600452fd5b6040516331b339a960e21b81526001600160a01b03919091166004820152336024820152604490fd5b5034610632576020366003190112610632576121f5613390565b9080546001600160a01b0380821693338503612247576001600160a01b03199394501691829116178255337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808380a380f35b6040516331b339a960e21b81526001600160a01b0386166004820152336024820152604490fd5b5034610632576020366003190112610632576001600160a01b03612290613390565b1680156122ad578160409160209352600483522054604051908152f35b602482604051907f89c62b640000000000000000000000000000000000000000000000000000000082526004820152fd5b50346106325760203660031901126106325760206122fd600435613b0b565b6001600160a01b0360405191168152f35b50346106325760403660031901126106325767ffffffffffffffff6004358181116104a357612341903690600401613405565b9091602490813590811161052b5761235d903690600401613405565b612368929192613dfa565b80840361279b57855b84811061237c578680f35b612387818688613891565b3590612394818789613891565b35885260036020526001600160a01b036040892054166123bd6123b8838689613891565b6138b7565b906123c6613dfa565b838a52600960205260ff600160408c20015460a81c161561278557838a52600960205260ff600160408c20015460a01c1661276e578015612757576001600160801b0382161561274057838a5260036020526001600160a01b0360408b205416918282141580612730575b61270c5761243e85614655565b6001600160801b0381166001600160801b038316116126dc5750908a9291858452600960205260408420926124c46001600160a01b03855416946002809101546001600160801b036fffffffffffffffffffffffffffffffff196124a687608094851c61467d565b938c8b52600960205260408b2001938454931b169116178155613949565b6001600160801b036124e8816020840151169282604081835116920151169061358e565b1611156126ab575b86855260096020526001600160a01b0360016040872001541661251d6001600160801b03841685836147e2565b83887f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d60206040516001600160801b0388168152a480331415806126a1575b612637575b83331415908161262c575b81612621575b506125af575b505050507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020600193604051908152a101612371565b823b156104a757604051636fd110e960e01b8152600481018790523360248201526001600160a01b039290921660448301526001600160801b031660648201529082908290608490829084905af1612609575b8080612578565b612612906134af565b61261d578738612602565b8780fd5b905083141538612572565b843b1515915061256c565b803b1561052b57604051636fd110e960e01b8152600481018890523360248201526001600160a01b03841660448201526001600160801b03831660648201528590818160848183875af161268d575b5050612561565b612696906134af565b61052b578438612686565b50803b151561255c565b86855260096020526040852060018101600160a01b60ff60a01b1982541617905560ff60f01b1981541690556124f0565b60405163287ecaef60e21b8152600481018790526001600160801b03928316602482015291166044820152606490fd5b60648583896040519263b34359d360e01b8452600484015233908301526044820152fd5b5061273a8561453e565b15612431565b85846040519063d2aabcd960e01b82526004820152fd5b858460405190630ff7ee2d60e31b82526004820152fd5b858460405190634a5541ef60e01b82526004820152fd5b85846040519062b8e7e760e51b82526004820152fd5b8390604492604051927faec934400000000000000000000000000000000000000000000000000000000084526004840152820152fd5b50346106325760203660031901126106325760ff6001604060043593848152600960205220015460a81c16156106a6576108996020916145a7565b50346106325760203660031901126106325760043590818152600960205260ff600160408320015460a81c16156120ca578061284783613c32565b926005841015611ac357600260209403612868575b50506040519015158152f35b815260098352604090205460f01c60ff169050388061285c565b503461063257806003193601126106325760206001600160a01b0360085416604051908152f35b503461063257602080600319360112610aec57600435906128c8613dfa565b8183526009815260ff600160408520015460a81c16156120ca578183526009815260ff600160408520015460a01c1615612a4f576129058261453e565b1561207f5781600052600381526001600160a01b038060406000205416151580612a47575b80612a2d575b612a15577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7908360005260038352604060002054169182159283156129da575b846000526003825260406000206001600160a01b03198154169055846000604051927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4848152a16129c2575080f35b60249060405190637e27328960e01b82526004820152fd5b6129fb85600052600560205260406000206001600160a01b03198154169055565b806000526004825260406000206000198154019055612970565b60248360405190630da9b01360e01b82526004820152fd5b506009825260ff60016040600020015460b01c1615612930565b50600061292a565b602482604051907f817cd6390000000000000000000000000000000000000000000000000000000082526004820152fd5b503461063257612a8f366133d0565b60405191602083019383851067ffffffffffffffff861117611ad7576111099460405285845261399e565b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a657600160408360ff93602095526009855220015460a01c166040519015158152f35b503461063257602090816003193601126106325760043590612b2b613dfa565b81815260099283815260ff600160408420015460a81c1615612d925782825283815260408220600181015460a01c60ff1615612b795760248460405190634a5541ef60e01b82526004820152fd5b9284935460f81c611e3057612ba48160005260096020526001600160a01b0360406000205416331490565b15611e1057612bb281613b4f565b93818452808352612bc860026040862001613949565b916001600160801b039384845116858816101561209e5781865282815260ff604087205460f01c161561206757612c16878683612c0c8a9b838a9c9b9c511661358e565b970151169061358e565b908286528381526040862091825494600160f81b7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87161784556003898316948515612d78575b01988716988981546fffffffffffffffffffffffffffffffff19161790556001600160a01b038096168097600385528760408b205416978893865260408b20600101541693612cab8c84876147e2565b604080518981526001600160801b03938416602082015292909116908201528060608101037f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5091a4604051908382527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791a1823b612d27578480f35b823b1561052b576084928591604051978896879563c6f5ed0f60e01b875260048701526024860152604485015260648401525af1612d69575b81818080808480f35b612d72906134af565b81612d60565b60018101600160a01b60ff60a01b19825416179055612c5b565b6024836040519062b8e7e760e51b82526004820152fd5b5034610632576003199060203683018113610aec576004359167ffffffffffffffff93848411610aec5761014090843603011261063257612de8613dfa565b60405193612df585613492565b612e01846004016133bc565b8552612e0f602485016133bc565b6020860152612e2060448501613556565b604086015260648401356001600160a01b03811681036104a3576060860152612e4b60848501613485565b6080860152612e5c60a48501613485565b60a0860152612e6d60c48501613802565b60c086015260e4840135908111610aec5783019136602384011215610aec576004830135612e9a81613814565b93612ea86040519586613518565b8185526024602086019260061b820101933685116106325750602401905b838210612ee85760206116cc886116c1898960e0840152610104369101613862565b82604091612ef6368561382c565b815201910190612ec6565b503461063257806003193601126106325760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461063257611109612f4e366133d0565b916135bd565b50346106325780600319360112610632576020600754604051908152f35b503461063257602036600319011261063257600435808252600960205260ff600160408420015460a81c16156106a657612fab90613c32565b9060058210156114a75760208215838115612fcc575b506040519015158152f35b600191501482612fc1565b50346106325760203660031901126106325760043590818152600960205260ff600160408320015460a81c16156120ca57602091604082828152600985522060ff815460f01c1680613065575b61303c575b50506001600160801b0360405191168152f35b61305e92506001600160801b0360026130589201541691613b4f565b9061358e565b3880613029565b5060ff600182015460a01c1615613024565b503461063257604036600319011261063257613091613390565b60243561309d81613b0b565b3315158061315d575b80613133575b6131035781906001600160a01b03809416938491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258680a48252600560205260408220906001600160a01b031982541617905580f35b60246040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152336004820152fd5b506001600160a01b038116845260066020526040842033855260205260ff604085205416156130ac565b50336001600160a01b03821614156130a6565b50346106325760203660031901126106325760206122fd60043561356a565b50346106325780600319360112610632576040519080600191600154928360011c926001851694851561324a575b60209586861081146113bf5785885287949392918790821561139d5750506001146131f057505061132f92500383613518565b90859250600182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b85831061323257505061132f93508201013880611321565b8054838901850152879450869390920191810161321a565b93607f16936131bd565b5034610632578060031936011261063257602060405167016345785d8a00008152f35b905034610aec576020366003190112610aec576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036104a357602092507f80ac58cd00000000000000000000000000000000000000000000000000000000811490811561331e575b81156132f4575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386132ed565b7f5b5e139f00000000000000000000000000000000000000000000000000000000811491506132e6565b60005b83811061335b5750506000910152565b818101518382015260200161334b565b9060209161338481518092818552858086019101613348565b601f01601f1916010190565b600435906001600160a01b038216820361062d57565b602435906001600160a01b038216820361062d57565b35906001600160a01b038216820361062d57565b606090600319011261062d576001600160a01b0390600435828116810361062d5791602435908116810361062d579060443590565b9181601f8401121561062d5782359167ffffffffffffffff831161062d576020808501948460051b01011161062d57565b90815180825260208080930193019160005b828110613456575050505090565b835180516001600160801b0316865282015164ffffffffff168583015260409094019392810192600101613448565b3590811515820361062d57565b610120810190811067ffffffffffffffff821117611ad757604052565b67ffffffffffffffff8111611ad757604052565b610180810190811067ffffffffffffffff821117611ad757604052565b6060810190811067ffffffffffffffff821117611ad757604052565b6040810190811067ffffffffffffffff821117611ad757604052565b90601f8019910116810190811067ffffffffffffffff821117611ad757604052565b67ffffffffffffffff8111611ad757601f01601f191660200190565b35906001600160801b038216820361062d57565b61357381613b0b565b5060005260056020526001600160a01b036040600020541690565b6001600160801b0391821690821603919082116135a757565b634e487b7160e01b600052601160045260246000fd5b906001600160a01b0380911680156137ea57600091848352602091600383526040928284862054161515806137e2575b806137ca575b6137b3578685526003815282848620541694873315159384613703575b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79450876136cb575b808352600484528683206001815401905581835260038452868320816001600160a01b0319825416179055877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef88519480a4878152a18316820361369d5750505050565b516364283d7b60e01b81526001600160a01b0392831660048201526024810193909352166044820152606490fd5b6136ec82600052600560205260406000206001600160a01b03198154169055565b878352600484528683208054600019019055613639565b91929380915090613772575b1561371d5790878392613610565b84888761373a576024915190637e27328960e01b82526004820152fd5b90517f177e802f0000000000000000000000000000000000000000000000000000000081523360048201526024810191909152604490fd5b503386148015613797575b8061370f575087825260058352338486842054161461370f565b5085825260068352848220338352835260ff858320541661377d565b602487855190630da9b01360e01b82526004820152fd5b506009815260ff6001858720015460b01c16156135f3565b5060016135ed565b6024604051633250574960e11b815260006004820152fd5b359064ffffffffff8216820361062d57565b67ffffffffffffffff8111611ad75760051b60200190565b919082604091031261062d57604051613844816134fc565b602061385d81839561385581613556565b855201613802565b910152565b919082604091031261062d5760405161387a816134fc565b6020808294613888816133bc565b84520135910152565b91908110156138a15760051b0190565b634e487b7160e01b600052603260045260246000fd5b356001600160801b038116810361062d5790565b9081546138d781613814565b926040936138e86040519182613518565b82815280946020809201926000526020600020906000935b85851061390f57505050505050565b6001848192845161391f816134fc565b64ffffffffff87546001600160801b038116835260801c1683820152815201930194019391613900565b90604051613956816134e0565b6040819360018154916001600160801b0392838116865260801c6020860152015416910152565b356001600160a01b038116810361062d5790565b35801515810361062d5790565b91906139ab8282856135bd565b803b6139b8575b50505050565b613a146001600160a01b03809216946040519384937f150b7a020000000000000000000000000000000000000000000000000000000096878652336004870152166024850152604484015260806064840152608483019061336b565b03906020816000938185885af190829082613aaa575b5050613a615782613a39614625565b8051919082613a5a5760248260405190633250574960e11b82526004820152fd5b9050602001fd5b7fffffffff000000000000000000000000000000000000000000000000000000001603613a925750388080806139b2565b60249060405190633250574960e11b82526004820152fd5b909192506020813d602011613b03575b81613ac760209383613518565b81010312610aec5751907fffffffff00000000000000000000000000000000000000000000000000000000821682036106325750903880613a2a565b3d9150613aba565b8060005260036020526001600160a01b03604060002054169081156129c2575090565b8051156138a15760200190565b80518210156138a15760209160051b010190565b64ffffffffff8042169180600052602090600a602052613b7260406000206138cb565b9084846020613b8085613b2e565b5101511611613c2857600052600960205260406000208484825460c81c161115613c1357506001600160801b039081613bb882613b2e565b515116946001948594855b613bd2575b5050505050505090565b8351871015613c0e57828282613be88a88613b3b565b5101511611613c0e578585889981613c01849b89613b3b565b5151160116980196613bc3565b613bc8565b600201546001600160801b0316949350505050565b5050505050600090565b806000526009602052604060002060ff600182015460a01c16600014613c59575050600490565b805460f81c613cb2575460a01c64ffffffffff164210613cac57613c7c81613b4f565b9060005260096020526001600160801b038060026040600020015416911610600014613ca757600190565b600290565b50600090565b5050600390565b916000828152602090600382526001600160a01b03604095818784205416151580613def575b80613dd7575b613dc0579480967ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79596828552600386527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84838720541694859283613d88575b169283613d72575b84875260038852808720846001600160a01b0319825416179055519580a4948152a1565b8387526004885280872060018154019055613d4e565b613da986600052600560205260406000206001600160a01b03198154169055565b838852600489528488208054600019019055613d46565b602486885190630da9b01360e01b82526004820152fd5b506009845260ff6001888520015460b01c1615613ce5565b508181161515613cdf565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003613e2c57565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b90613e786001600160801b036040840151166020610100850151015190614698565b6001600160801b0381511660e084015164ffffffffff60c08601511682156145145780156144ea57815180156144c0577f0000000000000000000000000000000000000000000000000000000000000000811161448f575064ffffffffff6020613ee184613b2e565b510151168110156144385750600090819082815184905b8082106143a7575050505064ffffffffff421664ffffffffff82168110156143675750506001600160801b0316808203614330575050600754928360005260096020526040600020916001600160801b0381511660028401906fffffffffffffffffffffffffffffffff198254161790556001600160a01b036060830151166001840154750100000000000000000000000000000000000000000060808501511515918654937fffffffffffffffffff0000ff000000000000000000000000000000000000000076ff0000000000000000000000000000000000000000000060a0890151151560b01b16921617171760018601556001600160a01b0384511678ffffffffff000000000000000000000000000000000000000060c086015160a01b169060e0860151937fff000000000000000000000000000000000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007dffffffffff0000000000000000000000000000000000000000000000000060206140948951996000198b0190613b3b565b51015160c81b169560f01b16911617171717845560005b81811061428b575050600185016007556001600160a01b0360208301511680156137ea576140e1866001600160a01b0392613cb9565b1661425a5761410c6001600160a01b036060840151166001600160801b038351169030903390614771565b6001600160801b036020820151168061422a575b507ffeb1cb9ce021c8bd5fb1eb836e6284c68866fa32d1d844238de19955238f807660206001600160a01b03845116926001600160a01b038286015116946001600160a01b036060820151169661421f61420060808401511515928c60a086015115156001600160a01b0361010060e089015194549864ffffffffff6040519a6141a98c6134fc565b818160a01c168c5260c81c168c8b015201515116956001600160801b036040519a8b9a610140958c5233828d01528281511660408d015201511660608a0152608089015260a08801528060c0880152860190613436565b9260e08501906020908164ffffffffff91828151168552015116910152565b6101208301520390a4565b614254906001600160a01b036060850151166001600160a01b036101008601515116903390614771565b38614120565b60246040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260006004820152fd5b86600052600a6020526040600020906142a88160e0870151613b3b565b51825468010000000000000000811015611ad757600181018085558110156138a157600193600052602060002001906001600160801b038151167fffffffffffffffffffffff00000000000000000000000000000000000000000074ffffffffff000000000000000000000000000000006020855494015160801b16921617179055016140ab565b60449250604051917f6375ff1300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b6040517f210aec0e00000000000000000000000000000000000000000000000000000000815264ffffffffff918216600482015291166024820152604490fd5b91935091936143cb906001600160801b036143c28588613b3b565b5151169061467d565b9364ffffffffff8060206143df8685613b3b565b510151169416808511156143fb57506001849301909291613ef8565b8385606492604051927fd97494c6000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b64ffffffffff602061444984613b2e565b5101516040517ff1fb2cc500000000000000000000000000000000000000000000000000000000815264ffffffffff938416600482015291169091166024820152604490fd5b602490604051907f73627f740000000000000000000000000000000000000000000000000000000082526004820152fd5b60046040517f7ea4ccdf000000000000000000000000000000000000000000000000000000008152fd5b60046040517fd572dbcb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f6095d3bc000000000000000000000000000000000000000000000000000000008152fd5b60009080825260036020526001600160a01b038060408420541692833314938415614583575b5050821561457157505090565b90915061457e339261356a565b161490565b60ff9294509060409181526006602052818120338252602052205416913880614564565b8060005260096020526145c06002604060002001613949565b816000526009602052604060002060ff600182015460a01c166000146145f357506001600160801b039150602001511690565b5460f81c614608575061460590613b4f565b90565b61460591506001600160801b03604081835116920151169061358e565b3d15614650573d906146368261353a565b916146446040519384613518565b82523d6000602084013e565b606090565b61460590614662816145a7565b90600052600960205260026040600020015460801c9061358e565b9190916001600160801b03808094169116019182116135a757565b919091604051906146a8826134fc565b600091828152826020820152936001600160801b03928383169182156147525767016345785d8a000080821161471b57506146e48591846148d3565b1660208701928184521115614707575090826147029251169061358e565b168252565b80634e487b7160e01b602492526001600452fd5b60449250604051917f4fea5c1a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5093945050505060405190614766826134fc565b808252602082015290565b9290604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff841117611ad7576147e092604052614837565b565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b039290921660248301526044808301939093529181526147e091614837606483613518565b6001600160a01b031690614862600080836020829551910182875af161485b614625565b9084614982565b9081519182151592836148ab575b50505061487a5750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312610aec5760200151908115918215036106325750388080614870565b9091906000198382098382029182808310920391808303921461497157670de0b6b3a7640000908183101561493a57947faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994950990828211900360ee1b910360121c170290565b60449086604051917f5173648d00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b5050670de0b6b3a764000090049150565b906149c1575080511561499757805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b81511580614a0c575b6149d2575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b156149ca56fea164736f6c6343000817000a"; bytes public constant BYTECODE_NFT_DESCRIPTOR = - hex"6080806040523461001757615f2090816200001d8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c63e9dc63751461002757600080fd5b346143a65760403660031901126143a6576001600160a01b0360043516600435036143a6576100566080614951565b60006080819052606060a081905260c082905260e0819052610120819052610140819052610160819052610180919091526101a0526004356001600160a01b03166101008190526100a690614a61565b61012052610100516040517feac8f5b80000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156143b3576000916148c0575b506001600160a01b03610117911680608052614c30565b60a052610100516040517fa80fc0710000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156143b3576fffffffffffffffffffffffffffffffff916000916148a1575b501660c052610100516040517fad35efd40000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156143b357600090614864575b6101e59150614d7d565b61014052610100516040517f4869e12d0000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156143b357600091614835575b5060c0516fffffffffffffffffffffffffffffffff16801561481f576fffffffffffffffffffffffffffffffff61271081930216041661010060800152610287600435614e79565b6101206080015260405160208101904682526bffffffffffffffffffffffff1960043560601b1660408201526024356054820152605481526102c88161496e565b519020610405602963ffffffff6103156102ee8261016861ffff8860101c16061661570a565b91601e604660ff61030b8460146050848d60081c1606011661570a565b981606011661570a565b6040519485927f68736c28000000000000000000000000000000000000000000000000000000006020850152610355815180926020602488019101614909565b83017f2c000000000000000000000000000000000000000000000000000000000000006024820152610391825180936020602585019101614909565b7f252c000000000000000000000000000000000000000000000000000000000000602583830101526103cf8351809460206027868601019101614909565b01017f252900000000000000000000000000000000000000000000000000000000000060278201520360098101845201826149fa565b61043d6fffffffffffffffffffffffffffffffff6040608001511660ff6104366001600160a01b0360805116615091565b16906151fa565b6104516001600160a01b0360805116614a61565b60a051610100516040517fbc2be1be0000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156143b357602491600091614800575b5060206001600160a01b03608080015116604051938480927f9067b677000000000000000000000000000000000000000000000000000000008252823560048301525afa80156143b357610513926000916147d1575b5064ffffffffff8091169116615545565b610120516101805190929161059d602161053a6064610533818706615a17565b950461570a565b6040519481610553879351809260208087019101614909565b82016105688251809360208085019101614909565b017f250000000000000000000000000000000000000000000000000000000000000060208201520360018101855201836149fa565b610100608001519260c060800151956101206080015197604051996105c18b614951565b8a5260208a015260408901526060880152608087015260a086015260c085015260e0840152610100830152610120820152604051806101c081011067ffffffffffffffff6101c083011117614402576101c0810160405260608152600060208201526000604082015260608082015260006080820152606060a0820152600060c0820152600060e08201526060610100820152600061012082015260006101408201526060610160820152600061018082015260006101a082015260a082015161069160c0840151845190615b23565b9061097861015c604051926106a5846149de565b600884527f50726f677265737300000000000000000000000000000000000000000000000060208501526106e86040516106de8161498a565b60008152866159eb565b156147c9576090945b6106fa8661570a565b916040519586938493661e339034b21e9160c91b6020860152610946835195869261072c846027840160208901614909565b6d11103334b6361e9111b33333111f60911b602785840101526c1e3932b1ba103bb4b23a341e9160991b603585840101526107738551809660206042888701019101614909565b7f22206865696768743d22313030222066696c6c2d6f7061636974793d222e3033828501860160428101919091527f222072783d223135222072793d22313522207374726f6b653d2223666666222060628201527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d77696474686082820152651e911a11179f60d11b60a28201527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60a88201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060c8820152703337b73a16b9b4bd329e911919383c111f60791b60e882015286519661087991889160f990910190602001614909565b661e17ba32bc3a1f60c91b8285018601870160f98101919091527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d6101008201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f73706163652220610120820152703337b73a16b9b4bd329e91191b383c111f60791b61014082015287519761091491899161015190910190602001614909565b661e17ba32bc3a1f60c91b6101518888888887010101010152602061015888888885519c8d9701010101019101614909565b631e17b39f60e11b90860190910190910190910190910161015881019190915281900361013c810190915201826149fa565b6101008301526101208201526028610100830151604051906109998261498a565b60008252610c3f61015c604051926109b0846149de565b600684527f537461747573000000000000000000000000000000000000000000000000000060208501526109e384615e1f565b6109ec82615e9d565b808211156147c15750945b610a0287870161570a565b91604051958693661e339034b21e9160c91b60208601528151610a2c816027880160208601614909565b85016d11103334b6361e9111b33333111f60911b60278201526c1e3932b1ba103bb4b23a341e9160991b6035820152610a6f825180936020604285019101614909565b017f22206865696768743d22313030222066696c6c2d6f7061636974793d222e303360428201527f222072783d223135222072793d22313522207374726f6b653d2223666666222060628201527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d77696474686082820152651e911a11179f60d11b60a28201527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60a88201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060c8820152703337b73a16b9b4bd329e911919383c111f60791b60e8820152610b6b82518093602060f985019101614909565b01661e17ba32bc3a1f60c91b60f98201527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d6101008201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f73706163652220610120820152703337b73a16b9b4bd329e91191b383c111f60791b610140820152610bfa82518093602061015185019101614909565b01661e17ba32bc3a1f60c91b610151820152610c2182518093602061015885019101614909565b01631e17b39f60e11b6101588201520361013c8101845201826149fa565b610160840152016101808201526028602083015160405190610c608261498a565b60008252610caa61015c60405192610c77846149de565b600684527f416d6f756e74000000000000000000000000000000000000000000000000000060208501526109e384615e1f565b8352016020820152610fe560808301516030604051610cc88161498a565b60008152610f6f61015c60405194610cdf866149de565b600886527f4475726174696f6e0000000000000000000000000000000000000000000000006020870152610d1286615e1f565b610d1b82615e9d565b808211156147b95750935b610d326028860161570a565b91604051978893661e339034b21e9160c91b60208601528151610d5c816027880160208601614909565b85016d11103334b6361e9111b33333111f60911b60278201526c1e3932b1ba103bb4b23a341e9160991b6035820152610d9f825180936020604285019101614909565b017f22206865696768743d22313030222066696c6c2d6f7061636974793d222e303360428201527f222072783d223135222072793d22313522207374726f6b653d2223666666222060628201527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d77696474686082820152651e911a11179f60d11b60a28201527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60a88201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060c8820152703337b73a16b9b4bd329e911919383c111f60791b60e8820152610e9b82518093602060f985019101614909565b01661e17ba32bc3a1f60c91b60f98201527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d6101008201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f73706163652220610120820152703337b73a16b9b4bd329e91191b383c111f60791b610140820152610f2a82518093602061015185019101614909565b01661e17ba32bc3a1f60c91b610151820152610f5182518093602061015885019101614909565b01631e17b39f60e11b6101588201520361013c8101865201846149fa565b8260a08601526028810160c0860152602085015190610120860151809161018088015192839185010101605881016080890152605719906103e8030160011c8061014089015201601081016101a088015201602081016040870152010160e0840152610100830151610160840151845191615190565b6060820152604051908161010081011067ffffffffffffffff6101008401111761440257610100820160405260c782527f3c726563742077696474683d223130302522206865696768743d22313030252260208301527f2066696c7465723d2275726c28234e6f69736529222f3e3c7265637420783d2260408301527f37302220793d223730222077696474683d2238363022206865696768743d223860608301527f3630222066696c6c3d2223666666222066696c6c2d6f7061636974793d222e3060808301527f33222072783d223435222072793d22343522207374726f6b653d22236666662260a08301527f207374726f6b652d6f7061636974793d222e3122207374726f6b652d7769647460c08301527f683d2234222f3e0000000000000000000000000000000000000000000000000060e08301528251916101008401519160608101519460405161113b816149a6565b603381527f3c636972636c652069643d22476c6f772220723d22353030222066696c6c3d2260208201527f75726c282352616469616c476c6f7729222f3e0000000000000000000000000060408201526040519661119888614951565b61011c88527f3c66696c7465722069643d224e6f697365223e3c6665466c6f6f6420783d223060208901527f2220793d2230222077696474683d223130302522206865696768743d2231303060408901527f252220666c6f6f642d636f6c6f723d2268736c283233302c3231252c3131252960608901527f2220666c6f6f642d6f7061636974793d22312220726573756c743d22666c6f6f60808901527f6446696c6c222f3e3c666554757262756c656e6365206261736546726571756560a08901527f6e63793d222e3422206e756d4f6374617665733d22332220726573756c743d2260c08901527f4e6f6973652220747970653d226672616374616c4e6f697365222f3e3c66654260e08901527f6c656e6420696e3d224e6f6973652220696e323d22666c6f6f6446696c6c22206101008901527f6d6f64653d22736f66742d6c69676874222f3e3c2f66696c7465723e0000000061012089015260405197886103a081011067ffffffffffffffff6103a08b011117614402576103a0890160405261037b89527f3c706174682069643d224c6f676f222066696c6c3d2223666666222066696c6c60208a01527f2d6f7061636974793d222e312220643d226d3133332e3535392c3132342e303360408a01527f34632d2e3031332c322e3431322d312e3035392c342e3834382d322e3932332c60608a01527f362e3430322d322e3535382c312e3831392d352e3136382c332e3433392d372e60808a01527f3838382c342e3939362d31342e34342c382e3236322d33312e3034372c31322e60a08a01527f3536352d34372e3637342c31322e3536392d382e3835382e3033362d31372e3860c08a01527f33382d312e3237322d32362e3332382d332e3636332d392e3830362d322e373660e08a01527f362d31392e3038372d372e3131332d32372e3536322d31322e3737382d31332e6101008a01527f3834322d382e3032352c392e3436382d32382e3630362c31362e3135332d33356101208a01527f2e323635683063322e3033352d312e3833382c342e3235322d332e3534362c366101408a01527f2e3436332d352e323234683063362e3432392d352e3635352c31362e3231382d6101608a01527f322e3833352c32302e3335382c342e31372c342e3134332c352e3035372c382e6101808a01527f3831362c392e3634392c31332e39322c31332e373334682e30333763352e37336101a08a01527f362c362e3436312c31352e3335372d322e3235332c392e33382d382e34382c306101c08a01527f2c302d332e3531352d332e3531352d332e3531352d332e3531352d31312e34396101e08a01527f2d31312e3437382d35322e3635362d35322e3636342d36342e3833372d36342e6102008a01527f3833376c2e3034392d2e303337632d312e3732352d312e3630362d322e3731396102208a01527f2d332e3834372d322e3735312d362e3230346830632d2e3034362d322e3337356102408a01527f2c312e3036322d342e3538322c322e3732362d362e32323968306c2e3138352d6102608a01527f2e3134386830632e3039392d2e3036322c2e3232322d2e3134382c2e33372d2e6102808a01527f323539683063322e30362d312e3336322c332e3935312d322e3632312c362e306102a08a01527f34342d332e3834324335372e3736332d332e3437332c39372e37362d322e33346102c08a01527f312c3132382e3633372c31382e3333326331362e3637312c392e3934362d32366102e08a01527f2e3334342c35342e3831332d33382e3635312c34302e3139392d362e3239392d6103008a01527f362e3039362d31382e3036332d31372e3734332d31392e3636382d31382e38316103208a01527f312d362e3031362d342e3034372d31332e3036312c342e3737362d372e3735326103408a01527f2c392e3735316c36382e3235342c36382e33373163312e3732342c312e3630316103608a01527f2c322e3731342c332e38342c322e3733382c362e3139325a222f3e00000000006103808a0152604051978860a081011067ffffffffffffffff60a08b01111761440257611c76611cd79160a08b0160405260758b527f3c706174682069643d22466c6f6174696e6754657874222066696c6c3d226e6f60208c01527f6e652220643d224d31323520343568373530733830203020383020383076373560408c01527f307330203830202d3830203830682d373530732d38302030202d3830202d383060608c01527f762d3735307330202d3830203830202d3830222f3e000000000000000000000060808c015261182d615aea565b906040517f3c72616469616c4772616469656e742069643d2252616469616c476c6f77223e6020820152611cd260d87f3c73746f70206f66667365743d223025222073746f702d636f6c6f723d22000093846040850152805161195f60b886602085019361189f81605e840187614909565b8101997f222073746f702d6f7061636974793d222e36222f3e0000000000000000000000605e8c01527f3c73746f70206f66667365743d2231303025222073746f702d636f6c6f723d229a8b6073820152611904825180936020609385019101614909565b017f222073746f702d6f7061636974793d2230222f3e00000000000000000000000060938201527f3c2f72616469616c4772616469656e743e00000000000000000000000000000060a78201520360988101885201866149fa565b611967615aea565b90604051967f3c6c696e6561724772616469656e742069643d2253616e64546f70222078313d60208901527f223025222079313d223025223e000000000000000000000000000000000000006040890152604d88015282516119cd81606b8a0184614909565b8701917f222f3e00000000000000000000000000000000000000000000000000000000009283606b82015289606e820152611a12825180936020608e85019101614909565b019082608e830152611a5660a2897f3c2f6c696e6561724772616469656e743e0000000000000000000000000000009485609182015203608281018b5201896149fa565b611b9c610108611a64615aea565b6040519b8c917f3c6c696e6561724772616469656e742069643d2253616e64426f74746f6d222060208401527f78313d2231303025222079313d2231303025223e00000000000000000000000060408401527f3c73746f70206f66667365743d22313025222073746f702d636f6c6f723d22006054840152611af0815180926020607387019101614909565b8201908760738301526076820152875190611b0f826096830188614909565b018660968201527f3c616e696d617465206174747269627574654e616d653d22783122206475723d60998201527f2236732220726570656174436f756e743d22696e646566696e6974652220766160b98201527f6c7565733d223330253b3630253b313230253b3630253b3330253b222f3e000060d98201528560f78201520360e881018c52018a6149fa565b611ba4615aea565b906040519a8b957f3c6c696e6561724772616469656e742069643d22486f7572676c61737353747260208801527f6f6b6522206772616469656e745472616e73666f726d3d22726f74617465283960408801527f302922206772616469656e74556e6974733d227573657253706163654f6e557360608801527f65223e000000000000000000000000000000000000000000000000000000000060808801527f3c73746f70206f66667365743d22353025222073746f702d636f6c6f723d2200608388015251809260a2880190614909565b84018360a28201527f3c73746f70206f66667365743d22383025222073746f702d636f6c6f723d220060a5820152611cb882518093602060c485019101614909565b019160c483015260c78201520360b88101875201856149fa565b615190565b92611ce9611ce3614d0b565b896159eb565b97881561479e575b50604051611cfe816149c2565b609081527f3c7061746820643d224d2035302c3336302061203330302c333030203020312c60208201527f31203630302c302061203330302c333030203020312c31202d3630302c30222060408201527f66696c6c3d2223666666222066696c6c2d6f7061636974793d222e303222207360608201527f74726f6b653d2275726c2823486f7572676c6173735374726f6b65292220737460808201527f726f6b652d77696474683d2234222f3e0000000000000000000000000000000060a082015260405193846102c081011067ffffffffffffffff6102c087011117614402576102c0850160405261029885527f3c7061746820643d226d3536362c3136312e323031762d35332e39323463302d60208601527f31392e3338322d32322e3531332d33372e3536332d36332e3339382d35312e3160408601527f39382d34302e3735362d31332e3539322d39342e3934362d32312e3037392d3160608601527f35322e3538372d32312e303739732d3131312e3833382c372e3438372d31353260808601527f2e3630322c32312e303739632d34302e3839332c31332e3633362d36332e343160a08601527f332c33312e3831362d36332e3431332c35312e3139387635332e39323463302c60c08601527f31372e3138312c31372e3730342c33332e3432372c35302e3232332c34362e3360e08601527f3934763238342e383039632d33322e3531392c31322e39362d35302e3232332c6101008601527f32392e3230362d35302e3232332c34362e3339347635332e39323463302c31396101208601527f2e3338322c32322e35322c33372e3536332c36332e3431332c35312e3139382c6101408601527f34302e3736332c31332e3539322c39342e3935342c32312e3037392c3135322e6101608601527f3630322c32312e303739733131312e3833312d372e3438372c3135322e3538376101808601527f2d32312e3037396334302e3838362d31332e3633362c36332e3339382d33312e6101a08601527f3831362c36332e3339382d35312e313938762d35332e39323463302d31372e316101c08601527f39362d31372e3730342d33332e3433352d35302e3232332d34362e34303156326101e08601527f30372e3630336333322e3531392d31322e3936372c35302e3232332d32392e326102008601527f30362c35302e3232332d34362e3430315a6d2d3334372e3436322c35372e37396102208601527f336c3133302e3935392c3133312e3032372d3133302e3935392c3133312e30316102408601527f33563231382e3939345a6d3236322e3932342e303232763236322e3031386c2d6102608601527f3133302e3933372d3133312e3030362c3133302e3933372d3133312e3031335a6102808601527f222066696c6c3d2223313631383232223e3c2f706174683e00000000000000006102a0860152896000146145795760405161212c8161498a565b60008152995b1561441857604051806101e081011067ffffffffffffffff6101e083011117614402576101e081016040526101b181527f3c7061746820643d226d3438312e34362c3438312e35347638312e3031632d3260208201527f2e33352e37372d342e38322c312e35312d372e33392c322e32332d33302e332c60408201527f382e35342d37342e36352c31332e39322d3132342e30362c31332e39322d353360608201527f2e362c302d3130312e32342d362e33332d3133312e34372d31362e3136762d3860808201527f316c34362e332d34362e3331683137302e33336c34362e32392c34362e33315a60a08201527f222066696c6c3d2275726c282353616e64426f74746f6d29222f3e3c7061746860c08201527f20643d226d3433352e31372c3433352e323363302c312e31372d2e34362c322e60e08201527f33322d312e33332c332e34342d372e31312c392e30382d34312e39332c31352e6101008201527f39382d38332e38312c31352e3938732d37362e372d362e392d38332e38322d316101208201527f352e3938632d2e38372d312e31322d312e33332d322e32372d312e33332d332e6101408201527f3434762d2e30346c382e33342d382e33352e30312d2e30316331332e37322d366101608201527f2e35312c34322e39352d31312e30322c37362e382d31312e30327336322e39376101808201527f2c342e34392c37362e37322c31316c382e34322c382e34325a222066696c6c3d6101a08201527f2275726c282353616e64546f7029222f3e0000000000000000000000000000006101c0820152995b60405196876107e081011067ffffffffffffffff6107e08a01111761440257613b3f9c612dfa6036602d9960819f97631e17b39f60e11b8d7f3c2f646566733e000000000000000000000000000000000000000000000000009a612ecb9f6107e0016040526107a782527f3c672066696c6c3d226e6f6e6522207374726f6b653d2275726c2823486f757260208301527f676c6173735374726f6b652922207374726f6b652d6c696e656361703d22726f60408301527f756e6422207374726f6b652d6d697465726c696d69743d22313022207374726f60608301527f6b652d77696474683d2234223e3c7061746820643d226d3536352e3634312c3160808301527f30372e323863302c392e3533372d352e35362c31382e3632392d31352e36373660a08301527f2c32362e393733682d2e303233632d392e3230342c372e3539362d32322e313960c08301527f342c31342e3536322d33382e3139372c32302e3539322d33392e3530342c313460e08301527f2e3933362d39372e3332352c32342e3335352d3136312e3733332c32342e33356101008301527f352d39302e34382c302d3136372e3934382d31382e3538322d3139392e3935336101208301527f2d34342e393438682d2e303233632d31302e3131352d382e3334342d31352e366101408301527f37362d31372e3433372d31352e3637362d32362e3937332c302d33392e3733356101608301527f2c39362e3535342d37312e3932312c3231352e3635322d37312e3932317332316101808301527f352e3632392c33322e3138352c3231352e3632392c37312e3932315a222f3e3c6101a08301527f7061746820643d226d3133342e33362c3136312e32303363302c33392e3733356101c08301527f2c39362e3535342c37312e3932312c3231352e3635322c37312e3932317332316101e08301527f352e3632392d33322e3138362c3231352e3632392d37312e393231222f3e3c6c6102008301527f696e652078313d223133342e3336222079313d223136312e323033222078323d6102208301527f223133342e3336222079323d223130372e3238222f3e3c6c696e652078313d226102408301527f3536352e3634222079313d223136312e323033222078323d223536352e3634226102608301527f2079323d223130372e3238222f3e3c6c696e652078313d223138342e353834226102808301527f2079313d223230362e383233222078323d223138342e353835222079323d22356102a08301527f33372e353739222f3e3c6c696e652078313d223231382e313831222079313d226102c08301527f3231382e313138222078323d223231382e313831222079323d223536322e35336102e08301527f37222f3e3c6c696e652078313d223438312e383138222079313d223231382e316103008301527f3432222078323d223438312e383139222079323d223536322e343238222f3e3c6103208301527f6c696e652078313d223531352e343135222079313d223230372e3335322220786103408301527f323d223531352e343136222079323d223533372e353739222f3e3c70617468206103608301527f643d226d3138342e35382c3533372e353863302c352e34352c342e32372c31306103808301527f2e36352c31322e30332c31352e3432682e303263352e35312c332e33392c31326103a08301527f2e37392c362e35352c32312e35352c392e34322c33302e32312c392e392c37386103c08301527f2e30322c31362e32382c3133312e38332c31362e32382c34392e34312c302c396103e08301527f332e37362d352e33382c3132342e30362d31332e39322c322e372d2e37362c356104008301527f2e32392d312e35342c372e37352d322e33352c382e37372d322e38372c31362e6104208301527f30352d362e30342c32312e35362d392e3433683063372e37362d342e37372c316104408301527f322e30342d392e39372c31322e30342d31352e3432222f3e3c7061746820643d6104608301527f226d3138342e3538322c3439322e363536632d33312e3335342c31322e3438356104808301527f2d35302e3232332c32382e35382d35302e3232332c34362e3134322c302c392e6104a08301527f3533362c352e3536342c31382e3632372c31352e3637372c32362e393639682e6104c08301527f30323263382e3530332c372e3030352c32302e3231332c31332e3436332c33346104e08301527f2e3532342c31392e3135392c392e3939392c332e3939312c32312e3236392c376105008301527f2e3630392c33332e3539372c31302e3738382c33362e34352c392e3430372c386105208301527f322e3138312c31352e3030322c3133312e3833352c31352e3030327339352e336105408301527f36332d352e3539352c3133312e3830372d31352e3030326331302e3834372d326105608301527f2e37392c32302e3836372d352e3932362c32392e3932342d392e3334392c312e6105808301527f3234342d2e3436372c322e3437332d2e3934322c332e3637332d312e3432342c6105a08301527f31342e3332362d352e3639362c32362e3033352d31322e3136312c33342e35326105c08301527f342d31392e313733682e3032326331302e3131342d382e3334322c31352e36376105e08301527f372d31372e3433332c31352e3637372d32362e3936392c302d31372e3536322d6106008301527f31382e3836392d33332e3636352d35302e3232332d34362e3135222f3e3c70616106208301527f746820643d226d3133342e33362c3539322e373263302c33392e3733352c39366106408301527f2e3535342c37312e3932312c3231352e3635322c37312e393231733231352e366106608301527f32392d33322e3138362c3231352e3632392d37312e393231222f3e3c6c696e656106808301527f2078313d223133342e3336222079313d223539322e3732222078323d223133346106a08301527f2e3336222079323d223533382e373937222f3e3c6c696e652078313d223536356106c08301527f2e3634222079313d223539322e3732222078323d223536352e3634222079323d6106e08301527f223533382e373937222f3e3c706f6c796c696e6520706f696e74733d223438316107008301527f2e383232203438312e393031203438312e373938203438312e383737203438316107208301527f2e373735203438312e383534203335302e303135203335302e303236203231386107408301527f2e313835203231382e313239222f3e3c706f6c796c696e6520706f696e74733d6107608301527f223231382e313835203438312e393031203231382e323331203438312e3835346107808301527f203335302e303135203335302e303236203438312e383232203231382e3135326107a08301527f222f3e3c2f673e000000000000000000000000000000000000000000000000006107c0830152604051998a957f3c672069643d22486f7572676c617373223e00000000000000000000000000006020880152603295612d968151809260208a8c019101614909565b8701612dab8251809360208a85019101614909565b01612dbf8251809360208985019101614909565b01612dd38251809360208885019101614909565b01612de78251809360208785019101614909565b01918201520360168101865201846149fa565b6040519e8f9788977f3c646566733e000000000000000000000000000000000000000000000000000060208a0152612e3f6026998260208c9451948593019101614909565b8901612e548251809360208c85019101614909565b01612e688251809360208b85019101614909565b01612e7c8251809360208a85019101614909565b01612e908251809360208985019101614909565b01612ea48251809360208885019101614909565b01612eb88251809360208785019101614909565b019182015203600d8101895201876149fa565b61375e604c60e0830151610120840151936134ba6130ed6060604084015193015196612ef78186615d63565b946130e861012b604051612f0a816149de565b600581527f2d3130302500000000000000000000000000000000000000000000000000000060208201526040519889917f3c74657874506174682073746172744f66667365743d220000000000000000006020840152612f74815180926020603787019101614909565b7f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666683820160378101919091527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201528251926130b891849161012090910190602001614909565b6a1e17ba32bc3a2830ba341f60a91b90830190910161012081019190915281900361010b810190915201876149fa565b615d63565b956132cc61012b604051613100816149de565b600281527f30250000000000000000000000000000000000000000000000000000000000006020820152604051998a917f3c74657874506174682073746172744f66667365743d22000000000000000000602084015261316a815180926020603787019101614909565b82017f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666660378201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201526132a782518093602061012085019101614909565b016a1e17ba32bc3a2830ba341f60a91b6101208201520361010b81018a5201886149fa565b6132d68184615dcb565b926134b561012b6040516132e9816149de565b600481527f2d3530250000000000000000000000000000000000000000000000000000000060208201526040519687917f3c74657874506174682073746172744f66667365743d220000000000000000006020840152613353815180926020603787019101614909565b82017f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666660378201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e00000000000000000061010982015261349082518093602061012085019101614909565b016a1e17ba32bc3a2830ba341f60a91b6101208201520361010b8101875201856149fa565b615dcb565b9061369961012b6040516134cd816149de565b600381527f353025000000000000000000000000000000000000000000000000000000000060208201526040519485917f3c74657874506174682073746172744f66667365743d220000000000000000006020840152613537815180926020603787019101614909565b82017f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666660378201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e00000000000000000061010982015261367482518093602061012085019101614909565b016a1e17ba32bc3a2830ba341f60a91b6101208201520361010b8101855201836149fa565b6040519586937f3c7465787420746578742d72656e646572696e673d226f7074696d697a65537060208601527f656564223e00000000000000000000000000000000000000000000000000000060408601526136ff815180926020604589019101614909565b8401613715825180936020604585019101614909565b0161372a825180936020604585019101614909565b0161373f825180936020604585019101614909565b01661e17ba32bc3a1f60c91b604582015203602c8101845201826149fa565b613a3e61019a6101408401516101a08501519061379f61379961379361378d60e060408b01519a01519461570a565b9461570a565b9761570a565b9161570a565b956040519687937f3c75736520687265663d2223476c6f77222066696c6c2d6f7061636974793d2260208601527f2e39222f3e00000000000000000000000000000000000000000000000000000060408601527f3c75736520687265663d2223476c6f772220783d22313030302220793d22313060458601527f3030222066696c6c2d6f7061636974793d222e39222f3e00000000000000000060658601527f3c75736520687265663d22234c6f676f2220783d223137302220793d22313730607c8601527f22207472616e73666f726d3d227363616c65282e3629222f3e3c757365206872609c8601527f65663d2223486f7572676c6173732220783d223135302220793d22393022207460bc8601527f72616e73666f726d3d22726f746174652831302922207472616e73666f726d2d60dc8601527f6f726967696e3d2235303020353030222f3e000000000000000000000000000060fc8601527f3c75736520687265663d222350726f67726573732220783d220000000000000061010e8601526101279061393a815180926020858a019101614909565b8501937f2220793d22373930222f3e00000000000000000000000000000000000000000080948180948801527f3c75736520687265663d22235374617475732220783d22000000000000000000610132880152610149966139a48251809360208b85019101614909565b01958601527f3c75736520687265663d2223416d6f756e742220783d2200000000000000000061015486015261016b946139e78251809360208985019101614909565b01938401527f3c75736520687265663d22234475726174696f6e2220783d220000000000000061017684015261018f92613a2a8251809360208785019101614909565b01918201520361017a8101855201836149fa565b6040519586937f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323060208601527f30302f737667222077696474683d223130303022206865696768743d2231303060408601527f30222076696577426f783d2230203020313030302031303030223e00000000006060860152613aca815180926020607b89019101614909565b8401613ae0825180936020607b85019101614909565b01613af5825180936020607b85019101614909565b01613b0a825180936020607b85019101614909565b017f3c2f7376673e0000000000000000000000000000000000000000000000000000607b8201520360618101845201826149fa565b6101605260a051610100516040517fb971302a0000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156143b3576000916143bf575b506089613bab613ccd92614a61565b9260c0608001516040519485927f5b7b2274726169745f74797065223a224173736574222c2276616c7565223a226020850152613bf2815180926020604088019101614909565b8301907f227d2c7b2274726169745f74797065223a2253656e646572222c2276616c756560408301527f223a22000000000000000000000000000000000000000000000000000000000091826060820152613c57825180936020606385019101614909565b01907f227d2c7b2274726169745f74797065223a22537461747573222c2276616c756560638301526083820152613c98825180936020608685019101614909565b017f227d5d000000000000000000000000000000000000000000000000000000000060868201520360698101845201826149fa565b6101a05160a051610120516080519193929091613cf2906001600160a01b0316614a61565b91613cfe60243561570a565b92602460206001600160a01b03608080015116604051928380927fb2564569000000000000000000000000000000000000000000000000000000008252823560048301525afa9081156143b357600091614369575b50936142dd9661406560e361426c966094966142769a9661417b9a6000146142e157604051613d81816149c2565b609b81527fe29aa0efb88f205741524e494e473a205472616e7366657272696e672074686560208201527f204e4654206d616b657320746865206e6577206f776e6572207468652072656360408201527f697069656e74206f66207468652073747265616d2e205468652066756e64732060608201527f617265206e6f74206175746f6d61746963616c6c792077697468647261776e2060808201527f666f72207468652070726576696f757320726563697069656e742e000000000060a0820152915b60405197889461400160208701997f54686973204e465420726570726573656e74732061207061796d656e742073748b527f7265616d20696e2061205361626c696572205632200000000000000000000000604089015282516020840190613eb18160558c0184614909565b8901947f20636f6e74726163742e20546865206f776e6572206f662074686973204e465460558701527f2063616e207769746864726177207468652073747265616d656420617373657460758701527f732c207768696368206172652064656e6f6d696e6174656420696e2000000000609587015282516020840196613f3b8260b183018a614909565b017f2e5c6e5c6e2d2053747265616d2049443a20000000000000000000000000000060b1820152613f7682518093602060c385019101614909565b01613faf7f5c6e2d2000000000000000000000000000000000000000000000000000000000958660c384015251809360c7840190614909565b01947f20416464726573733a2000000000000000000000000000000000000000000000958660c7820152613fed82518093602060d185019101614909565b019260d184015251809360d5840190614909565b019060d582015261401c82518093602060df85019101614909565b017f5c6e5c6e0000000000000000000000000000000000000000000000000000000060df8201526140568251809360208785019101614909565b010360c38101855201836149fa565b6101a051906141d661407860243561570a565b916140f7602d604051809560208201976a029b0b13634b2b9102b19160ad1b89526140ad815180926020602b87019101614909565b82017f2023000000000000000000000000000000000000000000000000000000000000602b8201526140e88251809360208785019101614909565b0103600d8101865201846149fa565b610160516141049061585b565b94604051998a977f7b2261747472696275746573223a00000000000000000000000000000000000060208a0152614145815180926020602e8d019101614909565b8801917f2c226465736372697074696f6e223a2200000000000000000000000000000000602e840152518093603e840190614909565b01917f222c2265787465726e616c5f75726c223a2268747470733a2f2f7361626c6965603e8401527f722e636f6d222c226e616d65223a220000000000000000000000000000000000605e840152518093606d840190614909565b017f222c22696d616765223a22646174613a696d6167652f7376672b786d6c3b6261606d8201527f736536342c000000000000000000000000000000000000000000000000000000608d820152614237825180936020609285019101614909565b017f227d00000000000000000000000000000000000000000000000000000000000060928201520360748101845201826149fa565b60e081905261585b565b6142c9603d60405180937f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000060208301526142b98151809260208686019101614909565b810103601d8101845201826149fa565b60405191829160208352602083019061492c565b0390f35b6040516142ed8161496e565b605b81527fe29d95494e464f3a2054686973204e4654206973206e6f6e2d7472616e73666560208201527f7261626c652e2049742063616e6e6f7420626520736f6c64206f72207472616e60408201527f7366657272656420746f20616e6f74686572206163636f756e742e0000000000606082015291613e45565b90506020959195813d6020116143ab575b81614387602093836149fa565b810103126143a657519384151585036143a657909490936142dd613d53565b600080fd5b3d915061437a565b6040513d6000823e3d90fd5b90506020813d6020116143fa575b816143da602093836149fa565b810103126143a657516001600160a01b03811681036143a6576089613b9c565b3d91506143cd565b634e487b7160e01b600052604160045260246000fd5b6040518061012081011067ffffffffffffffff6101208301111761440257610120810160405260f881527f3c7061746820643d226d3438312e34362c3530342e3130317635382e3434396360208201527f2d322e33352e37372d342e38322c312e35312d372e33392c322e32332d33302e60408201527f332c382e35342d37342e36352c31332e39322d3132342e30362c31332e39322d60608201527f35332e362c302d3130312e32342d362e33332d3133312e34372d31362e31367660808201527f2d35382e343339683236322e39325a222066696c6c3d2275726c282353616e6460a08201527f426f74746f6d29222f3e3c656c6c697073652063783d22333530222063793d2260c08201527f3530342e313031222072783d223133312e343632222072793d2232382e31303860e08201527f222066696c6c3d2275726c282353616e64546f7029222f3e00000000000000006101008201529961237f565b604051806101c081011067ffffffffffffffff6101c083011117614402576101c0810160405261019981527f3c706f6c79676f6e20706f696e74733d22333530203335302e3032362034313560208201527f2e3033203238342e39373820323835203238342e39373820333530203335302e60408201527f303236222066696c6c3d2275726c282353616e64426f74746f6d29222f3e3c7060608201527f61746820643d226d3431362e3334312c3238312e39373563302c2e3931342d2e60808201527f3335342c312e3830392d312e3033352c322e36382d352e3534322c372e30373660a08201527f2d33322e3636312c31322e34352d36352e32382c31322e34352d33322e36323460c08201527f2c302d35392e3733382d352e3337342d36352e32382d31322e34352d2e36383160e08201527f2d2e3837322d312e3033352d312e3736372d312e3033352d322e36382c302d2e6101008201527f3931342e3335342d312e3830382c312e3033352d322e3637362c352e3534322d6101208201527f372e3037362c33322e3635362d31322e34352c36352e32382d31322e34352c336101408201527f322e3631392c302c35392e3733382c352e3337342c36352e32382c31322e34356101608201527f2e3638312e3836372c312e3033352c312e3736322c312e3033352c322e3637366101808201527f5a222066696c6c3d2275726c282353616e64546f7029222f3e000000000000006101a082015299612132565b6147b29198506147ac614d44565b906159eb565b9638611cf1565b905093610d26565b9050946109f7565b60d0946106f1565b6147f3915060203d6020116147f9575b6147eb81836149fa565b810190614a44565b38610502565b503d6147e1565b614819915060203d6020116147f9576147eb81836149fa565b386104ac565b634e487b7160e01b600052601260045260246000fd5b614857915060203d60201161485d575b61484f81836149fa565b810190614a1c565b3861023f565b503d614845565b506020813d602011614899575b8161487e602093836149fa565b810103126143a6575160058110156143a6576101e5906101db565b3d9150614871565b6148ba915060203d60201161485d5761484f81836149fa565b38610181565b90506020813d602011614901575b816148db602093836149fa565b810103126143a657516001600160a01b03811681036143a6576001600160a01b03610100565b3d91506148ce565b60005b83811061491c5750506000910152565b818101518382015260200161490c565b9060209161494581518092818552858086019101614909565b601f01601f1916010190565b610140810190811067ffffffffffffffff82111761440257604052565b6080810190811067ffffffffffffffff82111761440257604052565b6020810190811067ffffffffffffffff82111761440257604052565b6060810190811067ffffffffffffffff82111761440257604052565b60c0810190811067ffffffffffffffff82111761440257604052565b6040810190811067ffffffffffffffff82111761440257604052565b90601f8019910116810190811067ffffffffffffffff82111761440257604052565b908160209103126143a657516fffffffffffffffffffffffffffffffff811681036143a65790565b908160209103126143a6575164ffffffffff811681036143a65790565b6001600160a01b03168060405191614a78836149a6565b602a8352602083016040368237835115614b6c5760309053825160019060011015614b6c57607860218501536029905b808211614af1575050614ab9575090565b604490604051907fe22e27eb000000000000000000000000000000000000000000000000000000008252600482015260146024820152fd5b9091600f81166010811015614b57577f3031323334353637383961626364656600000000000000000000000000000000901a614b2d84876159da565b5360041c918015614b42576000190190614aa8565b60246000634e487b7160e01b81526011600452fd5b60246000634e487b7160e01b81526032600452fd5b634e487b7160e01b600052603260045260246000fd5b67ffffffffffffffff811161440257601f01601f191660200190565b3d15614bc9573d90614baf82614b82565b91614bbd60405193846149fa565b82523d6000602084013e565b606090565b6020818303126143a65780519067ffffffffffffffff82116143a6570181601f820112156143a6578051614c0181614b82565b92614c0f60405194856149fa565b818452602082840101116143a657614c2d9160208085019101614909565b90565b6000809160405160208101906395d89b4160e01b825260048152614c53816149de565b51915afa614c5f614b9e565b90158015614cff575b614cc55780602080614c7f93518301019101614bce565b601e815111600014614c2d5750604051614c98816149de565b600b81527f4c6f6e672053796d626f6c000000000000000000000000000000000000000000602082015290565b50604051614cd2816149de565b600581527f4552433230000000000000000000000000000000000000000000000000000000602082015290565b50604081511115614c68565b60405190614d18826149de565b600782527f536574746c6564000000000000000000000000000000000000000000000000006020830152565b60405190614d51826149de565b600882527f4465706c657465640000000000000000000000000000000000000000000000006020830152565b6005811015614e635760048103614d975750614c2d614d44565b60038103614dd95750604051614dac816149de565b600881527f43616e63656c6564000000000000000000000000000000000000000000000000602082015290565b60018103614e1b5750604051614dee816149de565b600981527f53747265616d696e670000000000000000000000000000000000000000000000602082015290565b600203614e2a57614c2d614d0b565b604051614e36816149de565b600781527f50656e64696e6700000000000000000000000000000000000000000000000000602082015290565b634e487b7160e01b600052602160045260246000fd5b6001600160a01b031660408051916395d89b4160e01b8352600083600481845afa92831561508657600093615063575b50815192614eb6846149de565b60118452614eeb6020947f5341422d56322d4c4f434b55502d4c494e00000000000000000000000000000086820152826159eb565b15614f295750507f4c6f636b7570204c696e65617200000000000000000000000000000000000000905191614f1f836149de565b600d835282015290565b614f668351614f37816149de565b601181527f5341422d56322d4c4f434b55502d44594e00000000000000000000000000000086820152826159eb565b15614fa45750507f4c6f636b75702044796e616d6963000000000000000000000000000000000000905191614f9a836149de565b600e835282015290565b614fe18351614fb2816149de565b601181527f5341422d56322d4c4f434b55502d54524100000000000000000000000000000086820152826159eb565b1561501f5750507f4c6f636b7570205472616e636865640000000000000000000000000000000000905191615015836149de565b600f835282015290565b61505f9083519384937f814a8a2e00000000000000000000000000000000000000000000000000000000855260048501526024840152604483019061492c565b0390fd5b61507f91933d8091833e61507781836149fa565b810190614bce565b9138614ea9565b82513d6000823e3d90fd5b60405160208101907f313ce567000000000000000000000000000000000000000000000000000000008252600481526150c9816149de565b6000928392839251915afa6150dc614b9e565b9080615113575b1561510f5760208180518101031261510b57602001519060ff82168203615108575090565b80fd5b5080fd5b5090565b5060208151146150e3565b6040519061512b826149de565b600482527f2667743b000000000000000000000000000000000000000000000000000000006020830152565b60405190615164826149de565b600482527f266c743b000000000000000000000000000000000000000000000000000000006020830152565b906151f89294936040519586926020946151b281518092888089019101614909565b84016151c682518093888085019101614909565b016151d982518093878085019101614909565b016151ec82518093868085019101614909565b010380855201836149fa565b565b801561550a57600091806154e5575090505b600190808281101561527657505050615223615157565b614c2d602260405183615240829551809260208086019101614909565b81017f203100000000000000000000000000000000000000000000000000000000000060208201520360028101845201826149fa565b66038d7ea4c6800011156154885760409081519060a0820182811067ffffffffffffffff821117614402578084526152ad8161498a565b6000815282528251906152bf826149de565b8482526020917f4b00000000000000000000000000000000000000000000000000000000000000838201528284015283516152f9816149de565b8581527f4d0000000000000000000000000000000000000000000000000000000000000083820152848401528351615330816149de565b8581527f42000000000000000000000000000000000000000000000000000000000000008382015260608401528351615368816149de565b8581527f5400000000000000000000000000000000000000000000000000000000000000838201526080840152600091856000965b61545c575b508451946153af866149de565b600790600787527f2623383830353b0000000000000000000000000000000000000000000000000083880152519560005b828110615449575050505061542a615430917f2000000000000000000000000000000000000000000000000000000000000000602787015260088652615425866149de565b61570a565b91615a17565b916005851015614b6c57614c2d9460051b015192615190565b81810184015188820185015283016153e0565b9591926103e89081851061547f57508680916064600a870406950493019661539d565b939296506153a2565b505061549261511e565b614c2d6028604051836154af829551809260208086019101614909565b81017f203939392e39395400000000000000000000000000000000000000000000000060208201520360088101845201826149fa565b600a0a9182156154f657500461520c565b80634e487b7160e01b602492526012600452fd5b5050604051615518816149de565b600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b62015180910304806155ad575061555a615157565b614c2d602660405183615577829551809260208086019101614909565b81017f203120446179000000000000000000000000000000000000000000000000000060208201520360068101845201826149fa565b61270f811161567c576001810361563957614c2d60206156016040516155d2816149de565b600481527f2044617900000000000000000000000000000000000000000000000000000000838201529361570a565b60405193816156198693518092868087019101614909565b820161562d82518093868085019101614909565b010380845201826149fa565b614c2d602061560160405161564d816149de565b600581527f2044617973000000000000000000000000000000000000000000000000000000838201529361570a565b5061568561511e565b614c2d602a604051836156a2829551809260208086019101614909565b81017f2039393939204461797300000000000000000000000000000000000000000000602082015203600a8101845201826149fa565b906156e282614b82565b6156ef60405191826149fa565b8281528092615700601f1991614b82565b0190602036910137565b806000917a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008082101561584d575b506d04ee2d6d415b85acef81000000008083101561583e575b50662386f26fc100008083101561582f575b506305f5e10080831015615820575b5061271080831015615811575b506064821015615801575b600a809210156157f7575b6001908160216157a2600187016156d8565b95860101905b6157b4575b5050505090565b600019019083907f30313233343536373839616263646566000000000000000000000000000000008282061a8353049182156157f2579190826157a8565b6157ad565b9160010191615790565b9190606460029104910191615785565b6004919392049101913861577a565b6008919392049101913861576d565b6010919392049101913861575e565b6020919392049101913861574c565b604093508104915038615733565b8051156159c65760405161586e816149a6565b604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040820152815191600292600281018091116159b05760038091047f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681036159b05761590d906002959492951b6156d8565b936020850193839284518501935b84811061595d57505050505060039051068060011461594a5760021461593f575090565b603d90600019015390565b50603d9081600019820153600119015390565b8360049197929394959701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c16880101518885015316850101518682015301959392919061591b565b634e487b7160e01b600052601160045260246000fd5b506040516159d38161498a565b6000815290565b908151811015614b6c570160200190565b9081518151908181149384615a01575050505090565b60209293945082012092012014388080806157ad565b80615a2957506040516159d38161498a565b600a811015615a8e57615a3b9061570a565b614c2d602260405180937f2e300000000000000000000000000000000000000000000000000000000000006020830152615a7e8151809260208686019101614909565b81010360028101845201826149fa565b615a979061570a565b614c2d602160405180937f2e000000000000000000000000000000000000000000000000000000000000006020830152615ada8151809260208686019101614909565b81010360018101845201826149fa565b60405190615af7826149de565b601082527f68736c283233302c3231252c31312529000000000000000000000000000000006020830152565b8015615d5557615b31615aea565b906127109081039081116159b057614c2d91615b4f6101369261570a565b6040519485927f3c672066696c6c3d226e6f6e65223e000000000000000000000000000000000060208501527f3c636972636c652063783d22313636222063793d2235302220723d2232322220602f8501527f7374726f6b653d22000000000000000000000000000000000000000000000000604f850152615bdb815180926020605788019101614909565b83017f22207374726f6b652d77696474683d223130222f3e000000000000000000000060578201527f3c636972636c652063783d22313636222063793d2235302220706174684c656e606c8201527f6774683d2231303030302220723d22323222207374726f6b653d220000000000608c820152615c6382518093602060a785019101614909565b017f22207374726f6b652d6461736861727261793d22313030303022207374726f6b60a78201527f652d646173686f66667365743d2200000000000000000000000000000000000060c7820152615cc482518093602060d585019101614909565b017f22207374726f6b652d6c696e656361703d22726f756e6422207374726f6b652d60d58201527f77696474683d223522207472616e73666f726d3d22726f74617465282d39302960f58201527f22207472616e73666f726d2d6f726967696e3d22313636203530222f3e000000610115820152631e17b39f60e11b610132820152036101168101845201826149fa565b50506040516159d38161498a565b60306151f8919392936040519481615d85879351809260208087019101614909565b820164010714051160dd1b60208201526a029b0b13634b2b9102b19160ad1b6025820152615dbc8251809360208785019101614909565b010360108101855201836149fa565b60256151f8919392936040519481615ded879351809260208087019101614909565b820164010714051160dd1b6020820152615e108251809360208785019101614909565b010360058101855201836149fa565b60009080518015615e9557906000916000915b818310615e4457505050600d02900390565b909193603b60f81b7fff00000000000000000000000000000000000000000000000000000000000000615e7787856159da565b511614615e8d575b600d01936001019190615e32565b849350615e7f565b505050600090565b60009080518015615e9557906000916000915b818310615ec25750505060041b900390565b909193603b60f81b7fff00000000000000000000000000000000000000000000000000000000000000615ef587856159da565b511614615f0b575b601001936001019190615eb0565b849350615efd56fea164736f6c6343000817000a"; + hex"6080806040523461001757615f2f90816200001d8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c63e9dc63751461002757600080fd5b346143a95760403660031901126143a9576001600160a01b0360043516600435036143a9576100566080614954565b60006080819052606060a081905260c082905260e0819052610120819052610140819052610160819052610180526101a0526004356001600160a01b038116610100526100a290614ae2565b610120526100ba6004356001600160a01b0316614cfa565b61014052610100516040517feac8f5b80000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156143b6576000916148c3575b506001600160a01b0361012b911680608052614e4b565b60a052610100516040517fa80fc0710000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156143b6576fffffffffffffffffffffffffffffffff916000916148a4575b501660c052610100516040517fad35efd40000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156143b657600090614867575b6101f99150614f98565b61016052610100516040517f4869e12d0000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156143b657600091614838575b5060c0516fffffffffffffffffffffffffffffffff168015614822576fffffffffffffffffffffffffffffffff6127108193021604166101206080015260405160208101904682526bffffffffffffffffffffffff1960043560601b1660408201526024356054820152605481526102ca81614971565b519020610407602963ffffffff6103176102f08261016861ffff8860101c16061661570d565b91601e604660ff61030d8460146050848d60081c1606011661570d565b981606011661570d565b6040519485927f68736c2800000000000000000000000000000000000000000000000000000000602085015261035781518092602060248801910161490c565b83017f2c00000000000000000000000000000000000000000000000000000000000000602482015261039382518093602060258501910161490c565b7f252c000000000000000000000000000000000000000000000000000000000000602583830101526103d1835180946020602786860101910161490c565b01017f252900000000000000000000000000000000000000000000000000000000000060278201520360098101845201826149fd565b61043f6fffffffffffffffffffffffffffffffff6040608001511660ff6104386001600160a01b0360805116615094565b16906151fd565b6104536001600160a01b0360805116614cfa565b90602060800151602460206001600160a01b03608080015116604051928380927fbc2be1be000000000000000000000000000000000000000000000000000000008252823560048301525afa80156143b657602491600091614803575b5060206001600160a01b03608080015116604051938480927f9067b677000000000000000000000000000000000000000000000000000000008252823560048301525afa80156143b657610517926000916147d4575b5064ffffffffff8091169116615548565b610140516101a0519092916105a1602161053e6064610537818706615a26565b950461570d565b604051948161055787935180926020808701910161490c565b820161056c825180936020808501910161490c565b017f250000000000000000000000000000000000000000000000000000000000000060208201520360018101855201836149fd565b610120608001519260e0608001519660a06080015196604051996105c48b614954565b8a5260208a015260408901526060880152608087015260a086015260c085015260e0840152610100830152610120820152604051806101c081011067ffffffffffffffff6101c083011117614405576101c0810160405260608152600060208201526000604082015260608082015260006080820152606060a0820152600060c0820152600060e08201526060610100820152600061012082015260006101408201526060610160820152600061018082015260006101a082015260a082015161069460c0840151845190615b32565b9061097b61015c604051926106a8846149e1565b600884527f50726f677265737300000000000000000000000000000000000000000000000060208501526106eb6040516106e18161498d565b60008152866159e9565b156147cc576090945b6106fd8661570d565b916040519586938493661e339034b21e9160c91b6020860152610949835195869261072f84602784016020890161490c565b6d11103334b6361e9111b33333111f60911b602785840101526c1e3932b1ba103bb4b23a341e9160991b60358584010152610776855180966020604288870101910161490c565b7f22206865696768743d22313030222066696c6c2d6f7061636974793d222e3033828501860160428101919091527f222072783d223135222072793d22313522207374726f6b653d2223666666222060628201527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d77696474686082820152651e911a11179f60d11b60a28201527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60a88201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060c8820152703337b73a16b9b4bd329e911919383c111f60791b60e882015286519661087c91889160f99091019060200161490c565b661e17ba32bc3a1f60c91b8285018601870160f98101919091527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d6101008201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f73706163652220610120820152703337b73a16b9b4bd329e91191b383c111f60791b6101408201528751976109179189916101519091019060200161490c565b661e17ba32bc3a1f60c91b6101518888888887010101010152602061015888888885519c8d970101010101910161490c565b631e17b39f60e11b90860190910190910190910190910161015881019190915281900361013c810190915201826149fd565b61010083015261012082015260286101208301516040519061099c8261498d565b60008252610c4261015c604051926109b3846149e1565b600684527f537461747573000000000000000000000000000000000000000000000000000060208501526109e684615e2e565b6109ef82615eac565b808211156147c45750945b610a0587870161570d565b91604051958693661e339034b21e9160c91b60208601528151610a2f81602788016020860161490c565b85016d11103334b6361e9111b33333111f60911b60278201526c1e3932b1ba103bb4b23a341e9160991b6035820152610a7282518093602060428501910161490c565b017f22206865696768743d22313030222066696c6c2d6f7061636974793d222e303360428201527f222072783d223135222072793d22313522207374726f6b653d2223666666222060628201527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d77696474686082820152651e911a11179f60d11b60a28201527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60a88201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060c8820152703337b73a16b9b4bd329e911919383c111f60791b60e8820152610b6e82518093602060f98501910161490c565b01661e17ba32bc3a1f60c91b60f98201527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d6101008201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f73706163652220610120820152703337b73a16b9b4bd329e91191b383c111f60791b610140820152610bfd8251809360206101518501910161490c565b01661e17ba32bc3a1f60c91b610151820152610c248251809360206101588501910161490c565b01631e17b39f60e11b6101588201520361013c8101845201826149fd565b610160840152016101808201526028602083015160405190610c638261498d565b60008252610cad61015c60405192610c7a846149e1565b600684527f416d6f756e74000000000000000000000000000000000000000000000000000060208501526109e684615e2e565b8352016020820152610fe860808301516030604051610ccb8161498d565b60008152610f7261015c60405194610ce2866149e1565b600886527f4475726174696f6e0000000000000000000000000000000000000000000000006020870152610d1586615e2e565b610d1e82615eac565b808211156147bc5750935b610d356028860161570d565b91604051978893661e339034b21e9160c91b60208601528151610d5f81602788016020860161490c565b85016d11103334b6361e9111b33333111f60911b60278201526c1e3932b1ba103bb4b23a341e9160991b6035820152610da282518093602060428501910161490c565b017f22206865696768743d22313030222066696c6c2d6f7061636974793d222e303360428201527f222072783d223135222072793d22313522207374726f6b653d2223666666222060628201527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d77696474686082820152651e911a11179f60d11b60a28201527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60a88201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060c8820152703337b73a16b9b4bd329e911919383c111f60791b60e8820152610e9e82518093602060f98501910161490c565b01661e17ba32bc3a1f60c91b60f98201527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d6101008201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f73706163652220610120820152703337b73a16b9b4bd329e91191b383c111f60791b610140820152610f2d8251809360206101518501910161490c565b01661e17ba32bc3a1f60c91b610151820152610f548251809360206101588501910161490c565b01631e17b39f60e11b6101588201520361013c8101865201846149fd565b8260a08601526028810160c0860152602085015190610120860151809161018088015192839185010101605881016080890152605719906103e8030160011c8061014089015201601081016101a088015201602081016040870152010160e0840152610100830151610160840151845191615193565b6060820152604051908161010081011067ffffffffffffffff6101008401111761440557610100820160405260c782527f3c726563742077696474683d223130302522206865696768743d22313030252260208301527f2066696c7465723d2275726c28234e6f69736529222f3e3c7265637420783d2260408301527f37302220793d223730222077696474683d2238363022206865696768743d223860608301527f3630222066696c6c3d2223666666222066696c6c2d6f7061636974793d222e3060808301527f33222072783d223435222072793d22343522207374726f6b653d22236666662260a08301527f207374726f6b652d6f7061636974793d222e3122207374726f6b652d7769647460c08301527f683d2234222f3e0000000000000000000000000000000000000000000000000060e08301528251916101208401519160608101519460405161113e816149a9565b603381527f3c636972636c652069643d22476c6f772220723d22353030222066696c6c3d2260208201527f75726c282352616469616c476c6f7729222f3e0000000000000000000000000060408201526040519661119b88614954565b61011c88527f3c66696c7465722069643d224e6f697365223e3c6665466c6f6f6420783d223060208901527f2220793d2230222077696474683d223130302522206865696768743d2231303060408901527f252220666c6f6f642d636f6c6f723d2268736c283233302c3231252c3131252960608901527f2220666c6f6f642d6f7061636974793d22312220726573756c743d22666c6f6f60808901527f6446696c6c222f3e3c666554757262756c656e6365206261736546726571756560a08901527f6e63793d222e3422206e756d4f6374617665733d22332220726573756c743d2260c08901527f4e6f6973652220747970653d226672616374616c4e6f697365222f3e3c66654260e08901527f6c656e6420696e3d224e6f6973652220696e323d22666c6f6f6446696c6c22206101008901527f6d6f64653d22736f66742d6c69676874222f3e3c2f66696c7465723e0000000061012089015260405197886103a081011067ffffffffffffffff6103a08b011117614405576103a0890160405261037b89527f3c706174682069643d224c6f676f222066696c6c3d2223666666222066696c6c60208a01527f2d6f7061636974793d222e312220643d226d3133332e3535392c3132342e303360408a01527f34632d2e3031332c322e3431322d312e3035392c342e3834382d322e3932332c60608a01527f362e3430322d322e3535382c312e3831392d352e3136382c332e3433392d372e60808a01527f3838382c342e3939362d31342e34342c382e3236322d33312e3034372c31322e60a08a01527f3536352d34372e3637342c31322e3536392d382e3835382e3033362d31372e3860c08a01527f33382d312e3237322d32362e3332382d332e3636332d392e3830362d322e373660e08a01527f362d31392e3038372d372e3131332d32372e3536322d31322e3737382d31332e6101008a01527f3834322d382e3032352c392e3436382d32382e3630362c31362e3135332d33356101208a01527f2e323635683063322e3033352d312e3833382c342e3235322d332e3534362c366101408a01527f2e3436332d352e323234683063362e3432392d352e3635352c31362e3231382d6101608a01527f322e3833352c32302e3335382c342e31372c342e3134332c352e3035372c382e6101808a01527f3831362c392e3634392c31332e39322c31332e373334682e30333763352e37336101a08a01527f362c362e3436312c31352e3335372d322e3235332c392e33382d382e34382c306101c08a01527f2c302d332e3531352d332e3531352d332e3531352d332e3531352d31312e34396101e08a01527f2d31312e3437382d35322e3635362d35322e3636342d36342e3833372d36342e6102008a01527f3833376c2e3034392d2e303337632d312e3732352d312e3630362d322e3731396102208a01527f2d332e3834372d322e3735312d362e3230346830632d2e3034362d322e3337356102408a01527f2c312e3036322d342e3538322c322e3732362d362e32323968306c2e3138352d6102608a01527f2e3134386830632e3039392d2e3036322c2e3232322d2e3134382c2e33372d2e6102808a01527f323539683063322e30362d312e3336322c332e3935312d322e3632312c362e306102a08a01527f34342d332e3834324335372e3736332d332e3437332c39372e37362d322e33346102c08a01527f312c3132382e3633372c31382e3333326331362e3637312c392e3934362d32366102e08a01527f2e3334342c35342e3831332d33382e3635312c34302e3139392d362e3239392d6103008a01527f362e3039362d31382e3036332d31372e3734332d31392e3636382d31382e38316103208a01527f312d362e3031362d342e3034372d31332e3036312c342e3737362d372e3735326103408a01527f2c392e3735316c36382e3235342c36382e33373163312e3732342c312e3630316103608a01527f2c322e3731342c332e38342c322e3733382c362e3139325a222f3e00000000006103808a0152604051978860a081011067ffffffffffffffff60a08b01111761440557611c79611cda9160a08b0160405260758b527f3c706174682069643d22466c6f6174696e6754657874222066696c6c3d226e6f60208c01527f6e652220643d224d31323520343568373530733830203020383020383076373560408c01527f307330203830202d3830203830682d373530732d38302030202d3830202d383060608c01527f762d3735307330202d3830203830202d3830222f3e000000000000000000000060808c0152611830615af9565b906040517f3c72616469616c4772616469656e742069643d2252616469616c476c6f77223e6020820152611cd560d87f3c73746f70206f66667365743d223025222073746f702d636f6c6f723d22000093846040850152805161196260b88660208501936118a281605e84018761490c565b8101997f222073746f702d6f7061636974793d222e36222f3e0000000000000000000000605e8c01527f3c73746f70206f66667365743d2231303025222073746f702d636f6c6f723d229a8b607382015261190782518093602060938501910161490c565b017f222073746f702d6f7061636974793d2230222f3e00000000000000000000000060938201527f3c2f72616469616c4772616469656e743e00000000000000000000000000000060a78201520360988101885201866149fd565b61196a615af9565b90604051967f3c6c696e6561724772616469656e742069643d2253616e64546f70222078313d60208901527f223025222079313d223025223e000000000000000000000000000000000000006040890152604d88015282516119d081606b8a018461490c565b8701917f222f3e00000000000000000000000000000000000000000000000000000000009283606b82015289606e820152611a15825180936020608e8501910161490c565b019082608e830152611a5960a2897f3c2f6c696e6561724772616469656e743e0000000000000000000000000000009485609182015203608281018b5201896149fd565b611b9f610108611a67615af9565b6040519b8c917f3c6c696e6561724772616469656e742069643d2253616e64426f74746f6d222060208401527f78313d2231303025222079313d2231303025223e00000000000000000000000060408401527f3c73746f70206f66667365743d22313025222073746f702d636f6c6f723d22006054840152611af381518092602060738701910161490c565b8201908760738301526076820152875190611b1282609683018861490c565b018660968201527f3c616e696d617465206174747269627574654e616d653d22783122206475723d60998201527f2236732220726570656174436f756e743d22696e646566696e6974652220766160b98201527f6c7565733d223330253b3630253b313230253b3630253b3330253b222f3e000060d98201528560f78201520360e881018c52018a6149fd565b611ba7615af9565b906040519a8b957f3c6c696e6561724772616469656e742069643d22486f7572676c61737353747260208801527f6f6b6522206772616469656e745472616e73666f726d3d22726f74617465283960408801527f302922206772616469656e74556e6974733d227573657253706163654f6e557360608801527f65223e000000000000000000000000000000000000000000000000000000000060808801527f3c73746f70206f66667365743d22353025222073746f702d636f6c6f723d2200608388015251809260a288019061490c565b84018360a28201527f3c73746f70206f66667365743d22383025222073746f702d636f6c6f723d220060a5820152611cbb82518093602060c48501910161490c565b019160c483015260c78201520360b88101875201856149fd565b615193565b92611cec611ce6614f26565b896159e9565b9788156147a1575b50604051611d01816149c5565b609081527f3c7061746820643d224d2035302c3336302061203330302c333030203020312c60208201527f31203630302c302061203330302c333030203020312c31202d3630302c30222060408201527f66696c6c3d2223666666222066696c6c2d6f7061636974793d222e303222207360608201527f74726f6b653d2275726c2823486f7572676c6173735374726f6b65292220737460808201527f726f6b652d77696474683d2234222f3e0000000000000000000000000000000060a082015260405193846102c081011067ffffffffffffffff6102c087011117614405576102c0850160405261029885527f3c7061746820643d226d3536362c3136312e323031762d35332e39323463302d60208601527f31392e3338322d32322e3531332d33372e3536332d36332e3339382d35312e3160408601527f39382d34302e3735362d31332e3539322d39342e3934362d32312e3037392d3160608601527f35322e3538372d32312e303739732d3131312e3833382c372e3438372d31353260808601527f2e3630322c32312e303739632d34302e3839332c31332e3633362d36332e343160a08601527f332c33312e3831362d36332e3431332c35312e3139387635332e39323463302c60c08601527f31372e3138312c31372e3730342c33332e3432372c35302e3232332c34362e3360e08601527f3934763238342e383039632d33322e3531392c31322e39362d35302e3232332c6101008601527f32392e3230362d35302e3232332c34362e3339347635332e39323463302c31396101208601527f2e3338322c32322e35322c33372e3536332c36332e3431332c35312e3139382c6101408601527f34302e3736332c31332e3539322c39342e3935342c32312e3037392c3135322e6101608601527f3630322c32312e303739733131312e3833312d372e3438372c3135322e3538376101808601527f2d32312e3037396334302e3838362d31332e3633362c36332e3339382d33312e6101a08601527f3831362c36332e3339382d35312e313938762d35332e39323463302d31372e316101c08601527f39362d31372e3730342d33332e3433352d35302e3232332d34362e34303156326101e08601527f30372e3630336333322e3531392d31322e3936372c35302e3232332d32392e326102008601527f30362c35302e3232332d34362e3430315a6d2d3334372e3436322c35372e37396102208601527f336c3133302e3935392c3133312e3032372d3133302e3935392c3133312e30316102408601527f33563231382e3939345a6d3236322e3932342e303232763236322e3031386c2d6102608601527f3133302e3933372d3133312e3030362c3133302e3933372d3133312e3031335a6102808601527f222066696c6c3d2223313631383232223e3c2f706174683e00000000000000006102a08601528960001461457c5760405161212f8161498d565b60008152995b1561441b57604051806101e081011067ffffffffffffffff6101e083011117614405576101e081016040526101b181527f3c7061746820643d226d3438312e34362c3438312e35347638312e3031632d3260208201527f2e33352e37372d342e38322c312e35312d372e33392c322e32332d33302e332c60408201527f382e35342d37342e36352c31332e39322d3132342e30362c31332e39322d353360608201527f2e362c302d3130312e32342d362e33332d3133312e34372d31362e3136762d3860808201527f316c34362e332d34362e3331683137302e33336c34362e32392c34362e33315a60a08201527f222066696c6c3d2275726c282353616e64426f74746f6d29222f3e3c7061746860c08201527f20643d226d3433352e31372c3433352e323363302c312e31372d2e34362c322e60e08201527f33322d312e33332c332e34342d372e31312c392e30382d34312e39332c31352e6101008201527f39382d38332e38312c31352e3938732d37362e372d362e392d38332e38322d316101208201527f352e3938632d2e38372d312e31322d312e33332d322e32372d312e33332d332e6101408201527f3434762d2e30346c382e33342d382e33352e30312d2e30316331332e37322d366101608201527f2e35312c34322e39352d31312e30322c37362e382d31312e30327336322e39376101808201527f2c342e34392c37362e37322c31316c382e34322c382e34325a222066696c6c3d6101a08201527f2275726c282353616e64546f7029222f3e0000000000000000000000000000006101c0820152995b60405196876107e081011067ffffffffffffffff6107e08a01111761440557613b429c612dfd6036602d9960819f97631e17b39f60e11b8d7f3c2f646566733e000000000000000000000000000000000000000000000000009a612ece9f6107e0016040526107a782527f3c672066696c6c3d226e6f6e6522207374726f6b653d2275726c2823486f757260208301527f676c6173735374726f6b652922207374726f6b652d6c696e656361703d22726f60408301527f756e6422207374726f6b652d6d697465726c696d69743d22313022207374726f60608301527f6b652d77696474683d2234223e3c7061746820643d226d3536352e3634312c3160808301527f30372e323863302c392e3533372d352e35362c31382e3632392d31352e36373660a08301527f2c32362e393733682d2e303233632d392e3230342c372e3539362d32322e313960c08301527f342c31342e3536322d33382e3139372c32302e3539322d33392e3530342c313460e08301527f2e3933362d39372e3332352c32342e3335352d3136312e3733332c32342e33356101008301527f352d39302e34382c302d3136372e3934382d31382e3538322d3139392e3935336101208301527f2d34342e393438682d2e303233632d31302e3131352d382e3334342d31352e366101408301527f37362d31372e3433372d31352e3637362d32362e3937332c302d33392e3733356101608301527f2c39362e3535342d37312e3932312c3231352e3635322d37312e3932317332316101808301527f352e3632392c33322e3138352c3231352e3632392c37312e3932315a222f3e3c6101a08301527f7061746820643d226d3133342e33362c3136312e32303363302c33392e3733356101c08301527f2c39362e3535342c37312e3932312c3231352e3635322c37312e3932317332316101e08301527f352e3632392d33322e3138362c3231352e3632392d37312e393231222f3e3c6c6102008301527f696e652078313d223133342e3336222079313d223136312e323033222078323d6102208301527f223133342e3336222079323d223130372e3238222f3e3c6c696e652078313d226102408301527f3536352e3634222079313d223136312e323033222078323d223536352e3634226102608301527f2079323d223130372e3238222f3e3c6c696e652078313d223138342e353834226102808301527f2079313d223230362e383233222078323d223138342e353835222079323d22356102a08301527f33372e353739222f3e3c6c696e652078313d223231382e313831222079313d226102c08301527f3231382e313138222078323d223231382e313831222079323d223536322e35336102e08301527f37222f3e3c6c696e652078313d223438312e383138222079313d223231382e316103008301527f3432222078323d223438312e383139222079323d223536322e343238222f3e3c6103208301527f6c696e652078313d223531352e343135222079313d223230372e3335322220786103408301527f323d223531352e343136222079323d223533372e353739222f3e3c70617468206103608301527f643d226d3138342e35382c3533372e353863302c352e34352c342e32372c31306103808301527f2e36352c31322e30332c31352e3432682e303263352e35312c332e33392c31326103a08301527f2e37392c362e35352c32312e35352c392e34322c33302e32312c392e392c37386103c08301527f2e30322c31362e32382c3133312e38332c31362e32382c34392e34312c302c396103e08301527f332e37362d352e33382c3132342e30362d31332e39322c322e372d2e37362c356104008301527f2e32392d312e35342c372e37352d322e33352c382e37372d322e38372c31362e6104208301527f30352d362e30342c32312e35362d392e3433683063372e37362d342e37372c316104408301527f322e30342d392e39372c31322e30342d31352e3432222f3e3c7061746820643d6104608301527f226d3138342e3538322c3439322e363536632d33312e3335342c31322e3438356104808301527f2d35302e3232332c32382e35382d35302e3232332c34362e3134322c302c392e6104a08301527f3533362c352e3536342c31382e3632372c31352e3637372c32362e393639682e6104c08301527f30323263382e3530332c372e3030352c32302e3231332c31332e3436332c33346104e08301527f2e3532342c31392e3135392c392e3939392c332e3939312c32312e3236392c376105008301527f2e3630392c33332e3539372c31302e3738382c33362e34352c392e3430372c386105208301527f322e3138312c31352e3030322c3133312e3833352c31352e3030327339352e336105408301527f36332d352e3539352c3133312e3830372d31352e3030326331302e3834372d326105608301527f2e37392c32302e3836372d352e3932362c32392e3932342d392e3334392c312e6105808301527f3234342d2e3436372c322e3437332d2e3934322c332e3637332d312e3432342c6105a08301527f31342e3332362d352e3639362c32362e3033352d31322e3136312c33342e35326105c08301527f342d31392e313733682e3032326331302e3131342d382e3334322c31352e36376105e08301527f372d31372e3433332c31352e3637372d32362e3936392c302d31372e3536322d6106008301527f31382e3836392d33332e3636352d35302e3232332d34362e3135222f3e3c70616106208301527f746820643d226d3133342e33362c3539322e373263302c33392e3733352c39366106408301527f2e3535342c37312e3932312c3231352e3635322c37312e393231733231352e366106608301527f32392d33322e3138362c3231352e3632392d37312e393231222f3e3c6c696e656106808301527f2078313d223133342e3336222079313d223539322e3732222078323d223133346106a08301527f2e3336222079323d223533382e373937222f3e3c6c696e652078313d223536356106c08301527f2e3634222079313d223539322e3732222078323d223536352e3634222079323d6106e08301527f223533382e373937222f3e3c706f6c796c696e6520706f696e74733d223438316107008301527f2e383232203438312e393031203438312e373938203438312e383737203438316107208301527f2e373735203438312e383534203335302e303135203335302e303236203231386107408301527f2e313835203231382e313239222f3e3c706f6c796c696e6520706f696e74733d6107608301527f223231382e313835203438312e393031203231382e323331203438312e3835346107808301527f203335302e303135203335302e303236203438312e383232203231382e3135326107a08301527f222f3e3c2f673e000000000000000000000000000000000000000000000000006107c0830152604051998a957f3c672069643d22486f7572676c617373223e00000000000000000000000000006020880152603295612d998151809260208a8c01910161490c565b8701612dae8251809360208a8501910161490c565b01612dc2825180936020898501910161490c565b01612dd6825180936020888501910161490c565b01612dea825180936020878501910161490c565b01918201520360168101865201846149fd565b6040519e8f9788977f3c646566733e000000000000000000000000000000000000000000000000000060208a0152612e426026998260208c945194859301910161490c565b8901612e578251809360208c8501910161490c565b01612e6b8251809360208b8501910161490c565b01612e7f8251809360208a8501910161490c565b01612e93825180936020898501910161490c565b01612ea7825180936020888501910161490c565b01612ebb825180936020878501910161490c565b019182015203600d8101895201876149fd565b613761604c60e0830151610100840151936134bd6130f06060604084015193015196612efa8186615d72565b946130eb61012b604051612f0d816149e1565b600581527f2d3130302500000000000000000000000000000000000000000000000000000060208201526040519889917f3c74657874506174682073746172744f66667365743d220000000000000000006020840152612f7781518092602060378701910161490c565b7f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666683820160378101919091527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201528251926130bb9184916101209091019060200161490c565b6a1e17ba32bc3a2830ba341f60a91b90830190910161012081019190915281900361010b810190915201876149fd565b615d72565b956132cf61012b604051613103816149e1565b600281527f30250000000000000000000000000000000000000000000000000000000000006020820152604051998a917f3c74657874506174682073746172744f66667365743d22000000000000000000602084015261316d81518092602060378701910161490c565b82017f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666660378201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201526132aa8251809360206101208501910161490c565b016a1e17ba32bc3a2830ba341f60a91b6101208201520361010b81018a5201886149fd565b6132d98184615dda565b926134b861012b6040516132ec816149e1565b600481527f2d3530250000000000000000000000000000000000000000000000000000000060208201526040519687917f3c74657874506174682073746172744f66667365743d22000000000000000000602084015261335681518092602060378701910161490c565b82017f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666660378201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201526134938251809360206101208501910161490c565b016a1e17ba32bc3a2830ba341f60a91b6101208201520361010b8101875201856149fd565b615dda565b9061369c61012b6040516134d0816149e1565b600381527f353025000000000000000000000000000000000000000000000000000000000060208201526040519485917f3c74657874506174682073746172744f66667365743d22000000000000000000602084015261353a81518092602060378701910161490c565b82017f2220687265663d2223466c6f6174696e6754657874222066696c6c3d2223666660378201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201526136778251809360206101208501910161490c565b016a1e17ba32bc3a2830ba341f60a91b6101208201520361010b8101855201836149fd565b6040519586937f3c7465787420746578742d72656e646572696e673d226f7074696d697a65537060208601527f656564223e000000000000000000000000000000000000000000000000000000604086015261370281518092602060458901910161490c565b840161371882518093602060458501910161490c565b0161372d82518093602060458501910161490c565b0161374282518093602060458501910161490c565b01661e17ba32bc3a1f60c91b604582015203602c8101845201826149fd565b613a4161019a6101408401516101a0850151906137a261379c61379661379060e060408b01519a01519461570d565b9461570d565b9761570d565b9161570d565b956040519687937f3c75736520687265663d2223476c6f77222066696c6c2d6f7061636974793d2260208601527f2e39222f3e00000000000000000000000000000000000000000000000000000060408601527f3c75736520687265663d2223476c6f772220783d22313030302220793d22313060458601527f3030222066696c6c2d6f7061636974793d222e39222f3e00000000000000000060658601527f3c75736520687265663d22234c6f676f2220783d223137302220793d22313730607c8601527f22207472616e73666f726d3d227363616c65282e3629222f3e3c757365206872609c8601527f65663d2223486f7572676c6173732220783d223135302220793d22393022207460bc8601527f72616e73666f726d3d22726f746174652831302922207472616e73666f726d2d60dc8601527f6f726967696e3d2235303020353030222f3e000000000000000000000000000060fc8601527f3c75736520687265663d222350726f67726573732220783d220000000000000061010e8601526101279061393d815180926020858a01910161490c565b8501937f2220793d22373930222f3e00000000000000000000000000000000000000000080948180948801527f3c75736520687265663d22235374617475732220783d22000000000000000000610132880152610149966139a78251809360208b8501910161490c565b01958601527f3c75736520687265663d2223416d6f756e742220783d2200000000000000000061015486015261016b946139ea825180936020898501910161490c565b01938401527f3c75736520687265663d22234475726174696f6e2220783d220000000000000061017684015261018f92613a2d825180936020878501910161490c565b01918201520361017a8101855201836149fd565b6040519586937f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323060208601527f30302f737667222077696474683d223130303022206865696768743d2231303060408601527f30222076696577426f783d2230203020313030302031303030223e00000000006060860152613acd815180926020607b8901910161490c565b8401613ae3825180936020607b8501910161490c565b01613af8825180936020607b8501910161490c565b01613b0d825180936020607b8501910161490c565b017f3c2f7376673e0000000000000000000000000000000000000000000000000000607b8201520360618101845201826149fd565b6101805260a051610100516040517fb971302a0000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156143b6576000916143c2575b506089613bae613cd092614cfa565b9260e0608001516040519485927f5b7b2274726169745f74797065223a224173736574222c2276616c7565223a226020850152613bf581518092602060408801910161490c565b8301907f227d2c7b2274726169745f74797065223a2253656e646572222c2276616c756560408301527f223a22000000000000000000000000000000000000000000000000000000000091826060820152613c5a82518093602060638501910161490c565b01907f227d2c7b2274726169745f74797065223a22537461747573222c2276616c756560638301526083820152613c9b82518093602060868501910161490c565b017f227d5d000000000000000000000000000000000000000000000000000000000060868201520360698101845201826149fd565b6101205160a051610140516080519193929091613cf5906001600160a01b0316614cfa565b91613d0160243561570d565b92602460206001600160a01b03608080015116604051928380927fb2564569000000000000000000000000000000000000000000000000000000008252823560048301525afa9081156143b65760009161436c575b50936142e09661406860e361426f966094966142799a9661417e9a6000146142e457604051613d84816149c5565b609b81527fe29aa0efb88f205741524e494e473a205472616e7366657272696e672074686560208201527f204e4654206d616b657320746865206e6577206f776e6572207468652072656360408201527f697069656e74206f66207468652073747265616d2e205468652066756e64732060608201527f617265206e6f74206175746f6d61746963616c6c792077697468647261776e2060808201527f666f72207468652070726576696f757320726563697069656e742e000000000060a0820152915b60405197889461400460208701997f54686973204e465420726570726573656e74732061207061796d656e742073748b527f7265616d20696e2061205361626c696572205632200000000000000000000000604089015282516020840190613eb48160558c018461490c565b8901947f20636f6e74726163742e20546865206f776e6572206f662074686973204e465460558701527f2063616e207769746864726177207468652073747265616d656420617373657460758701527f732c207768696368206172652064656e6f6d696e6174656420696e2000000000609587015282516020840196613f3e8260b183018a61490c565b017f2e5c6e5c6e2d2053747265616d2049443a20000000000000000000000000000060b1820152613f7982518093602060c38501910161490c565b01613fb27f5c6e2d2000000000000000000000000000000000000000000000000000000000958660c384015251809360c784019061490c565b01947f20416464726573733a2000000000000000000000000000000000000000000000958660c7820152613ff082518093602060d18501910161490c565b019260d184015251809360d584019061490c565b019060d582015261401f82518093602060df8501910161490c565b017f5c6e5c6e0000000000000000000000000000000000000000000000000000000060df820152614059825180936020878501910161490c565b010360c38101855201836149fd565b61012051906141d961407b60243561570d565b916140fa602d604051809560208201976a029b0b13634b2b9102b19160ad1b89526140b0815180926020602b8701910161490c565b82017f2023000000000000000000000000000000000000000000000000000000000000602b8201526140eb825180936020878501910161490c565b0103600d8101865201846149fd565b610180516141079061585e565b94604051998a977f7b2261747472696275746573223a00000000000000000000000000000000000060208a0152614148815180926020602e8d01910161490c565b8801917f2c226465736372697074696f6e223a2200000000000000000000000000000000602e840152518093603e84019061490c565b01917f222c2265787465726e616c5f75726c223a2268747470733a2f2f7361626c6965603e8401527f722e636f6d222c226e616d65223a220000000000000000000000000000000000605e840152518093606d84019061490c565b017f222c22696d616765223a22646174613a696d6167652f7376672b786d6c3b6261606d8201527f736536342c000000000000000000000000000000000000000000000000000000608d82015261423a82518093602060928501910161490c565b017f227d00000000000000000000000000000000000000000000000000000000000060928201520360748101845201826149fd565b60e081905261585e565b6142cc603d60405180937f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000060208301526142bc815180926020868601910161490c565b810103601d8101845201826149fd565b60405191829160208352602083019061492f565b0390f35b6040516142f081614971565b605b81527fe29d95494e464f3a2054686973204e4654206973206e6f6e2d7472616e73666560208201527f7261626c652e2049742063616e6e6f7420626520736f6c64206f72207472616e60408201527f7366657272656420746f20616e6f74686572206163636f756e742e0000000000606082015291613e48565b90506020959195813d6020116143ae575b8161438a602093836149fd565b810103126143a957519384151585036143a957909490936142e0613d56565b600080fd5b3d915061437d565b6040513d6000823e3d90fd5b90506020813d6020116143fd575b816143dd602093836149fd565b810103126143a957516001600160a01b03811681036143a9576089613b9f565b3d91506143d0565b634e487b7160e01b600052604160045260246000fd5b6040518061012081011067ffffffffffffffff6101208301111761440557610120810160405260f881527f3c7061746820643d226d3438312e34362c3530342e3130317635382e3434396360208201527f2d322e33352e37372d342e38322c312e35312d372e33392c322e32332d33302e60408201527f332c382e35342d37342e36352c31332e39322d3132342e30362c31332e39322d60608201527f35332e362c302d3130312e32342d362e33332d3133312e34372d31362e31367660808201527f2d35382e343339683236322e39325a222066696c6c3d2275726c282353616e6460a08201527f426f74746f6d29222f3e3c656c6c697073652063783d22333530222063793d2260c08201527f3530342e313031222072783d223133312e343632222072793d2232382e31303860e08201527f222066696c6c3d2275726c282353616e64546f7029222f3e000000000000000061010082015299612382565b604051806101c081011067ffffffffffffffff6101c083011117614405576101c0810160405261019981527f3c706f6c79676f6e20706f696e74733d22333530203335302e3032362034313560208201527f2e3033203238342e39373820323835203238342e39373820333530203335302e60408201527f303236222066696c6c3d2275726c282353616e64426f74746f6d29222f3e3c7060608201527f61746820643d226d3431362e3334312c3238312e39373563302c2e3931342d2e60808201527f3335342c312e3830392d312e3033352c322e36382d352e3534322c372e30373660a08201527f2d33322e3636312c31322e34352d36352e32382c31322e34352d33322e36323460c08201527f2c302d35392e3733382d352e3337342d36352e32382d31322e34352d2e36383160e08201527f2d2e3837322d312e3033352d312e3736372d312e3033352d322e36382c302d2e6101008201527f3931342e3335342d312e3830382c312e3033352d322e3637362c352e3534322d6101208201527f372e3037362c33322e3635362d31322e34352c36352e32382d31322e34352c336101408201527f322e3631392c302c35392e3733382c352e3337342c36352e32382c31322e34356101608201527f2e3638312e3836372c312e3033352c312e3736322c312e3033352c322e3637366101808201527f5a222066696c6c3d2275726c282353616e64546f7029222f3e000000000000006101a082015299612135565b6147b59198506147af614f5f565b906159e9565b9638611cf4565b905093610d29565b9050946109fa565b60d0946106f4565b6147f6915060203d6020116147fc575b6147ee81836149fd565b810190614a47565b38610506565b503d6147e4565b61481c915060203d6020116147fc576147ee81836149fd565b386104b0565b634e487b7160e01b600052601260045260246000fd5b61485a915060203d602011614860575b61485281836149fd565b810190614a1f565b38610253565b503d614848565b506020813d60201161489c575b81614881602093836149fd565b810103126143a9575160058110156143a9576101f9906101ef565b3d9150614874565b6148bd915060203d6020116148605761485281836149fd565b38610195565b90506020813d602011614904575b816148de602093836149fd565b810103126143a957516001600160a01b03811681036143a9576001600160a01b03610114565b3d91506148d1565b60005b83811061491f5750506000910152565b818101518382015260200161490f565b906020916149488151809281855285808601910161490c565b601f01601f1916010190565b610140810190811067ffffffffffffffff82111761440557604052565b6080810190811067ffffffffffffffff82111761440557604052565b6020810190811067ffffffffffffffff82111761440557604052565b6060810190811067ffffffffffffffff82111761440557604052565b60c0810190811067ffffffffffffffff82111761440557604052565b6040810190811067ffffffffffffffff82111761440557604052565b90601f8019910116810190811067ffffffffffffffff82111761440557604052565b908160209103126143a957516fffffffffffffffffffffffffffffffff811681036143a95790565b908160209103126143a9575164ffffffffff811681036143a95790565b67ffffffffffffffff811161440557601f01601f191660200190565b6020818303126143a95780519067ffffffffffffffff82116143a9570181601f820112156143a9578051614ab381614a64565b92614ac160405194856149fd565b818452602082840101116143a957614adf916020808501910161490c565b90565b6001600160a01b031660408051916395d89b4160e01b8352600083600481845afa928315614cef57600093614ccc575b50815192614b1f846149e1565b60118452614b546020947f5341422d56322d4c4f434b55502d4c494e00000000000000000000000000000086820152826159e9565b15614b925750507f4c6f636b7570204c696e65617200000000000000000000000000000000000000905191614b88836149e1565b600d835282015290565b614bcf8351614ba0816149e1565b601181527f5341422d56322d4c4f434b55502d44594e00000000000000000000000000000086820152826159e9565b15614c0d5750507f4c6f636b75702044796e616d6963000000000000000000000000000000000000905191614c03836149e1565b600e835282015290565b614c4a8351614c1b816149e1565b601181527f5341422d56322d4c4f434b55502d54524100000000000000000000000000000086820152826159e9565b15614c885750507f4c6f636b7570205472616e636865640000000000000000000000000000000000905191614c7e836149e1565b600f835282015290565b614cc89083519384937f814a8a2e00000000000000000000000000000000000000000000000000000000855260048501526024840152604483019061492f565b0390fd5b614ce891933d8091833e614ce081836149fd565b810190614a80565b9138614b12565b82513d6000823e3d90fd5b6001600160a01b03168060405191614d11836149a9565b602a8352602083016040368237835115614e055760309053825160019060011015614e0557607860218501536029905b808211614d8a575050614d52575090565b604490604051907fe22e27eb000000000000000000000000000000000000000000000000000000008252600482015260146024820152fd5b9091600f81166010811015614df0577f3031323334353637383961626364656600000000000000000000000000000000901a614dc68487615a15565b5360041c918015614ddb576000190190614d41565b60246000634e487b7160e01b81526011600452fd5b60246000634e487b7160e01b81526032600452fd5b634e487b7160e01b600052603260045260246000fd5b3d15614e46573d90614e2c82614a64565b91614e3a60405193846149fd565b82523d6000602084013e565b606090565b6000809160405160208101906395d89b4160e01b825260048152614e6e816149e1565b51915afa614e7a614e1b565b90158015614f1a575b614ee05780602080614e9a93518301019101614a80565b601e815111600014614adf5750604051614eb3816149e1565b600b81527f4c6f6e672053796d626f6c000000000000000000000000000000000000000000602082015290565b50604051614eed816149e1565b600581527f4552433230000000000000000000000000000000000000000000000000000000602082015290565b50604081511115614e83565b60405190614f33826149e1565b600782527f536574746c6564000000000000000000000000000000000000000000000000006020830152565b60405190614f6c826149e1565b600882527f4465706c657465640000000000000000000000000000000000000000000000006020830152565b600581101561507e5760048103614fb25750614adf614f5f565b60038103614ff45750604051614fc7816149e1565b600881527f43616e63656c6564000000000000000000000000000000000000000000000000602082015290565b600181036150365750604051615009816149e1565b600981527f53747265616d696e670000000000000000000000000000000000000000000000602082015290565b60020361504557614adf614f26565b604051615051816149e1565b600781527f50656e64696e6700000000000000000000000000000000000000000000000000602082015290565b634e487b7160e01b600052602160045260246000fd5b60405160208101907f313ce567000000000000000000000000000000000000000000000000000000008252600481526150cc816149e1565b6000928392839251915afa6150df614e1b565b9080615116575b156151125760208180518101031261510e57602001519060ff8216820361510b575090565b80fd5b5080fd5b5090565b5060208151146150e6565b6040519061512e826149e1565b600482527f2667743b000000000000000000000000000000000000000000000000000000006020830152565b60405190615167826149e1565b600482527f266c743b000000000000000000000000000000000000000000000000000000006020830152565b906151fb9294936040519586926020946151b58151809288808901910161490c565b84016151c98251809388808501910161490c565b016151dc8251809387808501910161490c565b016151ef8251809386808501910161490c565b010380855201836149fd565b565b801561550d57600091806154e8575090505b60019080828110156152795750505061522661515a565b614adf60226040518361524382955180926020808601910161490c565b81017f203100000000000000000000000000000000000000000000000000000000000060208201520360028101845201826149fd565b66038d7ea4c68000111561548b5760409081519060a0820182811067ffffffffffffffff821117614405578084526152b08161498d565b6000815282528251906152c2826149e1565b8482526020917f4b00000000000000000000000000000000000000000000000000000000000000838201528284015283516152fc816149e1565b8581527f4d0000000000000000000000000000000000000000000000000000000000000083820152848401528351615333816149e1565b8581527f4200000000000000000000000000000000000000000000000000000000000000838201526060840152835161536b816149e1565b8581527f5400000000000000000000000000000000000000000000000000000000000000838201526080840152600091856000965b61545f575b508451946153b2866149e1565b600790600787527f2623383830353b0000000000000000000000000000000000000000000000000083880152519560005b82811061544c575050505061542d615433917f2000000000000000000000000000000000000000000000000000000000000000602787015260088652615428866149e1565b61570d565b91615a26565b916005851015614e0557614adf9460051b015192615193565b81810184015188820185015283016153e3565b9591926103e89081851061548257508680916064600a87040695049301966153a0565b939296506153a5565b5050615495615121565b614adf6028604051836154b282955180926020808601910161490c565b81017f203939392e39395400000000000000000000000000000000000000000000000060208201520360088101845201826149fd565b600a0a9182156154f957500461520f565b80634e487b7160e01b602492526012600452fd5b505060405161551b816149e1565b600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b62015180910304806155b0575061555d61515a565b614adf60266040518361557a82955180926020808601910161490c565b81017f203120446179000000000000000000000000000000000000000000000000000060208201520360068101845201826149fd565b61270f811161567f576001810361563c57614adf60206156046040516155d5816149e1565b600481527f2044617900000000000000000000000000000000000000000000000000000000838201529361570d565b604051938161561c869351809286808701910161490c565b82016156308251809386808501910161490c565b010380845201826149fd565b614adf6020615604604051615650816149e1565b600581527f2044617973000000000000000000000000000000000000000000000000000000838201529361570d565b50615688615121565b614adf602a604051836156a582955180926020808601910161490c565b81017f2039393939204461797300000000000000000000000000000000000000000000602082015203600a8101845201826149fd565b906156e582614a64565b6156f260405191826149fd565b8281528092615703601f1991614a64565b0190602036910137565b806000917a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000080821015615850575b506d04ee2d6d415b85acef810000000080831015615841575b50662386f26fc1000080831015615832575b506305f5e10080831015615823575b5061271080831015615814575b506064821015615804575b600a809210156157fa575b6001908160216157a5600187016156db565b95860101905b6157b7575b5050505090565b600019019083907f30313233343536373839616263646566000000000000000000000000000000008282061a8353049182156157f5579190826157ab565b6157b0565b9160010191615793565b9190606460029104910191615788565b6004919392049101913861577d565b60089193920491019138615770565b60109193920491019138615761565b6020919392049101913861574f565b604093508104915038615736565b908151156159d45760405191615873836149a9565b604083527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208401527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040840152805192600291600285018095116159be5760038095047f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681036159be576159119060029694961b6156db565b926020840192829183518401976020890192835194600085525b8a81106159715750505050600393949596505251068060011461595e57600214615953575090565b603d90600019015390565b50603d9081600019820153600119015390565b836004919b989b019a8b51600190603f9082828260121c16870101518453828282600c1c16870101518385015382828260061c16870101518785015316840101518582015301969961592b565b634e487b7160e01b600052601160045260246000fd5b90506040516159e28161498d565b6000815290565b90815181519081811493846159ff575050505090565b60209293945082012092012014388080806157b0565b908151811015614e05570160200190565b80615a3857506040516159e28161498d565b600a811015615a9d57615a4a9061570d565b614adf602260405180937f2e300000000000000000000000000000000000000000000000000000000000006020830152615a8d815180926020868601910161490c565b81010360028101845201826149fd565b615aa69061570d565b614adf602160405180937f2e000000000000000000000000000000000000000000000000000000000000006020830152615ae9815180926020868601910161490c565b81010360018101845201826149fd565b60405190615b06826149e1565b601082527f68736c283233302c3231252c31312529000000000000000000000000000000006020830152565b8015615d6457615b40615af9565b906127109081039081116159be57614adf91615b5e6101369261570d565b6040519485927f3c672066696c6c3d226e6f6e65223e000000000000000000000000000000000060208501527f3c636972636c652063783d22313636222063793d2235302220723d2232322220602f8501527f7374726f6b653d22000000000000000000000000000000000000000000000000604f850152615bea81518092602060578801910161490c565b83017f22207374726f6b652d77696474683d223130222f3e000000000000000000000060578201527f3c636972636c652063783d22313636222063793d2235302220706174684c656e606c8201527f6774683d2231303030302220723d22323222207374726f6b653d220000000000608c820152615c7282518093602060a78501910161490c565b017f22207374726f6b652d6461736861727261793d22313030303022207374726f6b60a78201527f652d646173686f66667365743d2200000000000000000000000000000000000060c7820152615cd382518093602060d58501910161490c565b017f22207374726f6b652d6c696e656361703d22726f756e6422207374726f6b652d60d58201527f77696474683d223522207472616e73666f726d3d22726f74617465282d39302960f58201527f22207472616e73666f726d2d6f726967696e3d22313636203530222f3e000000610115820152631e17b39f60e11b610132820152036101168101845201826149fd565b50506040516159e28161498d565b60306151fb919392936040519481615d9487935180926020808701910161490c565b820164010714051160dd1b60208201526a029b0b13634b2b9102b19160ad1b6025820152615dcb825180936020878501910161490c565b010360108101855201836149fd565b60256151fb919392936040519481615dfc87935180926020808701910161490c565b820164010714051160dd1b6020820152615e1f825180936020878501910161490c565b010360058101855201836149fd565b60009080518015615ea457906000916000915b818310615e5357505050600d02900390565b909193603b60f81b7fff00000000000000000000000000000000000000000000000000000000000000615e868785615a15565b511614615e9c575b600d01936001019190615e41565b849350615e8e565b505050600090565b60009080518015615ea457906000916000915b818310615ed15750505060041b900390565b909193603b60f81b7fff00000000000000000000000000000000000000000000000000000000000000615f048785615a15565b511614615f1a575b601001936001019190615ebf565b849350615f0c56fea164736f6c6343000817000a"; /*////////////////////////////////////////////////////////////////////////// DEPLOYERS @@ -43,7 +44,7 @@ contract Precompiles { /// - A default value is passed for `maxSegmentCount`. /// - A dummy {SablierV2NFTDescriptor} is deployed so that the user does not have to provide one. function deployLockupDynamic(address initialAdmin) public returns (ISablierV2LockupDynamic lockupDynamic) { - uint256 maxSegmentCount = MAX_COUNT; + uint256 maxSegmentCount = MAX_SEGMENT_COUNT; lockupDynamic = deployLockupDynamic(initialAdmin, maxSegmentCount); } @@ -69,7 +70,7 @@ contract Precompiles { public returns (ISablierV2LockupDynamic lockupDynamic) { - lockupDynamic = deployLockupDynamic(initialAdmin, nftDescriptor, MAX_COUNT); + lockupDynamic = deployLockupDynamic(initialAdmin, nftDescriptor, MAX_SEGMENT_COUNT); } /// @notice Deploys {SablierV2LockupDynamic} from precompiled bytecode. @@ -121,7 +122,7 @@ contract Precompiles { /// - A default value is passed for `maxTrancheCount`. /// - A dummy {SablierV2NFTDescriptor} is deployed so that the user does not have to provide one. function deployLockupTranched(address initialAdmin) public returns (ISablierV2LockupTranched lockupTranched) { - uint256 maxTrancheCount = MAX_COUNT; + uint256 maxTrancheCount = MAX_TRANCHE_COUNT; lockupTranched = deployLockupTranched(initialAdmin, maxTrancheCount); } @@ -147,7 +148,7 @@ contract Precompiles { public returns (ISablierV2LockupTranched lockupTranched) { - lockupTranched = deployLockupTranched(initialAdmin, nftDescriptor, MAX_COUNT); + lockupTranched = deployLockupTranched(initialAdmin, nftDescriptor, MAX_TRANCHE_COUNT); } /// @notice Deploys {SablierV2LockupTranched} from precompiled bytecode. diff --git a/remappings.txt b/remappings.txt index 05bda3006..83d4faffa 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,6 +1,6 @@ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ @prb/math/=node_modules/@prb/math/ -@sphinx-labs/contracts/=node_modules/@sphinx-labs/contracts/contracts/foundry +@sphinx-labs/contracts/=node_modules/@sphinx-labs/contracts/contracts/foundry/ forge-std/=node_modules/forge-std/ solady/=node_modules/solady/ solarray/=node_modules/solarray/ diff --git a/script/Base.s.sol b/script/Base.s.sol index 4e0c6a931..2747791f4 100644 --- a/script/Base.s.sol +++ b/script/Base.s.sol @@ -14,21 +14,23 @@ contract BaseScript is Script, Sphinx { /// @dev The Avalanche chain ID. uint256 internal constant AVALANCHE_CHAIN_ID = 43_114; - /// @dev The project name for the Sphinx plugin. - string internal constant SPHINX_PROJECT_NAME = "test-test"; - /// @dev Included to enable compilation of the script without a $MNEMONIC environment variable. string internal constant TEST_MNEMONIC = "test test test test test test test test test test test junk"; + /// @dev The project name for the Sphinx plugin. + string internal constant TEST_SPHINX_PROJECT_NAME = "test-test"; + /// @dev Needed for the deterministic deployments. bytes32 internal constant ZERO_SALT = bytes32(0); /// @dev The address of the transaction broadcaster. address internal broadcaster; - /// @dev The upper limit on the length of data structures to ensure that transactions stay within the - /// block gas limit. - uint256 internal maxCount; + /// @dev The upper limit on the length of segments to ensure that transactions stay within the block gas limit. + uint256 internal maxSegmentCount; + + /// @dev The upper limit on the length of tranches to ensure that transactions stay within the block gas limit. + uint256 internal maxTrancheCount; /// @dev Used to derive the broadcaster's address if $EOA is not defined. string internal mnemonic; @@ -52,13 +54,15 @@ contract BaseScript is Script, Sphinx { mnemonic = vm.envOr({ name: "MNEMONIC", defaultValue: TEST_MNEMONIC }); (broadcaster,) = deriveRememberKey({ mnemonic: mnemonic, index: 0 }); } - sphinxProjectName = vm.envOr({ name: "SPHINX_PROJECT_NAME", defaultValue: SPHINX_PROJECT_NAME }); + sphinxProjectName = vm.envOr({ name: "SPHINX_PROJECT_NAME", defaultValue: TEST_SPHINX_PROJECT_NAME }); - // Sets `maxCount` to 300 for Avalanche, and 500 for all other chains. + // Avalanche has a lower block gas limit than most other chains. if (block.chainid == AVALANCHE_CHAIN_ID) { - maxCount = 300; + maxSegmentCount = 300; + maxTrancheCount = 298; } else { - maxCount = 500; + maxSegmentCount = 500; + maxTrancheCount = 500; } } @@ -68,10 +72,11 @@ contract BaseScript is Script, Sphinx { vm.stopBroadcast(); } - /// @dev Configures the Sphinx plugin to use Sphinx managed deployment for smart contracts. + /// @dev Configures the Sphinx plugin to manage the deployment of the contracts. /// Refer to https://github.com/sphinx-labs/sphinx/tree/main/docs. + /// /// CLI example: - /// - bun sphinx propose script/DeployCore.s.sol --networks testnets --sig "runSphinx(address)" $ADMIN + /// bun sphinx propose script/DeployCore.s.sol --networks testnets --sig "runSphinx(address)" $ADMIN function configureSphinx() public override { sphinxConfig.mainnets = ["arbitrum", "avalanche", "base", "bnb", "gnosis", "ethereum", "optimism", "polygon"]; sphinxConfig.orgId = vm.envOr({ name: "SPHINX_ORG_ID", defaultValue: TEST_MNEMONIC }); @@ -88,7 +93,7 @@ contract BaseScript is Script, Sphinx { /// - The salt format is "ChainID , Version ". /// - The version is obtained from `package.json` using the `ffi` cheatcode: /// https://book.getfoundry.sh/cheatcodes/ffi - /// - Requires `jq` CLI tool installed: https://jqlang.github.io/jq/ + /// - Requires the `jq` CLI installed: https://jqlang.github.io/jq/ function constructCreate2Salt() public returns (bytes32) { string memory chainId = block.chainid.toString(); string[] memory inputs = new string[](4); diff --git a/script/DeployCore.s.sol b/script/DeployCore.s.sol index 44d1b9641..e98c688fb 100644 --- a/script/DeployCore.s.sol +++ b/script/DeployCore.s.sol @@ -15,7 +15,7 @@ import { BaseScript } from "./Base.s.sol"; /// 3. {SablierV2LockupLinear} /// 4. {SablierV2LockupTranched} contract DeployCore is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast(address initialAdmin) public virtual @@ -30,7 +30,7 @@ contract DeployCore is BaseScript { (lockupDynamic, lockupLinear, lockupTranched, nftDescriptor) = _run(initialAdmin); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx(address initialAdmin) public virtual @@ -55,8 +55,8 @@ contract DeployCore is BaseScript { ) { nftDescriptor = new SablierV2NFTDescriptor(); - lockupDynamic = new SablierV2LockupDynamic(initialAdmin, nftDescriptor, maxCount); + lockupDynamic = new SablierV2LockupDynamic(initialAdmin, nftDescriptor, maxSegmentCount); lockupLinear = new SablierV2LockupLinear(initialAdmin, nftDescriptor); - lockupTranched = new SablierV2LockupTranched(initialAdmin, nftDescriptor, maxCount); + lockupTranched = new SablierV2LockupTranched(initialAdmin, nftDescriptor, maxTrancheCount); } } diff --git a/script/DeployCore2.s.sol b/script/DeployCore2.s.sol index 3f52967b2..012e1294c 100644 --- a/script/DeployCore2.s.sol +++ b/script/DeployCore2.s.sol @@ -14,7 +14,7 @@ import { BaseScript } from "./Base.s.sol"; /// 2. {SablierV2LockupLinear} /// 3. {SablierV2LockupTranched} contract DeployCore2 is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor nftDescriptor @@ -31,7 +31,7 @@ contract DeployCore2 is BaseScript { (lockupDynamic, lockupLinear, lockupTranched) = _run(initialAdmin, nftDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor nftDescriptor @@ -59,8 +59,8 @@ contract DeployCore2 is BaseScript { SablierV2LockupTranched lockupTranched ) { - lockupDynamic = new SablierV2LockupDynamic(initialAdmin, nftDescriptor, maxCount); + lockupDynamic = new SablierV2LockupDynamic(initialAdmin, nftDescriptor, maxSegmentCount); lockupLinear = new SablierV2LockupLinear(initialAdmin, nftDescriptor); - lockupTranched = new SablierV2LockupTranched(initialAdmin, nftDescriptor, maxCount); + lockupTranched = new SablierV2LockupTranched(initialAdmin, nftDescriptor, maxTrancheCount); } } diff --git a/script/DeployDeterministicCore.s.sol b/script/DeployDeterministicCore.s.sol index 22eaddabf..a20dc6540 100644 --- a/script/DeployDeterministicCore.s.sol +++ b/script/DeployDeterministicCore.s.sol @@ -17,7 +17,7 @@ import { BaseScript } from "./Base.s.sol"; /// /// @dev Reverts if any contract has already been deployed. contract DeployDeterministicCore is BaseScript { - /// @dev Deploy using Forge. + /// @dev Deploy via Forge. function runBroadcast(address initialAdmin) public virtual @@ -32,7 +32,7 @@ contract DeployDeterministicCore is BaseScript { (lockupDynamic, lockupLinear, lockupTranched, nftDescriptor) = _run(initialAdmin); } - /// @dev Deploy using Sphinx. + /// @dev Deploy via Sphinx. function runSphinx(address initialAdmin) public virtual @@ -58,8 +58,8 @@ contract DeployDeterministicCore is BaseScript { { bytes32 salt = constructCreate2Salt(); nftDescriptor = new SablierV2NFTDescriptor{ salt: salt }(); - lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, nftDescriptor, maxCount); + lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, nftDescriptor, maxSegmentCount); lockupLinear = new SablierV2LockupLinear{ salt: salt }(initialAdmin, nftDescriptor); - lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, nftDescriptor, maxCount); + lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, nftDescriptor, maxTrancheCount); } } diff --git a/script/DeployDeterministicCore2.s.sol b/script/DeployDeterministicCore2.s.sol index 83d78b6ca..36232a624 100644 --- a/script/DeployDeterministicCore2.s.sol +++ b/script/DeployDeterministicCore2.s.sol @@ -16,7 +16,7 @@ import { BaseScript } from "./Base.s.sol"; /// /// @dev Reverts if any contract has already been deployed. contract DeployDeterministicCore2 is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor nftDescriptor @@ -33,7 +33,7 @@ contract DeployDeterministicCore2 is BaseScript { (lockupDynamic, lockupLinear, lockupTranched) = _run(initialAdmin, nftDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor nftDescriptor @@ -62,8 +62,8 @@ contract DeployDeterministicCore2 is BaseScript { ) { bytes32 salt = constructCreate2Salt(); - lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, nftDescriptor, maxCount); + lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, nftDescriptor, maxSegmentCount); lockupLinear = new SablierV2LockupLinear{ salt: salt }(initialAdmin, nftDescriptor); - lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, nftDescriptor, maxCount); + lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, nftDescriptor, maxTrancheCount); } } diff --git a/script/DeployDeterministicLockupDynamic.s.sol b/script/DeployDeterministicLockupDynamic.s.sol index d8b2a9e65..78dfbe962 100644 --- a/script/DeployDeterministicLockupDynamic.s.sol +++ b/script/DeployDeterministicLockupDynamic.s.sol @@ -9,7 +9,7 @@ import { BaseScript } from "./Base.s.sol"; /// @notice Deploys {SablierV2LockupDynamic} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. contract DeployDeterministicLockupDynamic is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -22,7 +22,7 @@ contract DeployDeterministicLockupDynamic is BaseScript { lockupDynamic = _run(initialAdmin, initialNFTDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -43,6 +43,6 @@ contract DeployDeterministicLockupDynamic is BaseScript { returns (SablierV2LockupDynamic lockupDynamic) { bytes32 salt = constructCreate2Salt(); - lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, initialNFTDescriptor, maxCount); + lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, initialNFTDescriptor, maxSegmentCount); } } diff --git a/script/DeployDeterministicLockupLinear.s.sol b/script/DeployDeterministicLockupLinear.s.sol index 47dc07651..81ca7ffcb 100644 --- a/script/DeployDeterministicLockupLinear.s.sol +++ b/script/DeployDeterministicLockupLinear.s.sol @@ -9,7 +9,7 @@ import { BaseScript } from "./Base.s.sol"; /// @dev Deploys {SablierV2LockupLinear} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. contract DeployDeterministicLockupLinear is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -22,7 +22,7 @@ contract DeployDeterministicLockupLinear is BaseScript { lockupLinear = _run(initialAdmin, initialNFTDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor diff --git a/script/DeployDeterministicLockupTranched.s.sol b/script/DeployDeterministicLockupTranched.s.sol index 08a3e550c..148a3023f 100644 --- a/script/DeployDeterministicLockupTranched.s.sol +++ b/script/DeployDeterministicLockupTranched.s.sol @@ -9,7 +9,7 @@ import { BaseScript } from "./Base.s.sol"; /// @dev Deploys {SablierV2LockupTranched} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. contract DeployDeterministicLockupTranched is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -22,7 +22,7 @@ contract DeployDeterministicLockupTranched is BaseScript { lockupTranched = _run(initialAdmin, initialNFTDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -43,6 +43,6 @@ contract DeployDeterministicLockupTranched is BaseScript { returns (SablierV2LockupTranched lockupTranched) { bytes32 salt = constructCreate2Salt(); - lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, initialNFTDescriptor, maxCount); + lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, initialNFTDescriptor, maxTrancheCount); } } diff --git a/script/DeployDeterministicNFTDescriptor.s.sol b/script/DeployDeterministicNFTDescriptor.s.sol index 21de03352..6cdde5c09 100644 --- a/script/DeployDeterministicNFTDescriptor.s.sol +++ b/script/DeployDeterministicNFTDescriptor.s.sol @@ -8,12 +8,12 @@ import { BaseScript } from "./Base.s.sol"; /// @dev Deploys {SablierV2NFTDescriptor} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. contract DeployDeterministicNFTDescriptor is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast() public virtual broadcast returns (SablierV2NFTDescriptor nftDescriptor) { nftDescriptor = _run(); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx() public virtual sphinx returns (SablierV2NFTDescriptor nftDescriptor) { nftDescriptor = _run(); } diff --git a/script/DeployLockupDynamic.s.sol b/script/DeployLockupDynamic.s.sol index 73ee2f387..fca805329 100644 --- a/script/DeployLockupDynamic.s.sol +++ b/script/DeployLockupDynamic.s.sol @@ -7,7 +7,7 @@ import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol"; import { BaseScript } from "./Base.s.sol"; contract DeployLockupDynamic is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -20,7 +20,7 @@ contract DeployLockupDynamic is BaseScript { lockupDynamic = _run(initialAdmin, initialNFTDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -40,6 +40,6 @@ contract DeployLockupDynamic is BaseScript { internal returns (SablierV2LockupDynamic lockupDynamic) { - lockupDynamic = new SablierV2LockupDynamic(initialAdmin, initialNFTDescriptor, maxCount); + lockupDynamic = new SablierV2LockupDynamic(initialAdmin, initialNFTDescriptor, maxSegmentCount); } } diff --git a/script/DeployLockupLinear.s.sol b/script/DeployLockupLinear.s.sol index 4690ab9a3..c7a4bb85c 100644 --- a/script/DeployLockupLinear.s.sol +++ b/script/DeployLockupLinear.s.sol @@ -7,7 +7,7 @@ import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol"; import { BaseScript } from "./Base.s.sol"; contract DeployLockupLinear is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -20,7 +20,7 @@ contract DeployLockupLinear is BaseScript { lockupLinear = _run(initialAdmin, initialNFTDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor diff --git a/script/DeployLockupTranched.s.sol b/script/DeployLockupTranched.s.sol index 1c5c97878..520a659ad 100644 --- a/script/DeployLockupTranched.s.sol +++ b/script/DeployLockupTranched.s.sol @@ -7,7 +7,7 @@ import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol"; import { BaseScript } from "./Base.s.sol"; contract DeployLockupTranched is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -20,7 +20,7 @@ contract DeployLockupTranched is BaseScript { lockupTranched = _run(initialAdmin, initialNFTDescriptor); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx( address initialAdmin, ISablierV2NFTDescriptor initialNFTDescriptor @@ -40,6 +40,6 @@ contract DeployLockupTranched is BaseScript { internal returns (SablierV2LockupTranched lockupTranched) { - lockupTranched = new SablierV2LockupTranched(initialAdmin, initialNFTDescriptor, maxCount); + lockupTranched = new SablierV2LockupTranched(initialAdmin, initialNFTDescriptor, maxTrancheCount); } } diff --git a/script/DeployNFTDescriptor.s.sol b/script/DeployNFTDescriptor.s.sol index 2649b5159..32bfeebff 100644 --- a/script/DeployNFTDescriptor.s.sol +++ b/script/DeployNFTDescriptor.s.sol @@ -6,12 +6,12 @@ import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol"; import { BaseScript } from "./Base.s.sol"; contract DeployNFTDescriptor is BaseScript { - /// @dev Deploy using Forge CLI. + /// @dev Deploy via Forge. function runBroadcast() public virtual broadcast returns (SablierV2NFTDescriptor nftDescriptor) { nftDescriptor = _run(); } - /// @dev Deploy using Sphinx CLI. + /// @dev Deploy via Sphinx. function runSphinx() public virtual sphinx returns (SablierV2NFTDescriptor nftDescriptor) { nftDescriptor = _run(); } diff --git a/script/GenerateSVG.s.sol b/script/GenerateSVG.s.sol index 1ee151a7b..9a3b63b98 100644 --- a/script/GenerateSVG.s.sol +++ b/script/GenerateSVG.s.sol @@ -38,11 +38,11 @@ contract GenerateSVG is BaseScript, SablierV2NFTDescriptor { assetAddress: DAI.toHexString(), assetSymbol: "DAI", duration: calculateDurationInDays({ startTime: 0, endTime: duration * 1 days }), - sablierAddress: LOCKUP_LINEAR.toHexString(), progress: stringifyPercentage(progress), progressNumerical: progress, - status: status, - streamingModel: "Lockup Linear" + sablierAddress: LOCKUP_LINEAR.toHexString(), + sablierModel: "Lockup Linear", + status: status }) ); } diff --git a/slither.config.json b/slither.config.json index 918d41bd7..edcc0bbb4 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,9 +1,10 @@ { "detectors_to_exclude": "naming-convention,reentrancy-events,solc-version,timestamp", - "filter_paths": "(node_modules,test)", + "filter_paths": "(node_modules/,test/)", "solc_remaps": [ "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "@prb/math/=node_modules/@prb-math/", + "@sphinx-labs/contracts/=node_modules/@sphinx-labs/contracts/contracts/foundry/", "forge-std/=node_modules/forge-std/", "solady/=node_modules/solady/", "solarray/=node_modules/solarray/" diff --git a/src/SablierV2LockupDynamic.sol b/src/SablierV2LockupDynamic.sol index 53bbdf28a..13a28d69d 100644 --- a/src/SablierV2LockupDynamic.sol +++ b/src/SablierV2LockupDynamic.sol @@ -49,7 +49,7 @@ contract SablierV2LockupDynamic is /// @inheritdoc ISablierV2LockupDynamic uint256 public immutable override MAX_SEGMENT_COUNT; - /// @dev Stream segments mapped by stream ids. + /// @dev Stream segments mapped by stream IDs. This complements the `_streams` mapping in {SablierV2Lockup}. mapping(uint256 id => LockupDynamic.Segment[] segments) internal _segments; /*////////////////////////////////////////////////////////////////////////// @@ -106,7 +106,7 @@ contract SablierV2LockupDynamic is notNull(streamId) returns (LockupDynamic.StreamLD memory stream) { - // Retrieve the lockup stream from storage. + // Retrieve the Lockup stream from storage. Lockup.Stream memory lockupStream = _streams[streamId]; // Settled streams cannot be canceled. @@ -119,9 +119,9 @@ contract SablierV2LockupDynamic is asset: lockupStream.asset, endTime: lockupStream.endTime, isCancelable: lockupStream.isCancelable, - isTransferable: lockupStream.isTransferable, isDepleted: lockupStream.isDepleted, isStream: lockupStream.isStream, + isTransferable: lockupStream.isTransferable, recipient: _ownerOf(streamId), segments: _segments[streamId], sender: lockupStream.sender, @@ -145,7 +145,7 @@ contract SablierV2LockupDynamic is LockupDynamic.Segment[] memory segments = Helpers.calculateSegmentTimestamps(params.segments); // Checks, Effects and Interactions: create the stream. - streamId = _createWithTimestamps( + streamId = _create( LockupDynamic.CreateWithTimestamps({ sender: params.sender, recipient: params.recipient, @@ -168,7 +168,7 @@ contract SablierV2LockupDynamic is returns (uint256 streamId) { // Checks, Effects and Interactions: create the stream. - streamId = _createWithTimestamps(params); + streamId = _create(params); } /*////////////////////////////////////////////////////////////////////////// @@ -176,7 +176,7 @@ contract SablierV2LockupDynamic is //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc SablierV2Lockup - /// @dev The streaming function is: + /// @dev The distribution function is: /// /// $$ /// f(x) = x^{exp} * csa + \Sigma(esa) @@ -184,25 +184,25 @@ contract SablierV2LockupDynamic is /// /// Where: /// - /// - $x$ is the elapsed time divided by the total time in the current segment. + /// - $x$ is the elapsed time divided by the total duration of the current segment. /// - $exp$ is the current segment exponent. /// - $csa$ is the current segment amount. - /// - $\Sigma(esa)$ is the sum of all elapsed segments' amounts. + /// - $\Sigma(esa)$ is the sum of all vested segments' amounts. function _calculateStreamedAmount(uint256 streamId) internal view override returns (uint128) { // If the start time is in the future, return zero. - uint40 currentTime = uint40(block.timestamp); - if (_streams[streamId].startTime >= currentTime) { + uint40 blockTimestamp = uint40(block.timestamp); + if (_streams[streamId].startTime >= blockTimestamp) { return 0; } // If the end time is not in the future, return the deposited amount. uint40 endTime = _streams[streamId].endTime; - if (endTime <= currentTime) { + if (endTime <= blockTimestamp) { return _streams[streamId].amounts.deposited; } if (_segments[streamId].length > 1) { - // If there is more than one segment, it may be necessary to iterate over all of them. + // If there is more than one segment, it may be required to iterate over all of them. return _calculateStreamedAmountForMultipleSegments(streamId); } else { // Otherwise, there is only one segment, and the calculation is simpler. @@ -220,15 +220,15 @@ contract SablierV2LockupDynamic is /// bounds" error. function _calculateStreamedAmountForMultipleSegments(uint256 streamId) internal view returns (uint128) { unchecked { - uint40 currentTime = uint40(block.timestamp); + uint40 blockTimestamp = uint40(block.timestamp); Lockup.Stream memory stream = _streams[streamId]; LockupDynamic.Segment[] memory segments = _segments[streamId]; - // Sum the amounts in all segments that precede the current time. + // Sum the amounts in all segments that precede the block timestamp. uint128 previousSegmentAmounts; uint40 currentSegmentTimestamp = segments[0].timestamp; uint256 index = 0; - while (currentSegmentTimestamp < currentTime) { + while (currentSegmentTimestamp < blockTimestamp) { previousSegmentAmounts += segments[index].amount; index += 1; currentSegmentTimestamp = segments[index].timestamp; @@ -245,20 +245,20 @@ contract SablierV2LockupDynamic is // time as the previous timestamp. previousTimestamp = stream.startTime; } else { - // Otherwise, when the current segment's index is greater than 0, it implies that the segment is not + // Otherwise, when the current segment's index is greater than zero, it means that the segment is not // the first. In this case, use the previous segment's timestamp. previousTimestamp = segments[index - 1].timestamp; } - // Calculate how much time has passed since the segment started, and the total time of the segment. - SD59x18 elapsedSegmentTime = (currentTime - previousTimestamp).intoSD59x18(); - SD59x18 totalSegmentTime = (currentSegmentTimestamp - previousTimestamp).intoSD59x18(); + // Calculate how much time has passed since the segment started, and the total duration of the segment. + SD59x18 elapsedTime = (blockTimestamp - previousTimestamp).intoSD59x18(); + SD59x18 segmentDuration = (currentSegmentTimestamp - previousTimestamp).intoSD59x18(); - // Divide the elapsed segment time by the total duration of the segment. - SD59x18 elapsedSegmentTimePercentage = elapsedSegmentTime.div(totalSegmentTime); + // Divide the elapsed time by the total duration of the segment. + SD59x18 elapsedTimePercentage = elapsedTime.div(segmentDuration); // Calculate the streamed amount using the special formula. - SD59x18 multiplier = elapsedSegmentTimePercentage.pow(currentSegmentExponent); + SD59x18 multiplier = elapsedTimePercentage.pow(currentSegmentExponent); SD59x18 segmentStreamedAmount = multiplier.mul(currentSegmentAmount); // Although the segment streamed amount should never exceed the total segment amount, this condition is @@ -283,10 +283,10 @@ contract SablierV2LockupDynamic is unchecked { // Calculate how much time has passed since the stream started, and the stream's total duration. SD59x18 elapsedTime = (uint40(block.timestamp) - _streams[streamId].startTime).intoSD59x18(); - SD59x18 totalTime = (_streams[streamId].endTime - _streams[streamId].startTime).intoSD59x18(); + SD59x18 totalDuration = (_streams[streamId].endTime - _streams[streamId].startTime).intoSD59x18(); // Divide the elapsed time by the stream's total duration. - SD59x18 elapsedTimePercentage = elapsedTime.div(totalTime); + SD59x18 elapsedTimePercentage = elapsedTime.div(totalDuration); // Cast the stream parameters to SD59x18. SD59x18 exponent = _segments[streamId][0].exponent.intoSD59x18(); @@ -313,27 +313,24 @@ contract SablierV2LockupDynamic is //////////////////////////////////////////////////////////////////////////*/ /// @dev See the documentation for the user-facing functions that call this internal function. - function _createWithTimestamps(LockupDynamic.CreateWithTimestamps memory params) - internal - returns (uint256 streamId) - { - // Checks: check the broker fee and calculate the amounts. + function _create(LockupDynamic.CreateWithTimestamps memory params) internal returns (uint256 streamId) { + // Check: verify the broker fee and calculate the amounts. Lockup.CreateAmounts memory createAmounts = Helpers.checkAndCalculateBrokerFee(params.totalAmount, params.broker.fee, MAX_BROKER_FEE); - // Checks: validate the user-provided parameters. - Helpers.checkCreateWithTimestamps(createAmounts.deposit, params.segments, MAX_SEGMENT_COUNT, params.startTime); + // Check: validate the user-provided parameters. + Helpers.checkCreateLockupDynamic(createAmounts.deposit, params.segments, MAX_SEGMENT_COUNT, params.startTime); - // Load the stream id in a variable. + // Load the stream ID in a variable. streamId = nextStreamId; - // Effects: create the stream. + // Effect: create the stream. Lockup.Stream storage stream = _streams[streamId]; stream.amounts.deposited = createAmounts.deposit; stream.asset = params.asset; stream.isCancelable = params.cancelable; - stream.isTransferable = params.transferable; stream.isStream = true; + stream.isTransferable = params.transferable; stream.sender = params.sender; stream.startTime = params.startTime; @@ -342,24 +339,24 @@ contract SablierV2LockupDynamic is uint256 segmentCount = params.segments.length; stream.endTime = params.segments[segmentCount - 1].timestamp; - // Effects: store the segments. Since Solidity lacks a syntax for copying arrays directly from + // Effect: store the segments. Since Solidity lacks a syntax for copying arrays of structs directly from // memory to storage, a manual approach is necessary. See https://github.com/ethereum/solidity/issues/12783. for (uint256 i = 0; i < segmentCount; ++i) { _segments[streamId].push(params.segments[i]); } - // Effects: bump the next stream id. + // Effect: bump the next stream ID. // Using unchecked arithmetic because these calculations cannot realistically overflow, ever. nextStreamId = streamId + 1; } - // Effects: mint the NFT to the recipient. + // Effect: mint the NFT to the recipient. _mint({ to: params.recipient, tokenId: streamId }); - // Interactions: transfer the deposit amount. + // Interaction: transfer the deposit amount. params.asset.safeTransferFrom({ from: msg.sender, to: address(this), value: createAmounts.deposit }); - // Interactions: pay the broker fee, if not zero. + // Interaction: pay the broker fee, if not zero. if (createAmounts.brokerFee > 0) { params.asset.safeTransferFrom({ from: msg.sender, to: params.broker.account, value: createAmounts.brokerFee }); } diff --git a/src/SablierV2LockupLinear.sol b/src/SablierV2LockupLinear.sol index cf6db6f6f..6051b7365 100644 --- a/src/SablierV2LockupLinear.sol +++ b/src/SablierV2LockupLinear.sol @@ -43,7 +43,7 @@ contract SablierV2LockupLinear is STATE VARIABLES //////////////////////////////////////////////////////////////////////////*/ - /// @dev Cliff times mapped by stream ids. + /// @dev Cliff times mapped by stream IDs. This complements the `_streams` mapping in {SablierV2Lockup}. mapping(uint256 id => uint40 cliff) internal _cliffs; /*////////////////////////////////////////////////////////////////////////// @@ -95,7 +95,7 @@ contract SablierV2LockupLinear is notNull(streamId) returns (LockupLinear.StreamLL memory stream) { - // Retrieve the lockup stream from storage. + // Retrieve the Lockup stream from storage. Lockup.Stream memory lockupStream = _streams[streamId]; // Settled streams cannot be canceled. @@ -134,20 +134,18 @@ contract SablierV2LockupLinear is LockupLinear.Range memory range; range.start = uint40(block.timestamp); - // Calculate the cliff time and the end time. It is safe to use unchecked arithmetic because - // {_createWithTimestamps} will nonetheless check that the end time is greater than the cliff time, - // and also that the cliff time, if set, is greater than or equal to the start time. + // Calculate the cliff time and the end time. It is safe to use unchecked arithmetic because {_create} will + // nonetheless check that the end time is greater than the cliff time, and also that the cliff time, if set, + // is greater than or equal to the start time. unchecked { - // If the cliff duration is greater than zero, calculate the cliff time. if (params.durations.cliff > 0) { range.cliff = range.start + params.durations.cliff; } - range.end = range.start + params.durations.total; } // Checks, Effects and Interactions: create the stream. - streamId = _createWithTimestamps( + streamId = _create( LockupLinear.CreateWithTimestamps({ sender: params.sender, recipient: params.recipient, @@ -169,7 +167,7 @@ contract SablierV2LockupLinear is returns (uint256 streamId) { // Checks, Effects and Interactions: create the stream. - streamId = _createWithTimestamps(params); + streamId = _create(params); } /*////////////////////////////////////////////////////////////////////////// @@ -177,7 +175,7 @@ contract SablierV2LockupLinear is //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc SablierV2Lockup - /// @dev The streaming function is: + /// @dev The distribution function is: /// /// $$ /// f(x) = x * d + c @@ -191,14 +189,14 @@ contract SablierV2LockupLinear is function _calculateStreamedAmount(uint256 streamId) internal view override returns (uint128) { // If the cliff time is in the future, return zero. uint256 cliffTime = uint256(_cliffs[streamId]); - uint256 currentTime = block.timestamp; - if (cliffTime > currentTime) { + uint256 blockTimestamp = block.timestamp; + if (cliffTime > blockTimestamp) { return 0; } // If the end time is not in the future, return the deposited amount. uint256 endTime = uint256(_streams[streamId].endTime); - if (currentTime >= endTime) { + if (blockTimestamp >= endTime) { return _streams[streamId].amounts.deposited; } @@ -207,11 +205,11 @@ contract SablierV2LockupLinear is unchecked { // Calculate how much time has passed since the stream started, and the stream's total duration. uint256 startTime = uint256(_streams[streamId].startTime); - UD60x18 elapsedTime = ud(currentTime - startTime); - UD60x18 totalTime = ud(endTime - startTime); + UD60x18 elapsedTime = ud(blockTimestamp - startTime); + UD60x18 totalDuration = ud(endTime - startTime); // Divide the elapsed time by the stream's total duration. - UD60x18 elapsedTimePercentage = elapsedTime.div(totalTime); + UD60x18 elapsedTimePercentage = elapsedTime.div(totalDuration); // Cast the deposited amount to UD60x18. UD60x18 depositedAmount = ud(_streams[streamId].amounts.deposited); @@ -236,52 +234,49 @@ contract SablierV2LockupLinear is //////////////////////////////////////////////////////////////////////////*/ /// @dev See the documentation for the user-facing functions that call this internal function. - function _createWithTimestamps(LockupLinear.CreateWithTimestamps memory params) - internal - returns (uint256 streamId) - { - // Checks: check the broker fee and calculate the amounts. + function _create(LockupLinear.CreateWithTimestamps memory params) internal returns (uint256 streamId) { + // Check: verify the broker fee and calculate the amounts. Lockup.CreateAmounts memory createAmounts = Helpers.checkAndCalculateBrokerFee(params.totalAmount, params.broker.fee, MAX_BROKER_FEE); - // Checks: validate the user-provided parameters. - Helpers.checkCreateWithTimestamps(createAmounts.deposit, params.range); + // Check: validate the user-provided parameters. + Helpers.checkCreateLockupLinear(createAmounts.deposit, params.range); - // Load the stream id. + // Load the stream ID. streamId = nextStreamId; - // Effects: create the stream. + // Effect: create the stream. _streams[streamId] = Lockup.Stream({ amounts: Lockup.Amounts({ deposited: createAmounts.deposit, refunded: 0, withdrawn: 0 }), asset: params.asset, endTime: params.range.end, isCancelable: params.cancelable, - isTransferable: params.transferable, isDepleted: false, isStream: true, + isTransferable: params.transferable, sender: params.sender, startTime: params.range.start, wasCanceled: false }); - // Effects: set the cliff time if it is greater than 0. + // Effect: set the cliff time if it is greater than zero. if (params.range.cliff > 0) { _cliffs[streamId] = params.range.cliff; } - // Effects: bump the next stream id. + // Effect: bump the next stream ID. // Using unchecked arithmetic because these calculations cannot realistically overflow, ever. unchecked { nextStreamId = streamId + 1; } - // Effects: mint the NFT to the recipient. + // Effect: mint the NFT to the recipient. _mint({ to: params.recipient, tokenId: streamId }); - // Interactions: transfer the deposit amount. + // Interaction: transfer the deposit amount. params.asset.safeTransferFrom({ from: msg.sender, to: address(this), value: createAmounts.deposit }); - // Interactions: pay the broker fee, if not zero. + // Interaction: pay the broker fee, if not zero. if (createAmounts.brokerFee > 0) { params.asset.safeTransferFrom({ from: msg.sender, to: params.broker.account, value: createAmounts.brokerFee }); } diff --git a/src/SablierV2LockupTranched.sol b/src/SablierV2LockupTranched.sol index 9625b5249..d39df2eb6 100644 --- a/src/SablierV2LockupTranched.sol +++ b/src/SablierV2LockupTranched.sol @@ -44,7 +44,7 @@ contract SablierV2LockupTranched is /// @inheritdoc ISablierV2LockupTranched uint256 public immutable override MAX_TRANCHE_COUNT; - /// @dev Stream tranches mapped by stream ids. + /// @dev Stream tranches mapped by stream IDs. This complements the `_streams` mapping in {SablierV2Lockup}. mapping(uint256 id => LockupTranched.Tranche[] tranches) internal _tranches; /*////////////////////////////////////////////////////////////////////////// @@ -90,7 +90,7 @@ contract SablierV2LockupTranched is notNull(streamId) returns (LockupTranched.StreamLT memory stream) { - // Retrieve the lockup stream from storage. + // Retrieve the Lockup stream from storage. Lockup.Stream memory lockupStream = _streams[streamId]; // Settled streams cannot be canceled. @@ -103,9 +103,9 @@ contract SablierV2LockupTranched is asset: lockupStream.asset, endTime: lockupStream.endTime, isCancelable: lockupStream.isCancelable, - isTransferable: lockupStream.isTransferable, isDepleted: lockupStream.isDepleted, isStream: lockupStream.isStream, + isTransferable: lockupStream.isTransferable, recipient: _ownerOf(streamId), sender: lockupStream.sender, startTime: lockupStream.startTime, @@ -140,7 +140,7 @@ contract SablierV2LockupTranched is LockupTranched.Tranche[] memory tranches = Helpers.calculateTrancheTimestamps(params.tranches); // Checks, Effects and Interactions: create the stream. - streamId = _createWithTimestamps( + streamId = _create( LockupTranched.CreateWithTimestamps({ sender: params.sender, recipient: params.recipient, @@ -163,7 +163,7 @@ contract SablierV2LockupTranched is returns (uint256 streamId) { // Checks, Effects and Interactions: create the stream. - streamId = _createWithTimestamps(params); + streamId = _create(params); } /*////////////////////////////////////////////////////////////////////////// @@ -171,7 +171,7 @@ contract SablierV2LockupTranched is //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc SablierV2Lockup - /// @dev The streaming function is: + /// @dev The distribution function is: /// /// $$ /// f(x) = \Sigma(eta) @@ -179,30 +179,33 @@ contract SablierV2LockupTranched is /// /// Where: /// - /// - $\Sigma(eta)$ is the sum of all elapsed tranches' amounts. + /// - $\Sigma(eta)$ is the sum of all vested tranches' amounts. function _calculateStreamedAmount(uint256 streamId) internal view override returns (uint128) { - uint40 currentTime = uint40(block.timestamp); + uint40 blockTimestamp = uint40(block.timestamp); LockupTranched.Tranche[] memory tranches = _tranches[streamId]; - // If the first timestamp in the tranches is in the future, return zero. - if (tranches[0].timestamp > currentTime) { + // If the first tranche's timestamp is in the future, return zero. + if (tranches[0].timestamp > blockTimestamp) { return 0; } // If the end time is not in the future, return the deposited amount. - if (_streams[streamId].endTime <= currentTime) { + if (_streams[streamId].endTime <= blockTimestamp) { return _streams[streamId].amounts.deposited; } - // Sum the amounts in all tranches that precede the current time. + // Sum the amounts in all tranches that have already been vested. // Using unchecked arithmetic is safe because the sum of the tranche amounts is equal to the total amount // at this point. uint128 streamedAmount = tranches[0].amount; - uint256 index = 1; - unchecked { - while (tranches[index].timestamp <= currentTime) { - streamedAmount += tranches[index].amount; - index += 1; + for (uint256 i = 1; i < tranches.length; ++i) { + // The loop breaks at the first tranche with a timestamp in the future. A tranche is considered vested if + // its timestamp is less than or equal to the block timestamp. + if (tranches[i].timestamp > blockTimestamp) { + break; + } + unchecked { + streamedAmount += tranches[i].amount; } } @@ -214,27 +217,24 @@ contract SablierV2LockupTranched is //////////////////////////////////////////////////////////////////////////*/ /// @dev See the documentation for the user-facing functions that call this internal function. - function _createWithTimestamps(LockupTranched.CreateWithTimestamps memory params) - internal - returns (uint256 streamId) - { - // Checks: check the broker fee and calculate the amounts. + function _create(LockupTranched.CreateWithTimestamps memory params) internal returns (uint256 streamId) { + // Check: verify the broker fee and calculate the amounts. Lockup.CreateAmounts memory createAmounts = Helpers.checkAndCalculateBrokerFee(params.totalAmount, params.broker.fee, MAX_BROKER_FEE); - // Checks: validate the user-provided parameters. - Helpers.checkCreateWithTimestamps(createAmounts.deposit, params.tranches, MAX_TRANCHE_COUNT, params.startTime); + // Check: validate the user-provided parameters. + Helpers.checkCreateLockupTranched(createAmounts.deposit, params.tranches, MAX_TRANCHE_COUNT, params.startTime); - // Load the stream id in a variable. + // Load the stream ID in a variable. streamId = nextStreamId; - // Effects: create the stream. + // Effect: create the stream. Lockup.Stream storage stream = _streams[streamId]; stream.amounts.deposited = createAmounts.deposit; stream.asset = params.asset; stream.isCancelable = params.cancelable; - stream.isTransferable = params.transferable; stream.isStream = true; + stream.isTransferable = params.transferable; stream.sender = params.sender; stream.startTime = params.startTime; @@ -243,24 +243,24 @@ contract SablierV2LockupTranched is uint256 trancheCount = params.tranches.length; stream.endTime = params.tranches[trancheCount - 1].timestamp; - // Effects: store the tranches. Since Solidity lacks a syntax for copying arrays directly from + // Effect: store the tranches. Since Solidity lacks a syntax for copying arrays of structs directly from // memory to storage, a manual approach is necessary. See https://github.com/ethereum/solidity/issues/12783. for (uint256 i = 0; i < trancheCount; ++i) { _tranches[streamId].push(params.tranches[i]); } - // Effects: bump the next stream id. + // Effect: bump the next stream ID. // Using unchecked arithmetic because these calculations cannot realistically overflow, ever. nextStreamId = streamId + 1; } - // Effects: mint the NFT to the recipient. + // Effect: mint the NFT to the recipient. _mint({ to: params.recipient, tokenId: streamId }); - // Interactions: transfer the deposit amount. + // Interaction: transfer the deposit amount. params.asset.safeTransferFrom({ from: msg.sender, to: address(this), value: createAmounts.deposit }); - // Interactions: pay the broker fee, if not zero. + // Interaction: pay the broker fee, if not zero. if (createAmounts.brokerFee > 0) { params.asset.safeTransferFrom({ from: msg.sender, to: params.broker.account, value: createAmounts.brokerFee }); } diff --git a/src/SablierV2NFTDescriptor.sol b/src/SablierV2NFTDescriptor.sol index db7fd5656..abe47289e 100644 --- a/src/SablierV2NFTDescriptor.sol +++ b/src/SablierV2NFTDescriptor.sol @@ -33,11 +33,11 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { uint128 depositedAmount; string json; ISablierV2Lockup sablier; - string sablierAddress; + string sablierModel; + string sablierStringified; string status; string svg; uint256 streamedPercentage; - string streamingModel; } /// @inheritdoc ISablierV2NFTDescriptor @@ -46,7 +46,8 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { // Load the contracts. vars.sablier = ISablierV2Lockup(address(sablier)); - vars.sablierAddress = address(sablier).toHexString(); + vars.sablierModel = mapSymbol(sablier); + vars.sablierStringified = address(sablier).toHexString(); vars.asset = address(vars.sablier.getAsset(streamId)); vars.assetSymbol = safeAssetSymbol(vars.asset); vars.depositedAmount = vars.sablier.getDepositedAmount(streamId); @@ -57,7 +58,6 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { streamedAmount: vars.sablier.streamedAmountOf(streamId), depositedAmount: vars.depositedAmount }); - vars.streamingModel = mapSymbol(sablier); // Generate the SVG. vars.svg = NFTSVG.generateSVG( @@ -70,11 +70,11 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { startTime: vars.sablier.getStartTime(streamId), endTime: vars.sablier.getEndTime(streamId) }), - sablierAddress: vars.sablierAddress, + sablierAddress: vars.sablierStringified, progress: stringifyPercentage(vars.streamedPercentage), progressNumerical: vars.streamedPercentage, status: vars.status, - streamingModel: vars.streamingModel + sablierModel: vars.sablierModel }) ); @@ -88,15 +88,15 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { }), ',"description":"', generateDescription({ - streamingModel: vars.streamingModel, + sablierModel: vars.sablierModel, assetSymbol: vars.assetSymbol, - sablierAddress: vars.sablierAddress, + sablierStringified: vars.sablierStringified, assetAddress: vars.asset.toHexString(), streamId: streamId.toString(), isTransferable: vars.sablier.isTransferable(streamId) }), '","external_url":"https://sablier.com","name":"', - generateName({ streamingModel: vars.streamingModel, streamId: streamId.toString() }), + generateName({ sablierModel: vars.sablierModel, streamId: streamId.toString() }), '","image":"data:image/svg+xml;base64,', Base64.encode(bytes(vars.svg)), '"}' @@ -194,7 +194,7 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { /// @notice Generates a pseudo-random HSL color by hashing together the `chainid`, the `sablier` address, /// and the `streamId`. This will be used as the accent color for the SVG. function generateAccentColor(address sablier, uint256 streamId) internal view returns (string memory) { - // The chain id is part of the hash so that the generated color is different across chains. + // The chain ID is part of the hash so that the generated color is different across chains. uint256 chainId = block.chainid; // Hash the parameters to generate a pseudo-random bit field, which will be used as entropy. @@ -249,9 +249,9 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { /// @notice Generates a string with the NFT's JSON metadata description, which provides a high-level overview. function generateDescription( - string memory streamingModel, + string memory sablierModel, string memory assetSymbol, - string memory sablierAddress, + string memory sablierStringified, string memory assetAddress, string memory streamId, bool isTransferable @@ -268,15 +268,15 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { return string.concat( "This NFT represents a payment stream in a Sablier V2 ", - streamingModel, + sablierModel, " contract. The owner of this NFT can withdraw the streamed assets, which are denominated in ", assetSymbol, ".\\n\\n- Stream ID: ", streamId, "\\n- ", - streamingModel, + sablierModel, " Address: ", - sablierAddress, + sablierStringified, "\\n- ", assetSymbol, " Address: ", @@ -288,11 +288,11 @@ contract SablierV2NFTDescriptor is ISablierV2NFTDescriptor { /// @notice Generates a string with the NFT's JSON metadata name, which is unique for each stream. /// @dev The `streamId` is equivalent to the ERC-721 `tokenId`. - function generateName(string memory streamingModel, string memory streamId) internal pure returns (string memory) { - return string.concat("Sablier V2 ", streamingModel, " #", streamId); + function generateName(string memory sablierModel, string memory streamId) internal pure returns (string memory) { + return string.concat("Sablier V2 ", sablierModel, " #", streamId); } - /// @notice Maps ERC-721 symbols to human-readable streaming models. + /// @notice Maps ERC-721 symbols to human-readable model names. /// @dev Reverts if the symbol is unknown. function mapSymbol(IERC721Metadata sablier) internal view returns (string memory) { string memory symbol = sablier.symbol(); diff --git a/src/abstracts/Adminable.sol b/src/abstracts/Adminable.sol index aac440d29..add9799a0 100644 --- a/src/abstracts/Adminable.sol +++ b/src/abstracts/Adminable.sol @@ -32,7 +32,7 @@ abstract contract Adminable is IAdminable { /// @inheritdoc IAdminable function transferAdmin(address newAdmin) public virtual override onlyAdmin { - // Effects: update the admin. + // Effect: update the admin. admin = newAdmin; // Log the transfer of the admin. diff --git a/src/abstracts/SablierV2Lockup.sol b/src/abstracts/SablierV2Lockup.sol index 526813cd0..6ca1f99de 100644 --- a/src/abstracts/SablierV2Lockup.sol +++ b/src/abstracts/SablierV2Lockup.sol @@ -102,7 +102,7 @@ abstract contract SablierV2Lockup is /// @inheritdoc ISablierV2Lockup function getRecipient(uint256 streamId) external view override returns (address recipient) { - // Checks: the stream NFT exists and return the owner, which is the stream's recipient. + // Check the stream NFT exists and return the owner, which is the stream's recipient. recipient = _requireOwned({ tokenId: streamId }); } @@ -207,7 +207,7 @@ abstract contract SablierV2Lockup is /// @inheritdoc ERC721 function tokenURI(uint256 streamId) public view override(IERC721Metadata, ERC721) returns (string memory uri) { - // Checks: the stream NFT exists. + // Check: the stream NFT exists. _requireOwned({ tokenId: streamId }); // Generate the URI describing the stream NFT. @@ -236,32 +236,32 @@ abstract contract SablierV2Lockup is /// @inheritdoc ISablierV2Lockup function burn(uint256 streamId) external override noDelegateCall notNull(streamId) { - // Checks: only depleted streams can be burned. + // Check: only depleted streams can be burned. if (!_streams[streamId].isDepleted) { revert Errors.SablierV2Lockup_StreamNotDepleted(streamId); } - // Checks: + // Check: // 1. NFT exists (see {IERC721.getApproved}). // 2. `msg.sender` is either the owner of the NFT or an approved third party. if (!_isCallerStreamRecipientOrApproved(streamId)) { revert Errors.SablierV2Lockup_Unauthorized(streamId, msg.sender); } - // Effects: burn the NFT. + // Effect: burn the NFT. _burn({ tokenId: streamId }); } /// @inheritdoc ISablierV2Lockup function cancel(uint256 streamId) public override noDelegateCall notNull(streamId) { - // Checks: the stream is neither depleted nor canceled. + // Check: the stream is neither depleted nor canceled. if (_streams[streamId].isDepleted) { revert Errors.SablierV2Lockup_StreamDepleted(streamId); } else if (_streams[streamId].wasCanceled) { revert Errors.SablierV2Lockup_StreamCanceled(streamId); } - // Checks: `msg.sender` is the stream's sender. + // Check: `msg.sender` is the stream's sender. if (!_isCallerStreamSender(streamId)) { revert Errors.SablierV2Lockup_Unauthorized(streamId, msg.sender); } @@ -272,7 +272,7 @@ abstract contract SablierV2Lockup is /// @inheritdoc ISablierV2Lockup function cancelMultiple(uint256[] calldata streamIds) external override noDelegateCall { - // Iterate over the provided array of stream ids and cancel each stream. + // Iterate over the provided array of stream IDs and cancel each stream. uint256 count = streamIds.length; for (uint256 i = 0; i < count; ++i) { // Effects and Interactions: cancel the stream. @@ -282,7 +282,7 @@ abstract contract SablierV2Lockup is /// @inheritdoc ISablierV2Lockup function renounce(uint256 streamId) external override noDelegateCall notNull(streamId) updateMetadata(streamId) { - // Checks: the stream is not cold. + // Check: the stream is not cold. Lockup.Status status = _statusOf(streamId); if (status == Lockup.Status.DEPLETED) { revert Errors.SablierV2Lockup_StreamDepleted(streamId); @@ -292,7 +292,7 @@ abstract contract SablierV2Lockup is revert Errors.SablierV2Lockup_StreamSettled(streamId); } - // Checks: `msg.sender` is the stream's sender. + // Check: `msg.sender` is the stream's sender. if (!_isCallerStreamSender(streamId)) { revert Errors.SablierV2Lockup_Unauthorized(streamId, msg.sender); } @@ -303,7 +303,7 @@ abstract contract SablierV2Lockup is // Log the renouncement. emit ISablierV2Lockup.RenounceLockupStream(streamId); - // Interactions: if the recipient is a contract, try to invoke the renounce hook on the recipient without + // Interaction: if the recipient is a contract, try to invoke the renounce hook on the recipient without // reverting if the hook is not implemented, and also without bubbling up any potential revert. address recipient = _ownerOf(streamId); if (recipient.code.length > 0) { @@ -313,7 +313,7 @@ abstract contract SablierV2Lockup is /// @inheritdoc ISablierV2Lockup function setNFTDescriptor(ISablierV2NFTDescriptor newNFTDescriptor) external override onlyAdmin { - // Effects: set the NFT descriptor. + // Effect: set the NFT descriptor. ISablierV2NFTDescriptor oldNftDescriptor = nftDescriptor; nftDescriptor = newNFTDescriptor; @@ -340,17 +340,17 @@ abstract contract SablierV2Lockup is notNull(streamId) updateMetadata(streamId) { - // Checks: the stream is not depleted. + // Check: the stream is not depleted. if (_streams[streamId].isDepleted) { revert Errors.SablierV2Lockup_StreamDepleted(streamId); } - // Checks: the withdrawal address is not zero. + // Check: the withdrawal address is not zero. if (to == address(0)) { - revert Errors.SablierV2Lockup_WithdrawToZeroAddress(); + revert Errors.SablierV2Lockup_WithdrawToZeroAddress(streamId); } - // Checks: the withdraw amount is not zero. + // Check: the withdraw amount is not zero. if (amount == 0) { revert Errors.SablierV2Lockup_WithdrawAmountZero(streamId); } @@ -358,13 +358,13 @@ abstract contract SablierV2Lockup is // Retrieve the recipient from storage. address recipient = _ownerOf(streamId); - // Checks: if `msg.sender` is neither the stream's recipient nor an approved third party, the withdrawal address + // Check: if `msg.sender` is neither the stream's recipient nor an approved third party, the withdrawal address // must be the recipient. if (to != recipient && !_isCallerStreamRecipientOrApproved(streamId)) { revert Errors.SablierV2Lockup_WithdrawalAddressNotRecipient(streamId, msg.sender, to); } - // Checks: the withdraw amount is not greater than the withdrawable amount. + // Check: the withdraw amount is not greater than the withdrawable amount. uint128 withdrawableAmount = _withdrawableAmountOf(streamId); if (amount > withdrawableAmount) { revert Errors.SablierV2Lockup_Overdraw(streamId, amount, withdrawableAmount); @@ -376,7 +376,7 @@ abstract contract SablierV2Lockup is // Effects and Interactions: make the withdrawal. _withdraw(streamId, to, amount); - // Interactions: if `msg.sender` is not the recipient and the recipient is a contract, try to invoke the + // Interaction: if `msg.sender` is not the recipient and the recipient is a contract, try to invoke the // withdraw hook on it without reverting if the hook is not implemented, and also without bubbling up // any potential revert. if (msg.sender != recipient && recipient.code.length > 0) { @@ -388,7 +388,7 @@ abstract contract SablierV2Lockup is }) { } catch { } } - // Interactions: if `msg.sender` is not the sender, the sender is a contract and sender is different from the + // Interaction: if `msg.sender` is not the sender, the sender is a contract and is different from the // recipient, try to invoke the withdraw hook on it without reverting if the hook is not implemented, and also // without bubbling up any potential revert. if (msg.sender != sender && sender.code.length > 0 && sender != recipient) { @@ -416,7 +416,7 @@ abstract contract SablierV2Lockup is noDelegateCall notNull(streamId) { - // Checks: the caller is the current recipient. This also checks that the NFT was not burned. + // Check: the caller is the current recipient. This also checks that the NFT was not burned. address currentRecipient = _ownerOf(streamId); if (msg.sender != currentRecipient) { revert Errors.SablierV2Lockup_Unauthorized(streamId, msg.sender); @@ -441,14 +441,14 @@ abstract contract SablierV2Lockup is override noDelegateCall { - // Checks: there is an equal number of `streamIds` and `amounts`. + // Check: there is an equal number of `streamIds` and `amounts`. uint256 streamIdsCount = streamIds.length; uint256 amountsCount = amounts.length; if (streamIdsCount != amountsCount) { revert Errors.SablierV2Lockup_WithdrawArrayCountsNotEqual(streamIdsCount, amountsCount); } - // Iterate over the provided array of stream ids and withdraw from each stream. + // Iterate over the provided array of stream IDs, and withdraw from each stream to the recipient. for (uint256 i = 0; i < streamIdsCount; ++i) { // Checks, Effects and Interactions: check the parameters and make the withdrawal. withdraw({ streamId: streamIds[i], to: _ownerOf(streamIds[i]), amount: amounts[i] }); @@ -459,12 +459,12 @@ abstract contract SablierV2Lockup is INTERNAL CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @notice Calculates the streamed amount of the stream without looking up the stream's status, which is - /// implemented by child contracts, it can vary depending on the model. + /// @notice Calculates the streamed amount of the stream without looking up the stream's status. + /// @dev This function is implemented by child contracts, so the logic varies depending on the model. function _calculateStreamedAmount(uint256 streamId) internal view virtual returns (uint128); /// @notice Checks whether `msg.sender` is the stream's recipient or an approved third party. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function _isCallerStreamRecipientOrApproved(uint256 streamId) internal view returns (bool) { address recipient = _ownerOf(streamId); return msg.sender == recipient || isApprovedForAll({ owner: recipient, operator: msg.sender }) @@ -472,7 +472,7 @@ abstract contract SablierV2Lockup is } /// @notice Checks whether `msg.sender` is the stream's sender. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function _isCallerStreamSender(uint256 streamId) internal view returns (bool) { return msg.sender == _streams[streamId].sender; } @@ -509,15 +509,15 @@ abstract contract SablierV2Lockup is return _calculateStreamedAmount(streamId); } - /// @notice Overrides the internal ERC-721 `_update` function to check that the stream is transferable and emit - /// an ERC-4906 event. + /// @notice Overrides the {ERC-721._update} function to check that the stream is transferable, and emits an + /// ERC-4906 event. /// @dev There are two cases when the transferable flag is ignored: - /// - If `from` is 0, then the update is a mint and is allowed. + /// - If the current owner is 0, then the update is a mint and is allowed. /// - If `to` is 0, then the update is a burn and is also allowed. /// @param to The address of the new recipient of the stream. - /// @param streamId Id of the stream to update. - /// @param auth Optional parameter. If the value is non 0, the upstream implementation of this function will check - /// that `auth` is either the recipient of the stream, or an approved third party. + /// @param streamId ID of the stream to update. + /// @param auth Optional parameter. If the value is not zero, the overridden implementation will check that + /// `auth` is either the recipient of the stream, or an approved third party. /// @return The original recipient of the `streamId` before the update. function _update( address to, @@ -531,7 +531,7 @@ abstract contract SablierV2Lockup is { address from = _ownerOf(streamId); - if (!_streams[streamId].isTransferable && from != address(0) && to != address(0)) { + if (from != address(0) && to != address(0) && !_streams[streamId].isTransferable) { revert Errors.SablierV2Lockup_NotTransferable(streamId); } @@ -555,12 +555,12 @@ abstract contract SablierV2Lockup is // Retrieve the amounts from storage. Lockup.Amounts memory amounts = _streams[streamId].amounts; - // Checks: the stream is not settled. + // Check: the stream is not settled. if (streamedAmount >= amounts.deposited) { revert Errors.SablierV2Lockup_StreamSettled(streamId); } - // Checks: the stream is cancelable. + // Check: the stream is cancelable. if (!_streams[streamId].isCancelable) { revert Errors.SablierV2Lockup_StreamNotCancelable(streamId); } @@ -569,18 +569,18 @@ abstract contract SablierV2Lockup is uint128 senderAmount = amounts.deposited - streamedAmount; uint128 recipientAmount = streamedAmount - amounts.withdrawn; - // Effects: mark the stream as canceled. + // Effect: mark the stream as canceled. _streams[streamId].wasCanceled = true; - // Effects: make the stream not cancelable anymore, because a stream can only be canceled once. + // Effect: make the stream not cancelable anymore, because a stream can only be canceled once. _streams[streamId].isCancelable = false; - // Effects: If there are no assets left for the recipient to withdraw, mark the stream as depleted. + // Effect: if there are no assets left for the recipient to withdraw, mark the stream as depleted. if (recipientAmount == 0) { _streams[streamId].isDepleted = true; } - // Effects: set the refunded amount. + // Effect: set the refunded amount. _streams[streamId].amounts.refunded = senderAmount; // Retrieve the sender and the recipient from storage. @@ -590,7 +590,7 @@ abstract contract SablierV2Lockup is // Retrieve the ERC-20 asset from storage. IERC20 asset = _streams[streamId].asset; - // Interactions: refund the sender. + // Interaction: refund the sender. asset.safeTransfer({ to: sender, value: senderAmount }); // Log the cancellation. @@ -599,7 +599,7 @@ abstract contract SablierV2Lockup is // Emits an ERC-4906 event to trigger an update of the NFT metadata. emit MetadataUpdate({ _tokenId: streamId }); - // Interactions: if the recipient is a contract, try to invoke the cancel hook on the recipient without + // Interaction: if the recipient is a contract, try to invoke the cancel hook on the recipient without // reverting if the hook is not implemented, and without bubbling up any potential revert. if (recipient.code.length > 0) { try ISablierV2Recipient(recipient).onLockupStreamCanceled({ @@ -613,18 +613,18 @@ abstract contract SablierV2Lockup is /// @dev See the documentation for the user-facing functions that call this internal function. function _renounce(uint256 streamId) internal { - // Checks: the stream is cancelable. + // Check: the stream is cancelable. if (!_streams[streamId].isCancelable) { revert Errors.SablierV2Lockup_StreamNotCancelable(streamId); } - // Effects: renounce the stream by making it not cancelable. + // Effect: renounce the stream by making it not cancelable. _streams[streamId].isCancelable = false; } /// @dev See the documentation for the user-facing functions that call this internal function. function _withdraw(uint256 streamId, address to, uint128 amount) internal { - // Effects: update the withdrawn amount. + // Effect: update the withdrawn amount. _streams[streamId].amounts.withdrawn = _streams[streamId].amounts.withdrawn + amount; // Retrieve the amounts from storage. @@ -633,17 +633,17 @@ abstract contract SablierV2Lockup is // Using ">=" instead of "==" for additional safety reasons. In the event of an unforeseen increase in the // withdrawn amount, the stream will still be marked as depleted. if (amounts.withdrawn >= amounts.deposited - amounts.refunded) { - // Effects: mark the stream as depleted. + // Effect: mark the stream as depleted. _streams[streamId].isDepleted = true; - // Effects: make the stream not cancelable anymore, because a depleted stream cannot be canceled. + // Effect: make the stream not cancelable anymore, because a depleted stream cannot be canceled. _streams[streamId].isCancelable = false; } // Retrieve the ERC-20 asset from storage. IERC20 asset = _streams[streamId].asset; - // Interactions: perform the ERC-20 transfer. + // Interaction: perform the ERC-20 transfer. asset.safeTransfer({ to: to, value: amount }); // Log the withdrawal. diff --git a/src/interfaces/ISablierV2Lockup.sol b/src/interfaces/ISablierV2Lockup.sol index 22419db24..28c00f8ce 100644 --- a/src/interfaces/ISablierV2Lockup.sol +++ b/src/interfaces/ISablierV2Lockup.sol @@ -10,7 +10,7 @@ import { IAdminable } from "./IAdminable.sol"; import { ISablierV2NFTDescriptor } from "./ISablierV2NFTDescriptor.sol"; /// @title ISablierV2Lockup -/// @notice Common logic between all Sablier V2 Lockup streaming contracts. +/// @notice Common logic between all Sablier V2 Lockup contracts. interface ISablierV2Lockup is IAdminable, // 0 inherited components IERC721Metadata // 2 inherited components @@ -20,10 +20,10 @@ interface ISablierV2Lockup is //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when a stream is canceled. - /// @param streamId The id of the stream. + /// @param streamId The ID of the stream. /// @param sender The address of the stream's sender. /// @param recipient The address of the stream's recipient. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param senderAmount The amount of assets refunded to the stream's sender, denoted in units of the asset's /// decimals. /// @param recipientAmount The amount of assets left for the stream's recipient to withdraw, denoted in units of the @@ -38,7 +38,7 @@ interface ISablierV2Lockup is ); /// @notice Emitted when a sender gives up the right to cancel a stream. - /// @param streamId The id of the stream. + /// @param streamId The ID of the stream. event RenounceLockupStream(uint256 indexed streamId); /// @notice Emitted when the admin sets a new NFT descriptor contract. @@ -50,9 +50,9 @@ interface ISablierV2Lockup is ); /// @notice Emitted when assets are withdrawn from a stream. - /// @param streamId The id of the stream. + /// @param streamId The ID of the stream. /// @param to The address that has received the withdrawn assets. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param amount The amount of assets withdrawn, denoted in units of the asset's decimals. event WithdrawFromLockupStream(uint256 indexed streamId, address indexed to, IERC20 indexed asset, uint128 amount); @@ -60,76 +60,76 @@ interface ISablierV2Lockup is CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @notice Retrieves the address of the ERC-20 asset used for streaming. + /// @notice Retrieves the address of the ERC-20 asset to be distributed. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getAsset(uint256 streamId) external view returns (IERC20 asset); /// @notice Retrieves the amount deposited in the stream, denoted in units of the asset's decimals. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getDepositedAmount(uint256 streamId) external view returns (uint128 depositedAmount); /// @notice Retrieves the stream's end time, which is a Unix timestamp. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getEndTime(uint256 streamId) external view returns (uint40 endTime); /// @notice Retrieves the stream's recipient. /// @dev Reverts if the NFT has been burned. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getRecipient(uint256 streamId) external view returns (address recipient); /// @notice Retrieves the amount refunded to the sender after a cancellation, denoted in units of the asset's /// decimals. This amount is always zero unless the stream was canceled. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getRefundedAmount(uint256 streamId) external view returns (uint128 refundedAmount); /// @notice Retrieves the stream's sender. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getSender(uint256 streamId) external view returns (address sender); /// @notice Retrieves the stream's start time, which is a Unix timestamp. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getStartTime(uint256 streamId) external view returns (uint40 startTime); /// @notice Retrieves the amount withdrawn from the stream, denoted in units of the asset's decimals. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getWithdrawnAmount(uint256 streamId) external view returns (uint128 withdrawnAmount); /// @notice Retrieves a flag indicating whether the stream can be canceled. When the stream is cold, this /// flag is always `false`. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function isCancelable(uint256 streamId) external view returns (bool result); /// @notice Retrieves a flag indicating whether the stream is cold, i.e. settled, canceled, or depleted. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function isCold(uint256 streamId) external view returns (bool result); /// @notice Retrieves a flag indicating whether the stream is depleted. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function isDepleted(uint256 streamId) external view returns (bool result); /// @notice Retrieves a flag indicating whether the stream exists. /// @dev Does not revert if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function isStream(uint256 streamId) external view returns (bool result); /// @notice Retrieves a flag indicating whether the stream NFT can be transferred. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function isTransferable(uint256 streamId) external view returns (bool result); /// @notice Retrieves a flag indicating whether the stream is warm, i.e. either pending or streaming. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function isWarm(uint256 streamId) external view returns (bool result); /// @notice Retrieves the maximum broker fee that can be charged by the broker, denoted as a fixed-point @@ -137,7 +137,7 @@ interface ISablierV2Lockup is /// @dev This value is hard coded as a constant. function MAX_BROKER_FEE() external view returns (UD60x18); - /// @notice Counter for stream ids, used in the create functions. + /// @notice Counter for stream IDs, used in the create functions. function nextStreamId() external view returns (uint256); /// @notice Contract that generates the non-fungible token URI. @@ -146,11 +146,11 @@ interface ISablierV2Lockup is /// @notice Calculates the amount that the sender would be refunded if the stream were canceled, denoted in units /// of the asset's decimals. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function refundableAmountOf(uint256 streamId) external view returns (uint128 refundableAmount); /// @notice Retrieves the stream's status. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function statusOf(uint256 streamId) external view returns (Lockup.Status status); /// @notice Calculates the amount streamed to the recipient, denoted in units of the asset's decimals. @@ -161,18 +161,18 @@ interface ISablierV2Lockup is /// amount and the refunded amount. Ultimately, when the stream becomes depleted, the streamed amount is equivalent /// to the total amount withdrawn. /// - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function streamedAmountOf(uint256 streamId) external view returns (uint128 streamedAmount); /// @notice Retrieves a flag indicating whether the stream was canceled. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function wasCanceled(uint256 streamId) external view returns (bool result); /// @notice Calculates the amount that the recipient can withdraw from the stream, denoted in units of the asset's /// decimals. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function withdrawableAmountOf(uint256 streamId) external view returns (uint128 withdrawableAmount); /*////////////////////////////////////////////////////////////////////////// @@ -189,7 +189,7 @@ interface ISablierV2Lockup is /// - The NFT must exist. /// - `msg.sender` must be either the NFT owner or an approved third party. /// - /// @param streamId The id of the stream NFT to burn. + /// @param streamId The ID of the stream NFT to burn. function burn(uint256 streamId) external; /// @notice Cancels the stream and refunds any remaining assets to the sender. @@ -206,7 +206,7 @@ interface ISablierV2Lockup is /// - The stream must be warm and cancelable. /// - `msg.sender` must be the stream's sender. /// - /// @param streamId The id of the stream to cancel. + /// @param streamId The ID of the stream to cancel. function cancel(uint256 streamId) external; /// @notice Cancels multiple streams and refunds any remaining assets to the sender. @@ -219,7 +219,7 @@ interface ISablierV2Lockup is /// Requirements: /// - All requirements from {cancel} must be met for each stream. /// - /// @param streamIds The ids of the streams to cancel. + /// @param streamIds The IDs of the streams to cancel. function cancelMultiple(uint256[] calldata streamIds) external; /// @notice Removes the right of the stream's sender to cancel the stream. @@ -236,7 +236,7 @@ interface ISablierV2Lockup is /// - `msg.sender` must be the stream's sender. /// - The stream must be cancelable. /// - /// @param streamId The id of the stream to renounce. + /// @param streamId The ID of the stream to renounce. function renounce(uint256 streamId) external; /// @notice Sets a new NFT descriptor contract, which produces the URI describing the Sablier stream NFTs. @@ -267,7 +267,7 @@ interface ISablierV2Lockup is /// - `amount` must be greater than zero and must not exceed the withdrawable amount. /// - `to` must be the recipient if `msg.sender` is not the stream's recipient or an approved third party. /// - /// @param streamId The id of the stream to withdraw from. + /// @param streamId The ID of the stream to withdraw from. /// @param to The address receiving the withdrawn assets. /// @param amount The amount to withdraw, denoted in units of the asset's decimals. function withdraw(uint256 streamId, address to, uint128 amount) external; @@ -282,7 +282,7 @@ interface ISablierV2Lockup is /// Requirements: /// - Refer to the requirements in {withdraw}. /// - /// @param streamId The id of the stream to withdraw from. + /// @param streamId The ID of the stream to withdraw from. /// @param to The address receiving the withdrawn assets. function withdrawMax(uint256 streamId, address to) external; @@ -300,7 +300,7 @@ interface ISablierV2Lockup is /// - Refer to the requirements in {withdraw}. /// - Refer to the requirements in {IERC721.transferFrom}. /// - /// @param streamId The id of the stream NFT to transfer. + /// @param streamId The ID of the stream NFT to transfer. /// @param newRecipient The address of the new owner of the stream NFT. function withdrawMaxAndTransfer(uint256 streamId, address newRecipient) external; @@ -315,10 +315,10 @@ interface ISablierV2Lockup is /// Requirements: /// - Must not be delegate called. /// - There must be an equal number of `streamIds` and `amounts`. - /// - Each stream id in the array must not reference a null or depleted stream. + /// - Each stream ID in the array must not reference a null or depleted stream. /// - Each amount in the array must be greater than zero and must not exceed the withdrawable amount. /// - /// @param streamIds The ids of the streams to withdraw from. + /// @param streamIds The IDs of the streams to withdraw from. /// @param amounts The amounts to withdraw, denoted in units of the asset's decimals. function withdrawMultiple(uint256[] calldata streamIds, uint128[] calldata amounts) external; } diff --git a/src/interfaces/ISablierV2LockupDynamic.sol b/src/interfaces/ISablierV2LockupDynamic.sol index 13f69a2c2..8931d8845 100644 --- a/src/interfaces/ISablierV2LockupDynamic.sol +++ b/src/interfaces/ISablierV2LockupDynamic.sol @@ -7,23 +7,23 @@ import { Lockup, LockupDynamic } from "../types/DataTypes.sol"; import { ISablierV2Lockup } from "./ISablierV2Lockup.sol"; /// @title ISablierV2LockupDynamic -/// @notice Creates and manages Lockup streams with dynamic streaming functions. +/// @notice Creates and manages Lockup streams with a dynamic distribution function. interface ISablierV2LockupDynamic is ISablierV2Lockup { /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when a stream is created. - /// @param streamId The id of the newly created stream. + /// @param streamId The ID of the newly created stream. /// @param funder The address which has funded the stream. - /// @param sender The address from which to stream the assets, who will have the ability to cancel the stream. + /// @param sender The address distributing the assets, which will have the ability to cancel the stream. /// @param recipient The address toward which to stream the assets. /// @param amounts Struct containing (i) the deposit amount, and (ii) the broker fee amount, both denoted /// in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Boolean indicating whether the stream will be cancelable or not. /// @param transferable Boolean indicating whether the stream NFT is transferable or not. - /// @param segments The segments the protocol uses to compose the custom streaming curve. + /// @param segments The segments the protocol uses to compose the dynamic distribution function. /// @param range Struct containing (i) the stream's start time and (ii) end time, both as Unix timestamps. /// @param broker The address of the broker who has helped create the stream, e.g. a front-end website. event CreateLockupDynamicStream( @@ -44,19 +44,21 @@ interface ISablierV2LockupDynamic is ISablierV2Lockup { CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @notice Retrieves the stream's range, which is a struct documented in {DataTypes}. + /// @notice Retrieves the stream's range. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. + /// @return range See the documentation in {DataTypes}. function getRange(uint256 streamId) external view returns (LockupDynamic.Range memory range); - /// @notice Retrieves the segments the protocol uses to compose the custom streaming curve. + /// @notice Retrieves the segments used to compose the dynamic distribution function. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getSegments(uint256 streamId) external view returns (LockupDynamic.Segment[] memory segments); - /// @notice Retrieves the stream details, which is a struct documented in {DataTypes}. + /// @notice Retrieves the full stream details. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. + /// @return stream See the documentation in {DataTypes}. function getStream(uint256 streamId) external view returns (LockupDynamic.StreamLD memory stream); /// @notice The maximum number of segments allowed in a stream. @@ -77,7 +79,7 @@ interface ISablierV2LockupDynamic is ISablierV2Lockup { /// - All requirements in {createWithTimestamps} must be met for the calculated parameters. /// /// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}. - /// @return streamId The id of the newly created stream. + /// @return streamId The ID of the newly created stream. function createWithDurations(LockupDynamic.CreateWithDurations calldata params) external returns (uint256 streamId); @@ -95,7 +97,7 @@ interface ISablierV2LockupDynamic is ISablierV2Lockup { /// - Must not be delegate called. /// - `params.totalAmount` must be greater than zero. /// - If set, `params.broker.fee` must not be greater than `MAX_BROKER_FEE`. - /// - `params.startTime` must be greater than zero and less than the first segment's timestamp + /// - `params.startTime` must be greater than zero and less than the first segment's timestamp. /// - `params.segments` must have at least one segment, but not more than `MAX_SEGMENT_COUNT`. /// - The segment timestamps must be arranged in ascending order. /// - The last segment timestamp (i.e. the stream's end time) must be in the future. @@ -104,7 +106,7 @@ interface ISablierV2LockupDynamic is ISablierV2Lockup { /// - `msg.sender` must have allowed this contract to spend at least `params.totalAmount` assets. /// /// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}. - /// @return streamId The id of the newly created stream. + /// @return streamId The ID of the newly created stream. function createWithTimestamps(LockupDynamic.CreateWithTimestamps calldata params) external returns (uint256 streamId); diff --git a/src/interfaces/ISablierV2LockupLinear.sol b/src/interfaces/ISablierV2LockupLinear.sol index 63b1a8dc4..11d34e692 100644 --- a/src/interfaces/ISablierV2LockupLinear.sol +++ b/src/interfaces/ISablierV2LockupLinear.sol @@ -7,20 +7,20 @@ import { Lockup, LockupLinear } from "../types/DataTypes.sol"; import { ISablierV2Lockup } from "./ISablierV2Lockup.sol"; /// @title ISablierV2LockupLinear -/// @notice Creates and manages Lockup streams with linear streaming functions. +/// @notice Creates and manages Lockup streams with a linear distribution function. interface ISablierV2LockupLinear is ISablierV2Lockup { /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when a stream is created. - /// @param streamId The id of the newly created stream. + /// @param streamId The ID of the newly created stream. /// @param funder The address which funded the stream. - /// @param sender The address streaming the assets, with the ability to cancel the stream. + /// @param sender The address distributing the assets, which will have the ability to cancel the stream. /// @param recipient The address receiving the assets. /// @param amounts Struct containing (i) the deposit amount, and (ii) the broker fee amount, both denoted /// in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Boolean indicating whether the stream will be cancelable or not. /// @param transferable Boolean indicating whether the stream NFT is transferable or not. /// @param range Struct containing (i) the stream's start time, (ii) cliff time, and (iii) end time, all as Unix @@ -46,17 +46,19 @@ interface ISablierV2LockupLinear is ISablierV2Lockup { /// @notice Retrieves the stream's cliff time, which is a Unix timestamp. A value of zero means there /// is no cliff. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getCliffTime(uint256 streamId) external view returns (uint40 cliffTime); - /// @notice Retrieves the stream's range, which is a struct documented in {DataTypes}. + /// @notice Retrieves the stream's range. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. + /// @return range See the documentation in {DataTypes}. function getRange(uint256 streamId) external view returns (LockupLinear.Range memory range); - /// @notice Retrieves the stream details, which is a struct documented in {DataTypes}. + /// @notice Retrieves the full stream details. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. + /// @return stream See the documentation in {DataTypes}. function getStream(uint256 streamId) external view returns (LockupLinear.StreamLL memory stream); /*////////////////////////////////////////////////////////////////////////// @@ -73,7 +75,7 @@ interface ISablierV2LockupLinear is ISablierV2Lockup { /// - All requirements in {createWithTimestamps} must be met for the calculated parameters. /// /// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}. - /// @return streamId The id of the newly created stream. + /// @return streamId The ID of the newly created stream. function createWithDurations(LockupLinear.CreateWithDurations calldata params) external returns (uint256 streamId); @@ -98,7 +100,7 @@ interface ISablierV2LockupLinear is ISablierV2Lockup { /// - `msg.sender` must have allowed this contract to spend at least `params.totalAmount` assets. /// /// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}. - /// @return streamId The id of the newly created stream. + /// @return streamId The ID of the newly created stream. function createWithTimestamps(LockupLinear.CreateWithTimestamps calldata params) external returns (uint256 streamId); diff --git a/src/interfaces/ISablierV2LockupTranched.sol b/src/interfaces/ISablierV2LockupTranched.sol index 526b95ebf..137aefbb4 100644 --- a/src/interfaces/ISablierV2LockupTranched.sol +++ b/src/interfaces/ISablierV2LockupTranched.sol @@ -7,23 +7,23 @@ import { Lockup, LockupTranched } from "../types/DataTypes.sol"; import { ISablierV2Lockup } from "./ISablierV2Lockup.sol"; /// @title ISablierV2LockupTranched -/// @notice Creates and manages Lockup streams with tranches. +/// @notice Creates and manages Lockup streams with a tranched distribution function. interface ISablierV2LockupTranched is ISablierV2Lockup { /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when a stream is created. - /// @param streamId The id of the newly created stream. + /// @param streamId The ID of the newly created stream. /// @param funder The address which has funded the stream. - /// @param sender The address from which to stream the assets, who will have the ability to cancel the stream. + /// @param sender The address distributing the assets, which will have the ability to cancel the stream. /// @param recipient The address toward which to stream the assets. /// @param amounts Struct containing (i) the deposit amount, and (ii) the broker fee amount, both denoted /// in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Boolean indicating whether the stream will be cancelable or not. /// @param transferable Boolean indicating whether the stream NFT is transferable or not. - /// @param tranches The tranches the protocol uses to compose the custom streaming curve. + /// @param tranches The tranches the protocol uses to compose the tranched distribution function. /// @param range Struct containing (i) the stream's start time and (ii) end time, both as Unix timestamps. /// @param broker The address of the broker who has helped create the stream, e.g. a front-end website. event CreateLockupTranchedStream( @@ -44,19 +44,21 @@ interface ISablierV2LockupTranched is ISablierV2Lockup { CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @notice Retrieves the stream's range, which is a struct documented in {DataTypes}. + /// @notice Retrieves the stream's range. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. + /// @return range See the documentation in {DataTypes}. function getRange(uint256 streamId) external view returns (LockupTranched.Range memory range); - /// @notice Retrieves the stream details, which is a struct documented in {DataTypes}. + /// @notice Retrieves the full stream details. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. + /// @return stream See the documentation in {DataTypes}. function getStream(uint256 streamId) external view returns (LockupTranched.StreamLT memory stream); - /// @notice Retrieves the tranches the protocol uses to compose the custom distribution curve. + /// @notice Retrieves the tranches used to compose the tranched distribution function. /// @dev Reverts if `streamId` references a null stream. - /// @param streamId The stream id for the query. + /// @param streamId The stream ID for the query. function getTranches(uint256 streamId) external view returns (LockupTranched.Tranche[] memory tranches); /// @notice The maximum number of tranches allowed in a stream. @@ -77,7 +79,7 @@ interface ISablierV2LockupTranched is ISablierV2Lockup { /// - All requirements in {createWithTimestamps} must be met for the calculated parameters. /// /// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}. - /// @return streamId The id of the newly created stream. + /// @return streamId The ID of the newly created stream. function createWithDurations(LockupTranched.CreateWithDurations calldata params) external returns (uint256 streamId); @@ -95,7 +97,7 @@ interface ISablierV2LockupTranched is ISablierV2Lockup { /// - Must not be delegate called. /// - `params.totalAmount` must be greater than zero. /// - If set, `params.broker.fee` must not be greater than `MAX_BROKER_FEE`. - /// - `params.startTime` must be greater than zero and less than the first tranche's timestamp + /// - `params.startTime` must be greater than zero and less than the first tranche's timestamp. /// - `params.tranches` must have at least one tranche, but not more than `MAX_TRANCHE_COUNT`. /// - The tranche timestamps must be arranged in ascending order. /// - The last tranche timestamp (i.e. the stream's end time) must be in the future. @@ -104,7 +106,7 @@ interface ISablierV2LockupTranched is ISablierV2Lockup { /// - `msg.sender` must have allowed this contract to spend at least `params.totalAmount` assets. /// /// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}. - /// @return streamId The id of the newly created stream. + /// @return streamId The ID of the newly created stream. function createWithTimestamps(LockupTranched.CreateWithTimestamps calldata params) external returns (uint256 streamId); diff --git a/src/interfaces/ISablierV2NFTDescriptor.sol b/src/interfaces/ISablierV2NFTDescriptor.sol index f2f757fdf..f0d134cb8 100644 --- a/src/interfaces/ISablierV2NFTDescriptor.sol +++ b/src/interfaces/ISablierV2NFTDescriptor.sol @@ -10,7 +10,7 @@ interface ISablierV2NFTDescriptor { /// @notice Produces the URI describing a particular stream NFT. /// @dev This is a data URI with the JSON contents directly inlined. /// @param sablier The address of the Sablier contract the stream was created in. - /// @param streamId The id of the stream for which to produce a description. + /// @param streamId The ID of the stream for which to produce a description. /// @return uri The URI of the ERC721-compliant metadata. function tokenURI(IERC721Metadata sablier, uint256 streamId) external view returns (string memory uri); } diff --git a/src/interfaces/hooks/ISablierV2Recipient.sol b/src/interfaces/hooks/ISablierV2Recipient.sol index 128d3b958..da95fc046 100644 --- a/src/interfaces/hooks/ISablierV2Recipient.sol +++ b/src/interfaces/hooks/ISablierV2Recipient.sol @@ -4,14 +4,14 @@ pragma solidity >=0.8.22; /// @title ISablierV2Recipient /// @notice Interface for recipient contracts capable of reacting to cancellations, renouncements, and withdrawals. /// @dev Implementation of this interface is optional. If a recipient contract doesn't implement this -/// interface or implements it partially, function execution will not revert. +/// interface or implements it partially, the function execution will not revert. interface ISablierV2Recipient { /// @notice Responds to sender-triggered cancellations. /// /// @dev Notes: /// - This function may revert, but the Sablier contract will ignore the revert. /// - /// @param streamId The id of the canceled stream. + /// @param streamId The ID of the canceled stream. /// @param sender The stream's sender, who canceled the stream. /// @param senderAmount The amount of assets refunded to the stream's sender, denoted in units of the asset's /// decimals. @@ -30,7 +30,7 @@ interface ISablierV2Recipient { /// @dev Notes: /// - This function may revert, but the Sablier contract will ignore the revert. /// - /// @param streamId The id of the renounced stream. + /// @param streamId The ID of the renounced stream. function onLockupStreamRenounced(uint256 streamId) external; /// @notice Responds to withdrawals triggered by any address except the contract implementing this interface. @@ -38,7 +38,7 @@ interface ISablierV2Recipient { /// @dev Notes: /// - This function may revert, but the Sablier contract will ignore the revert. /// - /// @param streamId The id of the stream being withdrawn from. + /// @param streamId The ID of the stream being withdrawn from. /// @param caller The original `msg.sender` address that triggered the withdrawal. /// @param to The address receiving the withdrawn assets. /// @param amount The amount of assets withdrawn, denoted in units of the asset's decimals. diff --git a/src/interfaces/hooks/ISablierV2Sender.sol b/src/interfaces/hooks/ISablierV2Sender.sol index 904380460..ab8e576ef 100644 --- a/src/interfaces/hooks/ISablierV2Sender.sol +++ b/src/interfaces/hooks/ISablierV2Sender.sol @@ -4,14 +4,14 @@ pragma solidity >=0.8.22; /// @title ISablierV2Sender /// @notice Interface for sender contracts capable of reacting to withdrawals. /// @dev Implementation of this interface is optional. If a sender contract doesn't implement this -/// interface or implements it partially, function execution will not revert. +/// interface, the function execution will not revert. interface ISablierV2Sender { /// @notice Responds to withdrawals triggered by any address except the contract implementing this interface. /// /// @dev Notes: /// - This function may revert, but the Sablier contract will ignore the revert. /// - /// @param streamId The id of the stream being withdrawn from. + /// @param streamId The ID of the stream being withdrawn from. /// @param caller The original `msg.sender` address that triggered the withdrawal. /// @param to The address receiving the withdrawn assets. /// @param amount The amount of assets withdrawn, denoted in units of the asset's decimals. diff --git a/src/libraries/Errors.sol b/src/libraries/Errors.sol index fc2554f35..a2899d746 100644 --- a/src/libraries/Errors.sol +++ b/src/libraries/Errors.sol @@ -28,12 +28,12 @@ library Errors { error SablierV2Lockup_DepositAmountZero(); /// @notice Thrown when trying to create a stream with an end time not in the future. - error SablierV2Lockup_EndTimeNotInTheFuture(uint40 currentTime, uint40 endTime); + error SablierV2Lockup_EndTimeNotInTheFuture(uint40 blockTimestamp, uint40 endTime); /// @notice Thrown when trying to transfer Stream NFT when transferability is disabled. error SablierV2Lockup_NotTransferable(uint256 tokenId); - /// @notice Thrown when the id references a null stream. + /// @notice Thrown when the ID references a null stream. error SablierV2Lockup_Null(uint256 streamId); /// @notice Thrown when trying to withdraw an amount greater than the withdrawable amount. @@ -66,12 +66,12 @@ library Errors { /// @notice Thrown when trying to withdraw zero assets from a stream. error SablierV2Lockup_WithdrawAmountZero(uint256 streamId); - /// @notice Thrown when trying to withdraw from multiple streams and the number of stream ids does + /// @notice Thrown when trying to withdraw from multiple streams and the number of stream IDs does /// not match the number of withdraw amounts. error SablierV2Lockup_WithdrawArrayCountsNotEqual(uint256 streamIdsCount, uint256 amountsCount); /// @notice Thrown when trying to withdraw to the zero address. - error SablierV2Lockup_WithdrawToZeroAddress(); + error SablierV2Lockup_WithdrawToZeroAddress(uint256 streamId); /*////////////////////////////////////////////////////////////////////////// SABLIER-V2-LOCKUP-DYNAMIC @@ -107,10 +107,11 @@ library Errors { /// @notice Thrown when trying to create a stream with a cliff time not strictly less than the end time. error SablierV2LockupLinear_CliffTimeNotLessThanEndTime(uint40 cliffTime, uint40 endTime); - /// @notice Thrown when trying to create a stream with a start time greater than the cliff time. + /// @notice Thrown when trying to create a stream with a start time not strictly less than the cliff time, when the + /// cliff time does not have a zero value. error SablierV2LockupLinear_StartTimeNotLessThanCliffTime(uint40 startTime, uint40 cliffTime); - /// @notice Thrown when trying to create a stream with a start time greater than the end time. + /// @notice Thrown when trying to create a stream with a start time not strictly less than the end time. error SablierV2LockupLinear_StartTimeNotLessThanEndTime(uint40 startTime, uint40 endTime); /*////////////////////////////////////////////////////////////////////////// diff --git a/src/libraries/Helpers.sol b/src/libraries/Helpers.sol index ff64f4ffb..d112ffa3f 100644 --- a/src/libraries/Helpers.sol +++ b/src/libraries/Helpers.sol @@ -13,6 +13,68 @@ library Helpers { INTERNAL CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ + /// @dev Calculate the timestamps and return the segments. + function calculateSegmentTimestamps(LockupDynamic.SegmentWithDuration[] memory segments) + internal + view + returns (LockupDynamic.Segment[] memory segmentsWithTimestamps) + { + uint256 segmentCount = segments.length; + segmentsWithTimestamps = new LockupDynamic.Segment[](segmentCount); + + // Make the block timestamp the stream's start time. + uint40 startTime = uint40(block.timestamp); + + // It is safe to use unchecked arithmetic because {SablierV2LockupDynamic-_create} will nonetheless check the + // correctness of the calculated segment timestamps. + unchecked { + // The first segment is precomputed because it is needed in the for loop below. + segmentsWithTimestamps[0] = LockupDynamic.Segment({ + amount: segments[0].amount, + exponent: segments[0].exponent, + timestamp: startTime + segments[0].duration + }); + + // Copy the segment amounts and exponents, and calculate the segment timestamps. + for (uint256 i = 1; i < segmentCount; ++i) { + segmentsWithTimestamps[i] = LockupDynamic.Segment({ + amount: segments[i].amount, + exponent: segments[i].exponent, + timestamp: segmentsWithTimestamps[i - 1].timestamp + segments[i].duration + }); + } + } + } + + /// @dev Calculate the timestamps and return the tranches. + function calculateTrancheTimestamps(LockupTranched.TrancheWithDuration[] memory tranches) + internal + view + returns (LockupTranched.Tranche[] memory tranchesWithTimestamps) + { + uint256 trancheCount = tranches.length; + tranchesWithTimestamps = new LockupTranched.Tranche[](trancheCount); + + // Make the block timestamp the stream's start time. + uint40 startTime = uint40(block.timestamp); + + // It is safe to use unchecked arithmetic because {SablierV2LockupTranched-_create} will nonetheless check the + // correctness of the calculated tranche timestamps. + unchecked { + // The first tranche is precomputed because it is needed in the for loop below. + tranchesWithTimestamps[0] = + LockupTranched.Tranche({ amount: tranches[0].amount, timestamp: startTime + tranches[0].duration }); + + // Copy the tranche amounts and calculate the tranche timestamps. + for (uint256 i = 1; i < trancheCount; ++i) { + tranchesWithTimestamps[i] = LockupTranched.Tranche({ + amount: tranches[i].amount, + timestamp: tranchesWithTimestamps[i - 1].timestamp + tranches[i].duration + }); + } + } + } + /// @dev Checks the broker fee is not greater than `maxBrokerFee`, and then calculates the broker fee amount and the /// deposit amount from the total amount. function checkAndCalculateBrokerFee( @@ -29,7 +91,7 @@ library Helpers { return Lockup.CreateAmounts(0, 0); } - // Checks: the broker fee is not greater than `maxBrokerFee`. + // Check: the broker fee is not greater than `maxBrokerFee`. if (brokerFee.gt(maxBrokerFee)) { revert Errors.SablierV2Lockup_BrokerFeeTooHigh(brokerFee, maxBrokerFee); } @@ -45,8 +107,8 @@ library Helpers { amounts.deposit = totalAmount - amounts.brokerFee; } - /// @dev Checks the parameters of the {SablierV2LockupDynamic-_createWithTimestamps} function. - function checkCreateWithTimestamps( + /// @dev Checks the parameters of the {SablierV2LockupDynamic-_create} function. + function checkCreateLockupDynamic( uint128 depositAmount, LockupDynamic.Segment[] memory segments, uint256 maxSegmentCount, @@ -55,67 +117,70 @@ library Helpers { internal view { - // Checks: the deposit amount is not zero. + // Check: the deposit amount is not zero. if (depositAmount == 0) { revert Errors.SablierV2Lockup_DepositAmountZero(); } - // Checks: the start time is not zero. + // Check: the start time is not zero. if (startTime == 0) { revert Errors.SablierV2Lockup_StartTimeZero(); } - // Checks: the segment count is not zero. + // Check: the segment count is not zero. uint256 segmentCount = segments.length; if (segmentCount == 0) { revert Errors.SablierV2LockupDynamic_SegmentCountZero(); } - // Checks: the segment count is not greater than the maximum allowed. + // Check: the segment count is not greater than the maximum allowed. if (segmentCount > maxSegmentCount) { revert Errors.SablierV2LockupDynamic_SegmentCountTooHigh(segmentCount); } - // Checks: requirements of segments variables. + // Check: requirements of segments. _checkSegments(segments, depositAmount, startTime); } - /// @dev Checks the parameters of the {SablierV2LockupLinear-_createWithTimestamps} function. - function checkCreateWithTimestamps(uint128 depositAmount, LockupLinear.Range memory range) internal view { - // Checks: the deposit amount is not zero. + /// @dev Checks the parameters of the {SablierV2LockupLinear-_create} function. + function checkCreateLockupLinear(uint128 depositAmount, LockupLinear.Range memory range) internal view { + // Check: the deposit amount is not zero. if (depositAmount == 0) { revert Errors.SablierV2Lockup_DepositAmountZero(); } - // Checks: the start time is not zero. + // Check: the start time is not zero. if (range.start == 0) { revert Errors.SablierV2Lockup_StartTimeZero(); } - // Checks: the start time is strictly less than the end time. - if (range.start >= range.end) { - revert Errors.SablierV2LockupLinear_StartTimeNotLessThanEndTime(range.start, range.end); - } + // Since a cliff time of zero means there is no cliff, the following checks are performed only if it's not zero. + if (range.cliff > 0) { + // Check: the start time is strictly less than the cliff time. + if (range.start >= range.cliff) { + revert Errors.SablierV2LockupLinear_StartTimeNotLessThanCliffTime(range.start, range.cliff); + } - // Checks: the start time is strictly less than the cliff time when cliff time is not zero. - if (range.cliff > 0 && range.start >= range.cliff) { - revert Errors.SablierV2LockupLinear_StartTimeNotLessThanCliffTime(range.start, range.cliff); + // Check: the cliff time is strictly less than the end time. + if (range.cliff >= range.end) { + revert Errors.SablierV2LockupLinear_CliffTimeNotLessThanEndTime(range.cliff, range.end); + } } - // Checks: the cliff time is strictly less than the end time. - if (range.cliff >= range.end) { - revert Errors.SablierV2LockupLinear_CliffTimeNotLessThanEndTime(range.cliff, range.end); + // Check: the start time is strictly less than the end time. + if (range.start >= range.end) { + revert Errors.SablierV2LockupLinear_StartTimeNotLessThanEndTime(range.start, range.end); } - // Checks: the end time is in the future. - uint40 currentTime = uint40(block.timestamp); - if (currentTime >= range.end) { - revert Errors.SablierV2Lockup_EndTimeNotInTheFuture(currentTime, range.end); + // Check: the end time is in the future. + uint40 blockTimestamp = uint40(block.timestamp); + if (blockTimestamp >= range.end) { + revert Errors.SablierV2Lockup_EndTimeNotInTheFuture(blockTimestamp, range.end); } } - /// @dev Checks the parameters of the {SablierV2LockupTranched-_createWithTimestamps} function. - function checkCreateWithTimestamps( + /// @dev Checks the parameters of the {SablierV2LockupTranched-_create} function. + function checkCreateLockupTranched( uint128 depositAmount, LockupTranched.Tranche[] memory tranches, uint256 maxTrancheCount, @@ -124,93 +189,31 @@ library Helpers { internal view { - // Checks: the deposit amount is not zero. + // Check: the deposit amount is not zero. if (depositAmount == 0) { revert Errors.SablierV2Lockup_DepositAmountZero(); } - // Checks: the start time is not zero. + // Check: the start time is not zero. if (startTime == 0) { revert Errors.SablierV2Lockup_StartTimeZero(); } - // Checks: the tranche count is not zero. + // Check: the tranche count is not zero. uint256 trancheCount = tranches.length; if (trancheCount == 0) { revert Errors.SablierV2LockupTranched_TrancheCountZero(); } - // Checks: the tranche count is not greater than the maximum allowed. + // Check: the tranche count is not greater than the maximum allowed. if (trancheCount > maxTrancheCount) { revert Errors.SablierV2LockupTranched_TrancheCountTooHigh(trancheCount); } - // Checks: requirements of tranches variables. + // Check: requirements of tranches. _checkTranches(tranches, depositAmount, startTime); } - /// @dev Calculate the timestamps and return the segments. - function calculateSegmentTimestamps(LockupDynamic.SegmentWithDuration[] memory segments) - internal - view - returns (LockupDynamic.Segment[] memory segmentsWithTimestamps) - { - uint256 segmentCount = segments.length; - segmentsWithTimestamps = new LockupDynamic.Segment[](segmentCount); - - // Make the current time the stream's start time. - uint40 startTime = uint40(block.timestamp); - - // It is safe to use unchecked arithmetic because {_createWithTimestamps} will nonetheless check the soundness - // of the calculated segment timestamps. - unchecked { - // Precompute the first segment because of the need to add the start time to the first segment duration. - segmentsWithTimestamps[0] = LockupDynamic.Segment({ - amount: segments[0].amount, - exponent: segments[0].exponent, - timestamp: startTime + segments[0].duration - }); - - // Copy the segment amounts and exponents, and calculate the segment timestamps. - for (uint256 i = 1; i < segmentCount; ++i) { - segmentsWithTimestamps[i] = LockupDynamic.Segment({ - amount: segments[i].amount, - exponent: segments[i].exponent, - timestamp: segmentsWithTimestamps[i - 1].timestamp + segments[i].duration - }); - } - } - } - - /// @dev Calculate the timestamps and return the tranches. - function calculateTrancheTimestamps(LockupTranched.TrancheWithDuration[] memory tranches) - internal - view - returns (LockupTranched.Tranche[] memory tranchesWithTimestamps) - { - uint256 trancheCount = tranches.length; - tranchesWithTimestamps = new LockupTranched.Tranche[](trancheCount); - - // Make the current time the stream's start time. - uint40 startTime = uint40(block.timestamp); - - // It is safe to use unchecked arithmetic because {_createWithTimestamps} will nonetheless check the soundness - // of the calculated tranche timestamps. - unchecked { - // Precompute the first tranche because of the need to add the start time to the first tranche duration. - tranchesWithTimestamps[0] = - LockupTranched.Tranche({ amount: tranches[0].amount, timestamp: startTime + tranches[0].duration }); - - // Copy the tranche amounts and calculate the tranche timestamps. - for (uint256 i = 1; i < trancheCount; ++i) { - tranchesWithTimestamps[i] = LockupTranched.Tranche({ - amount: tranches[i].amount, - timestamp: tranchesWithTimestamps[i - 1].timestamp + tranches[i].duration - }); - } - } - } - /*////////////////////////////////////////////////////////////////////////// PRIVATE CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ @@ -229,7 +232,7 @@ library Helpers { private view { - // Checks: the start time is strictly less than the first segment timestamp. + // Check: the start time is strictly less than the first segment timestamp. if (startTime >= segments[0].timestamp) { revert Errors.SablierV2LockupDynamic_StartTimeNotLessThanFirstSegmentTimestamp( startTime, segments[0].timestamp @@ -238,8 +241,8 @@ library Helpers { // Pre-declare the variables needed in the for loop. uint128 segmentAmountsSum; - uint40 currentTimestamp; - uint40 previousTimestamp; + uint40 currentSegmentTimestamp; + uint40 previousSegmentTimestamp; // Iterate over the segments to: // @@ -250,26 +253,27 @@ library Helpers { // Add the current segment amount to the sum. segmentAmountsSum += segments[index].amount; - // Checks: the current timestamp is strictly greater than the previous timestamp. - currentTimestamp = segments[index].timestamp; - if (currentTimestamp <= previousTimestamp) { + // Check: the current timestamp is strictly greater than the previous timestamp. + currentSegmentTimestamp = segments[index].timestamp; + if (currentSegmentTimestamp <= previousSegmentTimestamp) { revert Errors.SablierV2LockupDynamic_SegmentTimestampsNotOrdered( - index, previousTimestamp, currentTimestamp + index, previousSegmentTimestamp, currentSegmentTimestamp ); } // Make the current timestamp the previous timestamp of the next loop iteration. - previousTimestamp = currentTimestamp; + previousSegmentTimestamp = currentSegmentTimestamp; } - // Checks: the last timestamp is in the future. - // When the loop exits, the current timestamp is the last timestamp, i.e. the stream's end time. - uint40 currentTime = uint40(block.timestamp); - if (currentTime >= currentTimestamp) { - revert Errors.SablierV2Lockup_EndTimeNotInTheFuture(currentTime, currentTimestamp); + // Check: the last timestamp is in the future. + // When the loop exits, the current segment's timestamp is the last segment's timestamp, i.e. the stream's end + // time. The variable is not renamed for gas efficiency purposes. + uint40 blockTimestamp = uint40(block.timestamp); + if (blockTimestamp >= currentSegmentTimestamp) { + revert Errors.SablierV2Lockup_EndTimeNotInTheFuture(blockTimestamp, currentSegmentTimestamp); } - // Checks: the deposit amount is equal to the segment amounts sum. + // Check: the deposit amount is equal to the segment amounts sum. if (depositAmount != segmentAmountsSum) { revert Errors.SablierV2LockupDynamic_DepositAmountNotEqualToSegmentAmountsSum( depositAmount, segmentAmountsSum @@ -291,7 +295,7 @@ library Helpers { private view { - // Checks: the start time is strictly less than the first tranche timestamp. + // Check: the start time is strictly less than the first tranche timestamp. if (startTime >= tranches[0].timestamp) { revert Errors.SablierV2LockupTranched_StartTimeNotLessThanFirstTrancheTimestamp( startTime, tranches[0].timestamp @@ -300,8 +304,8 @@ library Helpers { // Pre-declare the variables needed in the for loop. uint128 trancheAmountsSum; - uint40 currentTimestamp; - uint40 previousTimestamp; + uint40 currentTrancheTimestamp; + uint40 previousTrancheTimestamp; // Iterate over the tranches to: // @@ -312,26 +316,27 @@ library Helpers { // Add the current tranche amount to the sum. trancheAmountsSum += tranches[index].amount; - // Checks: the current timestamp is strictly greater than the previous timestamp. - currentTimestamp = tranches[index].timestamp; - if (currentTimestamp <= previousTimestamp) { + // Check: the current timestamp is strictly greater than the previous timestamp. + currentTrancheTimestamp = tranches[index].timestamp; + if (currentTrancheTimestamp <= previousTrancheTimestamp) { revert Errors.SablierV2LockupTranched_TrancheTimestampsNotOrdered( - index, previousTimestamp, currentTimestamp + index, previousTrancheTimestamp, currentTrancheTimestamp ); } // Make the current timestamp the previous timestamp of the next loop iteration. - previousTimestamp = currentTimestamp; + previousTrancheTimestamp = currentTrancheTimestamp; } - // Checks: the last timestamp is in the future. - // When the loop exits, the current timestamp is the last timestamp, i.e. the stream's end time. - uint40 currentTime = uint40(block.timestamp); - if (currentTime >= currentTimestamp) { - revert Errors.SablierV2Lockup_EndTimeNotInTheFuture(currentTime, currentTimestamp); + // Check: the last timestamp is in the future. + // When the loop exits, the current tranche's timestamp is the last tranche's timestamp, i.e. the stream's end + // time. The variable is not renamed for gas efficiency purposes. + uint40 blockTimestamp = uint40(block.timestamp); + if (blockTimestamp >= currentTrancheTimestamp) { + revert Errors.SablierV2Lockup_EndTimeNotInTheFuture(blockTimestamp, currentTrancheTimestamp); } - // Checks: the deposit amount is equal to the tranche amounts sum. + // Check: the deposit amount is equal to the tranche amounts sum. if (depositAmount != trancheAmountsSum) { revert Errors.SablierV2LockupTranched_DepositAmountNotEqualToTrancheAmountsSum( depositAmount, trancheAmountsSum diff --git a/src/libraries/NFTSVG.sol b/src/libraries/NFTSVG.sol index dedd93cd1..0cfa05c0f 100644 --- a/src/libraries/NFTSVG.sol +++ b/src/libraries/NFTSVG.sol @@ -20,8 +20,8 @@ library NFTSVG { string progress; uint256 progressNumerical; string sablierAddress; + string sablierModel; string status; - string streamingModel; } struct SVGVars { @@ -89,7 +89,7 @@ library NFTSVG { '', SVGElements.BACKGROUND, generateDefs(params.accentColor, params.status, vars.cards), - generateFloatingText(params.sablierAddress, params.streamingModel, params.assetAddress, params.assetSymbol), + generateFloatingText(params.sablierAddress, params.sablierModel, params.assetAddress, params.assetSymbol), generateHrefs(vars.progressXPosition, vars.statusXPosition, vars.amountXPosition, vars.durationXPosition), "" ); @@ -119,7 +119,7 @@ library NFTSVG { function generateFloatingText( string memory sablierAddress, - string memory streamingModel, + string memory sablierModel, string memory assetAddress, string memory assetSymbol ) @@ -131,11 +131,11 @@ library NFTSVG { '', SVGElements.floatingText({ offset: "-100%", - text: string.concat(sablierAddress, unicode" • ", "Sablier V2 ", streamingModel) + text: string.concat(sablierAddress, unicode" • ", "Sablier V2 ", sablierModel) }), SVGElements.floatingText({ offset: "0%", - text: string.concat(sablierAddress, unicode" • ", "Sablier V2 ", streamingModel) + text: string.concat(sablierAddress, unicode" • ", "Sablier V2 ", sablierModel) }), SVGElements.floatingText({ offset: "-50%", text: string.concat(assetAddress, unicode" • ", assetSymbol) }), SVGElements.floatingText({ offset: "50%", text: string.concat(assetAddress, unicode" • ", assetSymbol) }), diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index f7082625f..8bbb378c5 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -66,14 +66,14 @@ library Lockup { DEPLETED } - /// @notice A common data structure to be stored in all child contracts of {SablierV2Lockup}. + /// @notice A common data structure to be stored in all {SablierV2Lockup} models. /// @dev The fields are arranged like this to save gas via tight variable packing. - /// @param sender The address streaming the assets, with the ability to cancel the stream. + /// @param sender The address distributing the assets, with the ability to cancel the stream. /// @param startTime The Unix timestamp indicating the stream's start. /// @param endTime The Unix timestamp indicating the stream's end. /// @param isCancelable Boolean indicating if the stream is cancelable. /// @param wasCanceled Boolean indicating if the stream was canceled. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param isDepleted Boolean indicating if the stream is depleted. /// @param isStream Boolean indicating if the struct entity exists. /// @param isTransferable Boolean indicating if the stream NFT is transferable. @@ -98,17 +98,17 @@ library Lockup { /// @notice Namespace for the structs used in {SablierV2LockupDynamic}. library LockupDynamic { - /// @notice Struct encapsulating the parameters for the {SablierV2LockupDynamic.createWithDurations} function. - /// @param sender The address streaming the assets, with the ability to cancel the stream. It doesn't have to be the - /// same as `msg.sender`. + /// @notice Struct encapsulating the parameters of the {SablierV2LockupDynamic.createWithDurations} function. + /// @param sender The address distributing the assets, with the ability to cancel the stream. It doesn't have to be + /// the same as `msg.sender`. /// @param recipient The address receiving the assets. - /// @param totalAmount The total amount of ERC-20 assets to be paid, including the stream deposit and any + /// @param totalAmount The total amount of ERC-20 assets to be distributed, including the stream deposit and any /// broker fee, both denoted in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Indicates if the stream is cancelable. /// @param transferable Indicates if the stream NFT is transferable. - /// @param segments Segments with durations used to compose the custom streaming curve. Timestamps are calculated by - /// starting from `block.timestamp` and adding each duration to the previous timestamp. + /// @param segments Segments with durations used to compose the dynamic distribution function. Timestamps are + /// calculated by starting from `block.timestamp` and adding each duration to the previous timestamp. /// @param broker Struct containing (i) the address of the broker assisting in creating the stream, and (ii) the /// percentage fee paid to the broker from `totalAmount`, denoted as a fixed-point number. Both can be set to zero. struct CreateWithDurations { @@ -122,18 +122,17 @@ library LockupDynamic { Broker broker; } - /// @notice Struct encapsulating the parameters for the {SablierV2LockupDynamic.createWithTimestamps} - /// function. - /// @param sender The address streaming the assets, with the ability to cancel the stream. It doesn't have to be the - /// same as `msg.sender`. + /// @notice Struct encapsulating the parameters of the {SablierV2LockupDynamic.createWithTimestamps} function. + /// @param sender The address distributing the assets, with the ability to cancel the stream. It doesn't have to be + /// the same as `msg.sender`. /// @param recipient The address receiving the assets. - /// @param totalAmount The total amount of ERC-20 assets to be paid, including the stream deposit and any + /// @param totalAmount The total amount of ERC-20 assets to be distributed, including the stream deposit and any /// broker fee, both denoted in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Indicates if the stream is cancelable. /// @param transferable Indicates if the stream NFT is transferable. /// @param startTime The Unix timestamp indicating the stream's start. - /// @param segments Segments used to compose the custom streaming curve. + /// @param segments Segments used to compose the dynamic distribution function. /// @param broker Struct containing (i) the address of the broker assisting in creating the stream, and (ii) the /// percentage fee paid to the broker from `totalAmount`, denoted as a fixed-point number. Both can be set to zero. struct CreateWithTimestamps { @@ -157,9 +156,9 @@ library LockupDynamic { } /// @notice Segment struct used in the Lockup Dynamic stream. - /// @param amount The amount of assets to be streamed in this segment, denoted in units of the asset's decimals. - /// @param exponent The exponent of this segment, denoted as a fixed-point number. - /// @param timestamp The Unix timestamp indicating this segment's end. + /// @param amount The amount of assets to be streamed in the segment, denoted in units of the asset's decimals. + /// @param exponent The exponent of the segment, denoted as a fixed-point number. + /// @param timestamp The Unix timestamp indicating the segment's end. struct Segment { // slot 0 uint128 amount; @@ -168,18 +167,17 @@ library LockupDynamic { } /// @notice Segment struct used at runtime in {SablierV2LockupDynamic.createWithDurations}. - /// @param amount The amount of assets to be streamed in this segment, denoted in units of the asset's decimals. - /// @param exponent The exponent of this segment, denoted as a fixed-point number. - /// @param duration The time difference in seconds between this segment and the previous one. + /// @param amount The amount of assets to be streamed in the segment, denoted in units of the asset's decimals. + /// @param exponent The exponent of the segment, denoted as a fixed-point number. + /// @param duration The time difference in seconds between the segment and the previous one. struct SegmentWithDuration { uint128 amount; UD2x18 exponent; uint40 duration; } - /// @notice Struct encapsulating all the data for a specific id, allowing anyone to retrieve all information within - /// one call to the contract. - /// @dev It contains the same data as the `Lockup.Stream` struct, plus the recipient and the segments. + /// @notice Struct encapsulating the full details of a stream. + /// @dev Extends `Lockup.Stream` by including the recipient and the segments. struct StreamLD { address sender; address recipient; @@ -198,13 +196,13 @@ library LockupDynamic { /// @notice Namespace for the structs used in {SablierV2LockupLinear}. library LockupLinear { - /// @notice Struct encapsulating the parameters for the {SablierV2LockupLinear.createWithDurations} function. - /// @param sender The address streaming the assets, with the ability to cancel the stream. It doesn't have to be the - /// same as `msg.sender`. + /// @notice Struct encapsulating the parameters of the {SablierV2LockupLinear.createWithDurations} function. + /// @param sender The address distributing the assets, with the ability to cancel the stream. It doesn't have to be + /// the same as `msg.sender`. /// @param recipient The address receiving the assets. - /// @param totalAmount The total amount of ERC-20 assets to be paid, including the stream deposit and any + /// @param totalAmount The total amount of ERC-20 assets to be distributed, including the stream deposit and any /// broker fee, both denoted in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Indicates if the stream is cancelable. /// @param transferable Indicates if the stream NFT is transferable. /// @param durations Struct containing (i) cliff period duration and (ii) total stream duration, both in seconds. @@ -221,13 +219,13 @@ library LockupLinear { Broker broker; } - /// @notice Struct encapsulating the parameters for the {SablierV2LockupLinear.createWithTimestamps} function. - /// @param sender The address streaming the assets, with the ability to cancel the stream. It doesn't have to be the - /// same as `msg.sender`. + /// @notice Struct encapsulating the parameters of the {SablierV2LockupLinear.createWithTimestamps} function. + /// @param sender The address distributing the assets, with the ability to cancel the stream. It doesn't have to be + /// the same as `msg.sender`. /// @param recipient The address receiving the assets. - /// @param totalAmount The total amount of ERC-20 assets to be paid, including the stream deposit and any + /// @param totalAmount The total amount of ERC-20 assets to be distributed, including the stream deposit and any /// broker fee, both denoted in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Indicates if the stream is cancelable. /// @param transferable Indicates if the stream NFT is transferable. /// @param range Struct containing (i) the stream's start time, (ii) cliff time, and (iii) end time, all as Unix @@ -263,9 +261,8 @@ library LockupLinear { uint40 end; } - /// @notice Struct encapsulating all the data for a specific id, allowing anyone to retrieve all information within - /// one call to the contract. - /// @dev It contains the same data as the `Lockup.Stream` struct, plus the recipient and the cliff value. + /// @notice Struct encapsulating the full details of a stream. + /// @dev Extends `Lockup.Stream` by including the recipient and the cliff time. struct StreamLL { address sender; address recipient; @@ -284,17 +281,17 @@ library LockupLinear { /// @notice Namespace for the structs used in {SablierV2LockupTranched}. library LockupTranched { - /// @notice Struct encapsulating the parameters for the {SablierV2LockupTranched.createWithDurations} function. - /// @param sender The address streaming the assets, with the ability to cancel the stream. It doesn't have to be the - /// same as `msg.sender`. + /// @notice Struct encapsulating the parameters of the {SablierV2LockupTranched.createWithDurations} function. + /// @param sender The address distributing the assets, with the ability to cancel the stream. It doesn't have to be + /// the same as `msg.sender`. /// @param recipient The address receiving the assets. - /// @param totalAmount The total amount of ERC-20 assets to be paid, including the stream deposit and any + /// @param totalAmount The total amount of ERC-20 assets to be distributed, including the stream deposit and any /// broker fee, both denoted in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Indicates if the stream is cancelable. /// @param transferable Indicates if the stream NFT is transferable. - /// @param tranches Tranches with durations used to compose the custom streaming curve. Timestamps are calculated by - /// starting from `block.timestamp` and adding each duration to the previous timestamp. + /// @param tranches Tranches with durations used to compose the tranched distribution function. Timestamps are + /// calculated by starting from `block.timestamp` and adding each duration to the previous timestamp. /// @param broker Struct containing (i) the address of the broker assisting in creating the stream, and (ii) the /// percentage fee paid to the broker from `totalAmount`, denoted as a fixed-point number. Both can be set to zero. struct CreateWithDurations { @@ -308,18 +305,17 @@ library LockupTranched { Broker broker; } - /// @notice Struct encapsulating the parameters for the {SablierV2LockupTranched.createWithTimestamps} - /// function. - /// @param sender The address streaming the assets, with the ability to cancel the stream. It doesn't have to be the - /// same as `msg.sender`. + /// @notice Struct encapsulating the parameters of the {SablierV2LockupTranched.createWithTimestamps} function. + /// @param sender The address distributing the assets, with the ability to cancel the stream. It doesn't have to be + /// the same as `msg.sender`. /// @param recipient The address receiving the assets. - /// @param totalAmount The total amount of ERC-20 assets to be paid, including the stream deposit and any + /// @param totalAmount The total amount of ERC-20 assets to be distributed, including the stream deposit and any /// broker fee, both denoted in units of the asset's decimals. - /// @param asset The contract address of the ERC-20 asset used for streaming. + /// @param asset The contract address of the ERC-20 asset to be distributed. /// @param cancelable Indicates if the stream is cancelable. /// @param transferable Indicates if the stream NFT is transferable. /// @param startTime The Unix timestamp indicating the stream's start. - /// @param tranches Tranches used to compose the custom streaming curve. + /// @param tranches Tranches used to compose the tranched distribution function. /// @param broker Struct containing (i) the address of the broker assisting in creating the stream, and (ii) the /// percentage fee paid to the broker from `totalAmount`, denoted as a fixed-point number. Both can be set to zero. struct CreateWithTimestamps { @@ -342,9 +338,8 @@ library LockupTranched { uint40 end; } - /// @notice Struct encapsulating all the data for a specific id, allowing anyone to retrieve all information within - /// one call to the contract. - /// @dev It contains the same data as the `Lockup.Stream` struct, plus the recipient and the tranches. + /// @notice Struct encapsulating the full details of a stream. + /// @dev Extends `Lockup.Stream` by including the recipient and the tranches. struct StreamLT { address sender; address recipient; @@ -361,8 +356,8 @@ library LockupTranched { } /// @notice Tranche struct used in the Lockup Tranched stream. - /// @param amount The amount of assets to be unlocked in this tranche, denoted in units of the asset's decimals. - /// @param timestamp The Unix timestamp indicating this tranche's end. + /// @param amount The amount of assets to be unlocked in the tranche, denoted in units of the asset's decimals. + /// @param timestamp The Unix timestamp indicating the tranche's end. struct Tranche { // slot 0 uint128 amount; @@ -370,8 +365,8 @@ library LockupTranched { } /// @notice Tranche struct used at runtime in {SablierV2LockupTranched.createWithDurations}. - /// @param amount The amount of assets to be unlocked in this tranche, denoted in units of the asset's decimals. - /// @param duration The time difference in seconds between this tranche and the previous one. + /// @param amount The amount of assets to be unlocked in the tranche, denoted in units of the asset's decimals. + /// @param duration The time difference in seconds between the tranche and the previous one. struct TrancheWithDuration { uint128 amount; uint40 duration; diff --git a/test/Base.t.sol b/test/Base.t.sol index 7957d2f16..edc907603 100644 --- a/test/Base.t.sol +++ b/test/Base.t.sol @@ -108,7 +108,7 @@ abstract contract Base_Test is Assertions, Calculations, Constants, DeployOptimi usdt.approve({ spender: address(lockupTranched), value: MAX_UINT256 }); } - /// @dev Generates a user, labels its address, funds it with test assets and approve the protocol contracts. + /// @dev Generates a user, labels its address, funds it with test assets, and approves the protocol contracts. function createUser(string memory name) internal returns (address payable) { address payable user = payable(makeAddr(name)); vm.deal({ account: user, newBalance: 100 ether }); @@ -126,12 +126,12 @@ abstract contract Base_Test is Assertions, Calculations, Constants, DeployOptimi function deployCoreConditionally() internal { if (!isTestOptimizedProfile()) { nftDescriptor = new SablierV2NFTDescriptor(); - lockupDynamic = new SablierV2LockupDynamic(users.admin, nftDescriptor, defaults.MAX_COUNT()); + lockupDynamic = new SablierV2LockupDynamic(users.admin, nftDescriptor, defaults.MAX_SEGMENT_COUNT()); lockupLinear = new SablierV2LockupLinear(users.admin, nftDescriptor); - lockupTranched = new SablierV2LockupTranched(users.admin, nftDescriptor, defaults.MAX_COUNT()); + lockupTranched = new SablierV2LockupTranched(users.admin, nftDescriptor, defaults.MAX_TRANCHE_COUNT()); } else { (lockupDynamic, lockupLinear, lockupTranched, nftDescriptor) = - deployOptimizedCore(users.admin, defaults.MAX_COUNT()); + deployOptimizedCore(users.admin, defaults.MAX_SEGMENT_COUNT(), defaults.MAX_TRANCHE_COUNT()); } vm.label({ account: address(lockupDynamic), newLabel: "LockupDynamic" }); diff --git a/test/fork/LockupDynamic.t.sol b/test/fork/LockupDynamic.t.sol index 2265eaf07..65ee2c540 100644 --- a/test/fork/LockupDynamic.t.sol +++ b/test/fork/LockupDynamic.t.sol @@ -86,7 +86,7 @@ abstract contract LockupDynamic_Fork_Test is Fork_Test { /// /// - It should perform all expected ERC-20 transfers. /// - It should create the stream. - /// - It should bump the next stream id. + /// - It should bump the next stream ID. /// - It should mint the NFT. /// - It should emit a {CreateLockupDynamicStream} event. /// - It may make a withdrawal. @@ -173,7 +173,7 @@ abstract contract LockupDynamic_Fork_Test is Fork_Test { }) ); - // Check if the stream is settled. It is possible for a lockupDynamic stream to settle at the time of creation + // Check if the stream is settled. It is possible for a Lockup Dynamic stream to settle at the time of creation // because some segment amounts can be zero. vars.isSettled = lockupDynamic.refundableAmountOf(vars.streamId) == 0; vars.isCancelable = vars.isSettled ? false : true; @@ -185,8 +185,8 @@ abstract contract LockupDynamic_Fork_Test is Fork_Test { assertEq(actualStream.endTime, vars.range.end, "endTime"); assertEq(actualStream.isCancelable, vars.isCancelable, "isCancelable"); assertEq(actualStream.isDepleted, false, "isDepleted"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.segments, params.segments, "segments"); assertEq(actualStream.sender, params.sender, "sender"); @@ -204,7 +204,7 @@ abstract contract LockupDynamic_Fork_Test is Fork_Test { } assertEq(vars.actualStatus, vars.expectedStatus, "post-create stream status"); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupDynamic.nextStreamId(); vars.expectedNextStreamId = vars.streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "post-create nextStreamId"); @@ -226,7 +226,7 @@ abstract contract LockupDynamic_Fork_Test is Fork_Test { assertEq( vars.actualLockupDynamicBalance, vars.expectedLockupDynamicBalance, - "post-create lockupDynamic contract balance" + "post-create LockupDynamic contract balance" ); // Assert that the holder's balance has been updated. diff --git a/test/fork/LockupLinear.t.sol b/test/fork/LockupLinear.t.sol index eb5a2e4a4..3bdfb78a8 100644 --- a/test/fork/LockupLinear.t.sol +++ b/test/fork/LockupLinear.t.sol @@ -51,11 +51,14 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { uint256 actualRecipientBalance; Lockup.Status actualStatus; uint256[] balances; + uint40 blockTimestamp; + uint40 endTimeLowerBound; uint256 expectedLockupLinearBalance; uint256 expectedHolderBalance; address expectedNFTOwner; uint256 expectedRecipientBalance; Lockup.Status expectedStatus; + bool hasCliff; uint256 initialLockupLinearBalance; uint256 initialRecipientBalance; bool isDepleted; @@ -84,7 +87,7 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { /// /// - It should perform all expected ERC-20 transfers. /// - It should create the stream. - /// - It should bump the next stream id. + /// - It should bump the next stream ID. /// - It should mint the NFT. /// - It should emit a {MetadataUpdate} event /// - It should emit a {CreateLockupLinearStream} event. @@ -98,31 +101,34 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { /// /// - Multiple values for the sender, recipient, and broker /// - Multiple values for the total amount - /// - Multiple values for the cliff time and the end time - /// - Multiple values for the broker fee, including zero /// - Multiple values for the withdraw amount, including zero /// - Start time in the past /// - Start time in the present /// - Start time in the future - /// - Start time lower than and equal to cliff time + /// - Multiple values for the cliff time and the end time + /// - Cliff time zero and not zero + /// - Multiple values for the broker fee, including zero /// - The whole gamut of stream statuses function testForkFuzz_LockupLinear_CreateWithdrawCancel(Params memory params) external { checkUsers(params.sender, params.recipient, params.broker.account, address(lockupLinear)); // Bound the parameters. - uint40 currentTime = getBlockTimestamp(); + Vars memory vars; + vars.blockTimestamp = getBlockTimestamp(); params.broker.fee = _bound(params.broker.fee, 0, MAX_BROKER_FEE); - params.range.start = boundUint40(params.range.start, currentTime - 1000 seconds, currentTime + 10_000 seconds); - params.range.cliff = boundUint40(params.range.cliff, params.range.start + 1, params.range.start + 52 weeks); + params.range.start = + boundUint40(params.range.start, vars.blockTimestamp - 1000 seconds, vars.blockTimestamp + 10_000 seconds); params.totalAmount = boundUint128(params.totalAmount, 1, uint128(initialHolderBalance)); - // Bound the end time so that it is always greater than both the current time and the cliff time (this is - // a requirement of the protocol). - params.range.end = boundUint40( - params.range.end, - (params.range.cliff <= currentTime ? currentTime : params.range.cliff) + 1, - MAX_UNIX_TIMESTAMP - ); + // The cliff time must be either zero or greater than the start time. + vars.hasCliff = params.range.cliff > 0; + if (vars.hasCliff) { + params.range.cliff = + boundUint40(params.range.cliff, params.range.start + 1 seconds, params.range.start + 52 weeks); + } + // Bound the end time so that it is always greater than the block timestamp, the start time, and the cliff time. + vars.endTimeLowerBound = maxOfThree(params.range.start, params.range.cliff, vars.blockTimestamp); + params.range.end = boundUint40(params.range.end, vars.endTimeLowerBound + 1 seconds, MAX_UNIX_TIMESTAMP); // Make the holder the caller. resetPrank(HOLDER); @@ -131,8 +137,6 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { CREATE //////////////////////////////////////////////////////////////////////////*/ - Vars memory vars; - // Load the pre-create asset balances. vars.balances = getTokenBalances(address(ASSET), Solarray.addresses(address(lockupLinear), params.broker.account)); @@ -184,8 +188,8 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { assertEq(actualStream.endTime, params.range.end, "endTime"); assertEq(actualStream.isCancelable, true, "isCancelable"); assertEq(actualStream.isDepleted, false, "isDepleted"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.sender, params.sender, "sender"); assertEq(actualStream.startTime, params.range.start, "startTime"); @@ -193,10 +197,10 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { // Assert that the stream's status is correct. vars.actualStatus = lockupLinear.statusOf(vars.streamId); - vars.expectedStatus = params.range.start > currentTime ? Lockup.Status.PENDING : Lockup.Status.STREAMING; + vars.expectedStatus = params.range.start > vars.blockTimestamp ? Lockup.Status.PENDING : Lockup.Status.STREAMING; assertEq(vars.actualStatus, vars.expectedStatus, "post-create stream status"); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupLinear.nextStreamId(); vars.expectedNextStreamId = vars.streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "post-create nextStreamId"); @@ -230,7 +234,11 @@ abstract contract LockupLinear_Fork_Test is Fork_Test { //////////////////////////////////////////////////////////////////////////*/ // Simulate the passage of time. - params.warpTimestamp = boundUint40(params.warpTimestamp, params.range.cliff, params.range.end + 100 seconds); + params.warpTimestamp = boundUint40( + params.warpTimestamp, + vars.hasCliff ? params.range.cliff : params.range.start + 1 seconds, + params.range.end + 100 seconds + ); vm.warp({ newTimestamp: params.warpTimestamp }); // Bound the withdraw amount. diff --git a/test/fork/LockupTranched.t.sol b/test/fork/LockupTranched.t.sol index 9bf85d3ff..6ae743529 100644 --- a/test/fork/LockupTranched.t.sol +++ b/test/fork/LockupTranched.t.sol @@ -86,7 +86,7 @@ abstract contract LockupTranched_Fork_Test is Fork_Test { /// /// - It should perform all expected ERC-20 transfers. /// - It should create the stream. - /// - It should bump the next stream id. + /// - It should bump the next stream ID. /// - It should mint the NFT. /// - It should emit a {CreateLockupTranchedStream} event. /// - It may make a withdrawal. @@ -175,7 +175,7 @@ abstract contract LockupTranched_Fork_Test is Fork_Test { }) ); - // Check if the stream is settled. It is possible for a lockupTranched stream to settle at the time of creation + // Check if the stream is settled. It is possible for a Lockup Tranched stream to settle at the time of creation // because some tranche amounts can be zero. vars.isSettled = lockupTranched.refundableAmountOf(vars.streamId) == 0; vars.isCancelable = vars.isSettled ? false : true; @@ -187,8 +187,8 @@ abstract contract LockupTranched_Fork_Test is Fork_Test { assertEq(actualStream.endTime, vars.range.end, "endTime"); assertEq(actualStream.isCancelable, vars.isCancelable, "isCancelable"); assertEq(actualStream.isDepleted, false, "isDepleted"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.tranches, params.tranches, "tranches"); assertEq(actualStream.sender, params.sender, "sender"); @@ -206,7 +206,7 @@ abstract contract LockupTranched_Fork_Test is Fork_Test { } assertEq(vars.actualStatus, vars.expectedStatus, "post-create stream status"); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupTranched.nextStreamId(); vars.expectedNextStreamId = vars.streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "post-create nextStreamId"); @@ -228,7 +228,7 @@ abstract contract LockupTranched_Fork_Test is Fork_Test { assertEq( vars.actualLockupTranchedBalance, vars.expectedLockupTranchedBalance, - "post-create lockupTranched contract balance" + "post-create LockupTranched contract balance" ); // Assert that the holder's balance has been updated. diff --git a/test/integration/concrete/lockup-dynamic/constructor.t.sol b/test/integration/concrete/lockup-dynamic/constructor.t.sol index 41c339147..e08fa8763 100644 --- a/test/integration/concrete/lockup-dynamic/constructor.t.sol +++ b/test/integration/concrete/lockup-dynamic/constructor.t.sol @@ -16,7 +16,7 @@ contract Constructor_LockupDynamic_Integration_Concrete_Test is LockupDynamic_In SablierV2LockupDynamic constructedLockupDynamic = new SablierV2LockupDynamic({ initialAdmin: users.admin, initialNFTDescriptor: nftDescriptor, - maxSegmentCount: defaults.MAX_COUNT() + maxSegmentCount: defaults.MAX_SEGMENT_COUNT() }); // {SablierV2Lockup.constant} @@ -39,7 +39,7 @@ contract Constructor_LockupDynamic_Integration_Concrete_Test is LockupDynamic_In // {SablierV2LockupDynamic.constructor} uint256 actualMaxSegmentCount = constructedLockupDynamic.MAX_SEGMENT_COUNT(); - uint256 expectedMaxSegmentCount = defaults.MAX_COUNT(); - assertEq(actualMaxSegmentCount, expectedMaxSegmentCount, "MAX_COUNT"); + uint256 expectedMaxSegmentCount = defaults.MAX_SEGMENT_COUNT(); + assertEq(actualMaxSegmentCount, expectedMaxSegmentCount, "MAX_SEGMENT_COUNT"); } } diff --git a/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.t.sol b/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.t.sol index 12dc4758b..8d7bbce4f 100644 --- a/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.t.sol +++ b/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.t.sol @@ -7,7 +7,7 @@ import { ISablierV2LockupDynamic } from "src/interfaces/ISablierV2LockupDynamic. import { Errors } from "src/libraries/Errors.sol"; import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; -import { CreateWithDurations_Integration_Shared_Test } from "../../../shared/lockup-dynamic/createWithDurations.t.sol"; +import { CreateWithDurations_Integration_Shared_Test } from "../../../shared/lockup/createWithDurations.t.sol"; import { LockupDynamic_Integration_Concrete_Test } from "../LockupDynamic.t.sol"; contract CreateWithDurations_LockupDynamic_Integration_Concrete_Test is @@ -126,9 +126,9 @@ contract CreateWithDurations_LockupDynamic_Integration_Concrete_Test is address funder = users.sender; // Declare the range. - uint40 currentTime = getBlockTimestamp(); + uint40 blockTimestamp = getBlockTimestamp(); LockupDynamic.Range memory range = - LockupDynamic.Range({ start: currentTime, end: currentTime + defaults.TOTAL_DURATION() }); + LockupDynamic.Range({ start: blockTimestamp, end: blockTimestamp + defaults.TOTAL_DURATION() }); // Adjust the segments. LockupDynamic.SegmentWithDuration[] memory segmentsWithDurations = defaults.segmentsWithDurations(); @@ -176,7 +176,7 @@ contract CreateWithDurations_LockupDynamic_Integration_Concrete_Test is Lockup.Status expectedStatus = Lockup.Status.STREAMING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupDynamic.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.tree b/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.tree index 48cdb0c85..9c42b9b8a 100644 --- a/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.tree +++ b/test/integration/concrete/lockup-dynamic/create-with-durations/createWithDurations.tree @@ -15,7 +15,7 @@ createWithDurations.t.sol │ └── it should revert └── when the segment timestamp calculations do not overflow uint256 ├── it should create the stream - ├── it should bump the next stream id + ├── it should bump the next stream ID ├── it should mint the NFT ├── it should emit a {MetadataUpdate} event ├── it should perform the ERC-20 transfers diff --git a/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.t.sol b/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.t.sol index 043e668e3..b8b2e1843 100644 --- a/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.t.sol +++ b/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.t.sol @@ -11,7 +11,7 @@ import { ISablierV2LockupDynamic } from "src/interfaces/ISablierV2LockupDynamic. import { Errors } from "src/libraries/Errors.sol"; import { Broker, Lockup, LockupDynamic } from "src/types/DataTypes.sol"; -import { CreateWithTimestamps_Integration_Shared_Test } from "../../../shared/lockup-dynamic/createWithTimestamps.t.sol"; +import { CreateWithTimestamps_Integration_Shared_Test } from "../../../shared/lockup/createWithTimestamps.t.sol"; import { LockupDynamic_Integration_Concrete_Test } from "../LockupDynamic.t.sol"; contract CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test is @@ -78,7 +78,7 @@ contract CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test is whenStartTimeNotZero whenSegmentCountNotZero { - uint256 segmentCount = defaults.MAX_COUNT() + 1; + uint256 segmentCount = defaults.MAX_SEGMENT_COUNT() + 1; LockupDynamic.Segment[] memory segments = new LockupDynamic.Segment[](segmentCount); vm.expectRevert( abi.encodeWithSelector(Errors.SablierV2LockupDynamic_SegmentCountTooHigh.selector, segmentCount) @@ -379,7 +379,7 @@ contract CreateWithTimestamps_LockupDynamic_Integration_Concrete_Test is Lockup.Status expectedStatus = Lockup.Status.PENDING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupDynamic.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.tree b/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.tree index 020277763..8105493e3 100644 --- a/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.tree +++ b/test/integration/concrete/lockup-dynamic/create-with-timestamps/createWithTimestamps.tree @@ -42,14 +42,14 @@ createWithTimestamps.t.sol └── when the asset is a contract ├── when the asset misses the ERC-20 return value │ ├── it should create the stream - │ ├── it should bump the next stream id + │ ├── it should bump the next stream ID │ ├── it should mint the NFT │ ├── it should emit a {MetadataUpdate} event │ ├── it should perform the ERC-20 transfers │ └── it should emit a {CreateLockupDynamicStream} event └── when the asset does not miss the ERC-20 return value ├── it should create the stream - ├── it should bump the next stream id + ├── it should bump the next stream ID ├── it should mint the NFT ├── it should emit a {MetadataUpdate} event ├── it should perform the ERC-20 transfers diff --git a/test/integration/concrete/lockup-dynamic/get-range/getRange.tree b/test/integration/concrete/lockup-dynamic/get-range/getRange.tree index 88dcc9707..61e44d77a 100644 --- a/test/integration/concrete/lockup-dynamic/get-range/getRange.tree +++ b/test/integration/concrete/lockup-dynamic/get-range/getRange.tree @@ -1,5 +1,5 @@ getRange.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct range diff --git a/test/integration/concrete/lockup-dynamic/get-segments/getSegments.tree b/test/integration/concrete/lockup-dynamic/get-segments/getSegments.tree index b7032eba6..6ac298106 100644 --- a/test/integration/concrete/lockup-dynamic/get-segments/getSegments.tree +++ b/test/integration/concrete/lockup-dynamic/get-segments/getSegments.tree @@ -1,5 +1,5 @@ getSegments.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct segments diff --git a/test/integration/concrete/lockup-dynamic/get-stream/getStream.tree b/test/integration/concrete/lockup-dynamic/get-stream/getStream.tree index c3278db89..bde21f7b4 100644 --- a/test/integration/concrete/lockup-dynamic/get-stream/getStream.tree +++ b/test/integration/concrete/lockup-dynamic/get-stream/getStream.tree @@ -1,7 +1,7 @@ getStream.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is settled │ └── it should adjust the `isCancelable` flag and return the stream └── given the stream is not settled diff --git a/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol b/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol index d4b4993b8..4c4e4ad9a 100644 --- a/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol +++ b/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol @@ -10,7 +10,7 @@ import { Base64 } from "solady/src/utils/Base64.sol"; import { LockupDynamic_Integration_Concrete_Test } from "../LockupDynamic.t.sol"; /// @dev Requirements for these tests to work: -/// - The stream id must be 1 +/// - The stream ID must be 1 /// - The stream's sender must be `0x6332e7b1deb1f1a0b77b2bb18b144330c7291bca`, i.e. `makeAddr("Sender")` /// - The stream asset must have the DAI symbol /// - The contract deployer, i.e. the `sender` config option in `foundry.toml`, must have the default value diff --git a/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.t.sol b/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.t.sol index 46263b07e..c6d16323d 100644 --- a/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.t.sol +++ b/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.t.sol @@ -5,7 +5,7 @@ import { ISablierV2LockupLinear } from "src/interfaces/ISablierV2LockupLinear.so import { Errors } from "src/libraries/Errors.sol"; import { Lockup, LockupLinear } from "src/types/DataTypes.sol"; -import { CreateWithDurations_Integration_Shared_Test } from "../../../shared/lockup-linear/createWithDurations.t.sol"; +import { CreateWithDurations_Integration_Shared_Test } from "../../../shared/lockup/createWithDurations.t.sol"; import { LockupLinear_Integration_Concrete_Test } from "../LockupLinear.t.sol"; contract CreateWithDurations_LockupLinear_Integration_Concrete_Test is @@ -28,6 +28,28 @@ contract CreateWithDurations_LockupLinear_Integration_Concrete_Test is expectRevertDueToDelegateCall(success, returnData); } + function test_RevertWhen_CliffDurationCalculationOverflows() external whenNotDelegateCalled { + uint40 startTime = getBlockTimestamp(); + uint40 cliffDuration = MAX_UINT40 - startTime + 2 seconds; + uint40 totalDuration = defaults.TOTAL_DURATION(); + + // Calculate the end time. Needs to be "unchecked" to avoid an overflow. + uint40 cliffTime; + unchecked { + cliffTime = startTime + cliffDuration; + } + + // Expect the relevant error to be thrown. + vm.expectRevert( + abi.encodeWithSelector( + Errors.SablierV2LockupLinear_StartTimeNotLessThanCliffTime.selector, startTime, cliffTime + ) + ); + + // Create the stream. + createDefaultStreamWithDurations(LockupLinear.Durations({ cliff: cliffDuration, total: totalDuration })); + } + function test_RevertWhen_TotalDurationCalculationOverflows() external whenNotDelegateCalled @@ -66,11 +88,11 @@ contract CreateWithDurations_LockupLinear_Integration_Concrete_Test is address funder = users.sender; // Declare the range. - uint40 currentTime = getBlockTimestamp(); + uint40 blockTimestamp = getBlockTimestamp(); LockupLinear.Range memory range = LockupLinear.Range({ - start: currentTime, - cliff: currentTime + defaults.CLIFF_DURATION(), - end: currentTime + defaults.TOTAL_DURATION() + start: blockTimestamp, + cliff: blockTimestamp + defaults.CLIFF_DURATION(), + end: blockTimestamp + defaults.TOTAL_DURATION() }); // Expect the assets to be transferred from the funder to {SablierV2LockupLinear}. @@ -112,7 +134,7 @@ contract CreateWithDurations_LockupLinear_Integration_Concrete_Test is Lockup.Status expectedStatus = Lockup.Status.STREAMING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupLinear.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.tree b/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.tree index 898296b77..e769f8a06 100644 --- a/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.tree +++ b/test/integration/concrete/lockup-linear/create-with-durations/createWithDurations.tree @@ -2,11 +2,14 @@ createWithDurations.t.sol ├── when delegate called │ └── it should revert └── when not delegate called + ├── when the cliff duration calculation overflows uint256 + │ └── it should revert due to the start time being greater than the cliff time + └── when the cliff duration calculation does not overflow uint256 ├── when the total duration calculation overflows uint256 - │ └── it should revert + │ └── it should revert └── when the total duration calculation does not overflow uint256 - ├── it should create the stream - ├── it should bump the next stream id - ├── it should mint the NFT - ├── it should perform the ERC-20 transfers - └── it should emit a {CreateLockupLinearStream} event + ├── it should create the stream + ├── it should bump the next stream ID + ├── it should mint the NFT + ├── it should perform the ERC-20 transfers + └── it should emit a {CreateLockupLinearStream} event diff --git a/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.t.sol b/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.t.sol index 16e46c75f..eeb709aeb 100644 --- a/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.t.sol +++ b/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.t.sol @@ -10,7 +10,7 @@ import { ISablierV2LockupLinear } from "src/interfaces/ISablierV2LockupLinear.so import { Errors } from "src/libraries/Errors.sol"; import { Broker, Lockup, LockupLinear } from "src/types/DataTypes.sol"; -import { CreateWithTimestamps_Integration_Shared_Test } from "../../../shared/lockup-linear/createWithTimestamps.t.sol"; +import { CreateWithTimestamps_Integration_Shared_Test } from "../../../shared/lockup/createWithTimestamps.t.sol"; import { LockupLinear_Integration_Concrete_Test } from "../LockupLinear.t.sol"; contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is @@ -59,11 +59,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is createDefaultStreamWithRange(LockupLinear.Range({ start: 0, cliff: cliffTime, end: endTime })); } - modifier whenCliffTimeZero() { - _; - } - - function test_RevertWhen_StartTimeGreaterThanEndTime() + function test_RevertWhen_StartTimeNotLessThanEndTime() external whenNotDelegateCalled whenRecipientNonZeroAddress @@ -82,7 +78,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is createDefaultStreamWithRange(LockupLinear.Range({ start: startTime, cliff: 0, end: endTime })); } - function test_CreateWithTimestamps_CliffTimeZero() + function test_CreateWithTimestamps_StartTimeLessThanEndTime() external whenNotDelegateCalled whenRecipientNonZeroAddress @@ -100,7 +96,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is expectedStream.cliffTime = 0; assertEq(actualStream, expectedStream); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupLinear.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); @@ -111,10 +107,6 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is assertEq(actualNFTOwner, expectedNFTOwner, "NFT owner"); } - modifier whenCliffTimeGreaterThanZero() { - _; - } - function test_RevertWhen_StartTimeGreaterThanCliffTime() external whenNotDelegateCalled @@ -122,6 +114,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero + whenStartTimeLessThanEndTime { uint40 startTime = defaults.CLIFF_TIME(); uint40 cliffTime = defaults.START_TIME(); @@ -141,7 +134,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero - whenStartTimeNotGreaterThanCliffTime + whenStartTimeLessThanEndTime { uint40 startTime = defaults.START_TIME(); uint40 cliffTime = defaults.END_TIME(); @@ -161,7 +154,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero - whenStartTimeNotGreaterThanCliffTime + whenStartTimeLessThanEndTime whenCliffTimeLessThanEndTime whenEndTimeInTheFuture { @@ -178,7 +171,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero - whenStartTimeNotGreaterThanCliffTime + whenStartTimeLessThanEndTime whenCliffTimeLessThanEndTime whenEndTimeInTheFuture { @@ -196,7 +189,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero - whenStartTimeNotGreaterThanCliffTime + whenStartTimeLessThanEndTime whenCliffTimeLessThanEndTime whenEndTimeInTheFuture whenBrokerFeeNotTooHigh @@ -213,7 +206,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero - whenStartTimeNotGreaterThanCliffTime + whenStartTimeLessThanEndTime whenCliffTimeLessThanEndTime whenEndTimeInTheFuture whenBrokerFeeNotTooHigh @@ -228,7 +221,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is whenDepositAmountNotZero whenStartTimeNotZero whenCliffTimeGreaterThanZero - whenStartTimeNotGreaterThanCliffTime + whenStartTimeLessThanEndTime whenCliffTimeLessThanEndTime whenEndTimeInTheFuture whenBrokerFeeNotTooHigh @@ -290,7 +283,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Concrete_Test is Lockup.Status expectedStatus = Lockup.Status.PENDING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupLinear.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.tree b/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.tree index ea808de62..6729ea211 100644 --- a/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.tree +++ b/test/integration/concrete/lockup-linear/create-with-timestamps/createWithTimestamps.tree @@ -12,15 +12,15 @@ createWithTimestamps.t.sol │ └── it should revert └── when the start time is not zero ├── when the cliff time is zero - │ ├── when the start time is greater than the end time + │ ├── when the start time is not less than the end time │ │ └── it should revert - │ └── when the start time is not greater than the end time + │ └── when the start time is less than the end time │ └── it should create the stream └── when the cliff time is greater than zero ├── when the start time is not less than the cliff time │ └── it should revert - └── when the start time is not greater than the cliff time - ├── when the cliff time is less than the end time + └── when the start time is less than the cliff time + ├── when the cliff time is not less than the end time │ └── it should revert └── when the cliff time is less than the end time ├── when the end time is not in the future @@ -34,16 +34,15 @@ createWithTimestamps.t.sol └── when the asset is a contract ├── when the asset misses the ERC-20 return value │ ├── it should create the stream - │ ├── it should bump the next stream id + │ ├── it should bump the next stream ID │ ├── it should mint the NFT │ ├── it should emit a {MetadataUpdate} event │ ├── it should perform the ERC-20 transfers │ └── it should emit a {CreateLockupLinearStream} event └── when the asset does not miss the ERC-20 return value ├── it should create the stream - ├── it should bump the next stream id + ├── it should bump the next stream ID ├── it should mint the NFT ├── it should emit a {MetadataUpdate} event ├── it should perform the ERC-20 transfers └── it should emit a {CreateLockupLinearStream} event - diff --git a/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree b/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree index afa854032..d588c8587 100644 --- a/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree +++ b/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree @@ -1,5 +1,5 @@ getCliffTime.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct cliff time diff --git a/test/integration/concrete/lockup-linear/get-range/getRange.tree b/test/integration/concrete/lockup-linear/get-range/getRange.tree index 88dcc9707..61e44d77a 100644 --- a/test/integration/concrete/lockup-linear/get-range/getRange.tree +++ b/test/integration/concrete/lockup-linear/get-range/getRange.tree @@ -1,5 +1,5 @@ getRange.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct range diff --git a/test/integration/concrete/lockup-linear/get-stream/getStream.tree b/test/integration/concrete/lockup-linear/get-stream/getStream.tree index c3278db89..bde21f7b4 100644 --- a/test/integration/concrete/lockup-linear/get-stream/getStream.tree +++ b/test/integration/concrete/lockup-linear/get-stream/getStream.tree @@ -1,7 +1,7 @@ getStream.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is settled │ └── it should adjust the `isCancelable` flag and return the stream └── given the stream is not settled diff --git a/test/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol b/test/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol index 30aa29f37..2ce92568e 100644 --- a/test/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol +++ b/test/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol @@ -10,7 +10,7 @@ import { Base64 } from "solady/src/utils/Base64.sol"; import { LockupLinear_Integration_Concrete_Test } from "../LockupLinear.t.sol"; /// @dev Requirements for these tests to work: -/// - The stream id must be 1 +/// - The stream ID must be 1 /// - The stream's sender must be `0x6332e7b1deb1f1a0b77b2bb18b144330c7291bca`, i.e. `makeAddr("Sender")` /// - The stream asset must have the DAI symbol /// - The contract deployer, i.e. the `sender` config option in `foundry.toml`, must have the default value diff --git a/test/integration/concrete/lockup-tranched/constructor.t.sol b/test/integration/concrete/lockup-tranched/constructor.t.sol index bb7d729e0..ce5481180 100644 --- a/test/integration/concrete/lockup-tranched/constructor.t.sol +++ b/test/integration/concrete/lockup-tranched/constructor.t.sol @@ -16,7 +16,7 @@ contract Constructor_LockupTranched_Integration_Concrete_Test is LockupTranched_ SablierV2LockupTranched constructedLockupTranched = new SablierV2LockupTranched({ initialAdmin: users.admin, initialNFTDescriptor: nftDescriptor, - maxTrancheCount: defaults.MAX_COUNT() + maxTrancheCount: defaults.MAX_TRANCHE_COUNT() }); // {SablierV2Lockup.constant} @@ -39,7 +39,7 @@ contract Constructor_LockupTranched_Integration_Concrete_Test is LockupTranched_ // {SablierV2lockupTranched.constructor} uint256 actualMaxTrancheCount = constructedLockupTranched.MAX_TRANCHE_COUNT(); - uint256 expectedMaxTrancheCount = defaults.MAX_COUNT(); - assertEq(actualMaxTrancheCount, expectedMaxTrancheCount, "MAX_COUNT"); + uint256 expectedMaxTrancheCount = defaults.MAX_TRANCHE_COUNT(); + assertEq(actualMaxTrancheCount, expectedMaxTrancheCount, "MAX_TRANCHE_COUNT"); } } diff --git a/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.t.sol b/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.t.sol index 000c2b315..24097a17f 100644 --- a/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.t.sol +++ b/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.t.sol @@ -5,7 +5,7 @@ import { ISablierV2LockupTranched } from "src/interfaces/ISablierV2LockupTranche import { Errors } from "src/libraries/Errors.sol"; import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; -import { CreateWithDurations_Integration_Shared_Test } from "../../../shared/lockup-tranched/createWithDurations.t.sol"; +import { CreateWithDurations_Integration_Shared_Test } from "../../../shared/lockup/createWithDurations.t.sol"; import { LockupTranched_Integration_Concrete_Test } from "../LockupTranched.t.sol"; contract CreateWithDurations_LockupTranched_Integration_Concrete_Test is @@ -120,9 +120,9 @@ contract CreateWithDurations_LockupTranched_Integration_Concrete_Test is address funder = users.sender; // Declare the range. - uint40 currentTime = getBlockTimestamp(); + uint40 blockTimestamp = getBlockTimestamp(); LockupTranched.Range memory range = - LockupTranched.Range({ start: currentTime, end: currentTime + defaults.TOTAL_DURATION() }); + LockupTranched.Range({ start: blockTimestamp, end: blockTimestamp + defaults.TOTAL_DURATION() }); LockupTranched.TrancheWithDuration[] memory tranchesWithDurations = defaults.tranchesWithDurations(); LockupTranched.Tranche[] memory tranches = defaults.tranches(); @@ -170,7 +170,7 @@ contract CreateWithDurations_LockupTranched_Integration_Concrete_Test is Lockup.Status expectedStatus = Lockup.Status.STREAMING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupTranched.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.tree b/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.tree index b739c2df6..e4b379b65 100644 --- a/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.tree +++ b/test/integration/concrete/lockup-tranched/create-with-durations/createWithDurations.tree @@ -15,7 +15,7 @@ createWithDurations.t.sol │ └── it should revert └── when the tranche timestamp calculations do not overflow uint256 ├── it should create the stream - ├── it should bump the next stream id + ├── it should bump the next stream ID ├── it should mint the NFT ├── it should emit a {MetadataUpdate} event ├── it should perform the ERC-20 transfers diff --git a/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.t.sol b/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.t.sol index 29a12979a..7519eca56 100644 --- a/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.t.sol +++ b/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.t.sol @@ -11,8 +11,7 @@ import { ISablierV2LockupTranched } from "src/interfaces/ISablierV2LockupTranche import { Errors } from "src/libraries/Errors.sol"; import { Broker, Lockup, LockupTranched } from "src/types/DataTypes.sol"; -import { CreateWithTimestamps_Integration_Shared_Test } from - "../../../shared/lockup-tranched/createWithTimestamps.t.sol"; +import { CreateWithTimestamps_Integration_Shared_Test } from "../../../shared/lockup/createWithTimestamps.t.sol"; import { LockupTranched_Integration_Concrete_Test } from "../LockupTranched.t.sol"; contract CreateWithTimestamps_LockupTranched_Integration_Concrete_Test is @@ -79,7 +78,7 @@ contract CreateWithTimestamps_LockupTranched_Integration_Concrete_Test is whenStartTimeNotZero whenTrancheCountNotZero { - uint256 trancheCount = defaults.MAX_COUNT() + 1; + uint256 trancheCount = defaults.MAX_TRANCHE_COUNT() + 1; LockupTranched.Tranche[] memory tranches = new LockupTranched.Tranche[](trancheCount); vm.expectRevert( abi.encodeWithSelector(Errors.SablierV2LockupTranched_TrancheCountTooHigh.selector, trancheCount) @@ -380,7 +379,7 @@ contract CreateWithTimestamps_LockupTranched_Integration_Concrete_Test is Lockup.Status expectedStatus = Lockup.Status.PENDING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupTranched.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.tree b/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.tree index 4ffd8d5a5..3c4205768 100644 --- a/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.tree +++ b/test/integration/concrete/lockup-tranched/create-with-timestamps/createWithTimestamps.tree @@ -42,14 +42,14 @@ createWithTimestamps.t.sol └── when the asset is a contract ├── when the asset misses the ERC-20 return value │ ├── it should create the stream - │ ├── it should bump the next stream id + │ ├── it should bump the next stream ID │ ├── it should mint the NFT │ ├── it should emit a {MetadataUpdate} event │ ├── it should perform the ERC-20 transfers │ └── it should emit a {CreateLockupTranchedStream} event └── when the asset does not miss the ERC-20 return value ├── it should create the stream - ├── it should bump the next stream id + ├── it should bump the next stream ID ├── it should mint the NFT ├── it should emit a {MetadataUpdate} event ├── it should perform the ERC-20 transfers diff --git a/test/integration/concrete/lockup-tranched/get-range/getRange.tree b/test/integration/concrete/lockup-tranched/get-range/getRange.tree index 88dcc9707..61e44d77a 100644 --- a/test/integration/concrete/lockup-tranched/get-range/getRange.tree +++ b/test/integration/concrete/lockup-tranched/get-range/getRange.tree @@ -1,5 +1,5 @@ getRange.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct range diff --git a/test/integration/concrete/lockup-tranched/get-stream/getStream.tree b/test/integration/concrete/lockup-tranched/get-stream/getStream.tree index c3278db89..bde21f7b4 100644 --- a/test/integration/concrete/lockup-tranched/get-stream/getStream.tree +++ b/test/integration/concrete/lockup-tranched/get-stream/getStream.tree @@ -1,7 +1,7 @@ getStream.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is settled │ └── it should adjust the `isCancelable` flag and return the stream └── given the stream is not settled diff --git a/test/integration/concrete/lockup-tranched/get-tranches/getTranches.tree b/test/integration/concrete/lockup-tranched/get-tranches/getTranches.tree index 826ba60fa..4a8884be1 100644 --- a/test/integration/concrete/lockup-tranched/get-tranches/getTranches.tree +++ b/test/integration/concrete/lockup-tranched/get-tranches/getTranches.tree @@ -1,5 +1,5 @@ getTranches.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct tranches diff --git a/test/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol b/test/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol index 28e0257ad..04b8aeb06 100644 --- a/test/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol +++ b/test/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol @@ -10,7 +10,7 @@ import { Base64 } from "solady/src/utils/Base64.sol"; import { LockupTranched_Integration_Concrete_Test } from "../LockupTranched.t.sol"; /// @dev Requirements for these tests to work: -/// - The stream id must be 1 +/// - The stream ID must be 1 /// - The stream's sender must be `0x6332e7b1deb1f1a0b77b2bb18b144330c7291bca`, i.e. `makeAddr("Sender")` /// - The stream asset must have the DAI symbol /// - The contract deployer, i.e. the `sender` config option in `foundry.toml`, must have the default value diff --git a/test/integration/concrete/lockup/burn/burn.tree b/test/integration/concrete/lockup/burn/burn.tree index 90efa59eb..5ec96014b 100644 --- a/test/integration/concrete/lockup/burn/burn.tree +++ b/test/integration/concrete/lockup/burn/burn.tree @@ -2,9 +2,9 @@ burn.t.sol ├── when delegate called │ └── it should revert └── when not delegate called - ├── given the id references a null stream + ├── given the ID references a null stream │ └── it should revert - └── given the id does not reference a null stream + └── given the ID does not reference a null stream ├── given the stream has not been depleted │ ├── given the stream's status is "PENDING" │ │ └── it should revert diff --git a/test/integration/concrete/lockup/cancel-multiple/cancelMultiple.tree b/test/integration/concrete/lockup/cancel-multiple/cancelMultiple.tree index 2cd6a411f..b039e509f 100644 --- a/test/integration/concrete/lockup/cancel-multiple/cancelMultiple.tree +++ b/test/integration/concrete/lockup/cancel-multiple/cancelMultiple.tree @@ -5,11 +5,11 @@ cancelMultiple.t.sol ├── when the array count is zero │ └── it should do nothing └── when the array count is not zero - ├── given the stream ids array references only null streams + ├── given the stream IDs array references only null streams │ └── it should revert - ├── given the stream ids array references some null streams + ├── given the stream IDs array references some null streams │ └── it should revert - └── given the stream ids array references only streams that are not null + └── given the stream IDs array references only streams that are not null ├── given all streams are cold │ └── it should revert ├── given some streams are cold diff --git a/test/integration/concrete/lockup/cancel/cancel.tree b/test/integration/concrete/lockup/cancel/cancel.tree index 491c3f2e3..52c1ae929 100644 --- a/test/integration/concrete/lockup/cancel/cancel.tree +++ b/test/integration/concrete/lockup/cancel/cancel.tree @@ -2,9 +2,9 @@ cancel.t.sol ├── when delegate called │ └── it should revert └── when not delegate called - ├── given the id references a null stream + ├── given the ID references a null stream │ └── it should revert - └── given the id does not reference a null stream + └── given the ID does not reference a null stream ├── given the stream is cold │ ├── given the stream's status is "DEPLETED" │ │ └── it should revert @@ -57,4 +57,3 @@ cancel.t.sol ├── it should call the recipient hook ├── it should emit a {MetadataUpdate} event └── it should emit a {CancelLockupStream} event - \ No newline at end of file diff --git a/test/integration/concrete/lockup/get-asset/getAsset.tree b/test/integration/concrete/lockup/get-asset/getAsset.tree index 01bde9485..fd072b636 100644 --- a/test/integration/concrete/lockup/get-asset/getAsset.tree +++ b/test/integration/concrete/lockup/get-asset/getAsset.tree @@ -1,5 +1,5 @@ getAsset.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct address of the asset diff --git a/test/integration/concrete/lockup/get-deposited-amount/getDepositedAmount.tree b/test/integration/concrete/lockup/get-deposited-amount/getDepositedAmount.tree index 5254069e5..7aab0ae56 100644 --- a/test/integration/concrete/lockup/get-deposited-amount/getDepositedAmount.tree +++ b/test/integration/concrete/lockup/get-deposited-amount/getDepositedAmount.tree @@ -1,5 +1,5 @@ getDepositedAmount.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct deposited amount diff --git a/test/integration/concrete/lockup/get-end-time/getEndTime.tree b/test/integration/concrete/lockup/get-end-time/getEndTime.tree index 20359c089..235fe5270 100644 --- a/test/integration/concrete/lockup/get-end-time/getEndTime.tree +++ b/test/integration/concrete/lockup/get-end-time/getEndTime.tree @@ -1,5 +1,5 @@ getEndTime.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct end time diff --git a/test/integration/concrete/lockup/get-recipient/getRecipient.tree b/test/integration/concrete/lockup/get-recipient/getRecipient.tree index 5b33ed4a0..075fc23bd 100644 --- a/test/integration/concrete/lockup/get-recipient/getRecipient.tree +++ b/test/integration/concrete/lockup/get-recipient/getRecipient.tree @@ -1,7 +1,7 @@ getRecipient.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the NFT has been burned │ └── it should revert └── given the NFT has not been burned diff --git a/test/integration/concrete/lockup/get-refunded-amount/getRefundedAmount.tree b/test/integration/concrete/lockup/get-refunded-amount/getRefundedAmount.tree index 3a8aa8645..0ab67e853 100644 --- a/test/integration/concrete/lockup/get-refunded-amount/getRefundedAmount.tree +++ b/test/integration/concrete/lockup/get-refunded-amount/getRefundedAmount.tree @@ -1,7 +1,7 @@ getRefundedAmount.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream has been canceled │ ├── given the stream's status is "CANCELED" │ │ └── it should return the correct refunded amount diff --git a/test/integration/concrete/lockup/get-sender/getSender.tree b/test/integration/concrete/lockup/get-sender/getSender.tree index 50160b661..65b9b412a 100644 --- a/test/integration/concrete/lockup/get-sender/getSender.tree +++ b/test/integration/concrete/lockup/get-sender/getSender.tree @@ -1,5 +1,5 @@ getSender.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct sender diff --git a/test/integration/concrete/lockup/get-start-time/getStartTime.tree b/test/integration/concrete/lockup/get-start-time/getStartTime.tree index d65e107ab..a0c4f6da7 100644 --- a/test/integration/concrete/lockup/get-start-time/getStartTime.tree +++ b/test/integration/concrete/lockup/get-start-time/getStartTime.tree @@ -1,5 +1,5 @@ getStartTime.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return the correct start time diff --git a/test/integration/concrete/lockup/get-withdrawn-amount/getWithdrawnAmount.tree b/test/integration/concrete/lockup/get-withdrawn-amount/getWithdrawnAmount.tree index 2a88d73c9..ca78cb978 100644 --- a/test/integration/concrete/lockup/get-withdrawn-amount/getWithdrawnAmount.tree +++ b/test/integration/concrete/lockup/get-withdrawn-amount/getWithdrawnAmount.tree @@ -1,7 +1,7 @@ getWithdrawnAmount.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given there are no previous withdrawals │ └── it should return zero └── given there are previous withdrawals diff --git a/test/integration/concrete/lockup/is-cancelable/isCancelable.tree b/test/integration/concrete/lockup/is-cancelable/isCancelable.tree index 8a36d6dbe..c75cda4f3 100644 --- a/test/integration/concrete/lockup/is-cancelable/isCancelable.tree +++ b/test/integration/concrete/lockup/is-cancelable/isCancelable.tree @@ -1,7 +1,7 @@ isCancelable.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is cold │ └── it should return true └── given the stream is not cold diff --git a/test/integration/concrete/lockup/is-cold/isCold.tree b/test/integration/concrete/lockup/is-cold/isCold.tree index 15bfe3fdc..5902b8b9f 100644 --- a/test/integration/concrete/lockup/is-cold/isCold.tree +++ b/test/integration/concrete/lockup/is-cold/isCold.tree @@ -1,7 +1,7 @@ isCold.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream's status is pending │ └── it should return false ├── given the stream's status is streaming diff --git a/test/integration/concrete/lockup/is-depleted/isDepleted.tree b/test/integration/concrete/lockup/is-depleted/isDepleted.tree index 43149d5aa..3b796bd0c 100644 --- a/test/integration/concrete/lockup/is-depleted/isDepleted.tree +++ b/test/integration/concrete/lockup/is-depleted/isDepleted.tree @@ -1,7 +1,7 @@ isDepleted.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is not depleted │ └── it should return false └── given the stream is depleted diff --git a/test/integration/concrete/lockup/is-stream/isStream.tree b/test/integration/concrete/lockup/is-stream/isStream.tree index 5846352f8..83ae45765 100644 --- a/test/integration/concrete/lockup/is-stream/isStream.tree +++ b/test/integration/concrete/lockup/is-stream/isStream.tree @@ -1,5 +1,5 @@ isStream.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should return false -└── given the id does not reference a null stream +└── given the ID does not reference a null stream └── it should return true diff --git a/test/integration/concrete/lockup/is-transferable/isTransferable.tree b/test/integration/concrete/lockup/is-transferable/isTransferable.tree index 2fefdc265..aba57c19d 100644 --- a/test/integration/concrete/lockup/is-transferable/isTransferable.tree +++ b/test/integration/concrete/lockup/is-transferable/isTransferable.tree @@ -1,7 +1,7 @@ isTransferable.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is not transferable │ └── it should return false └── given the stream is transferable diff --git a/test/integration/concrete/lockup/is-warm/isWarm.tree b/test/integration/concrete/lockup/is-warm/isWarm.tree index be21fe1d1..7044432bb 100644 --- a/test/integration/concrete/lockup/is-warm/isWarm.tree +++ b/test/integration/concrete/lockup/is-warm/isWarm.tree @@ -1,7 +1,7 @@ isWarm.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream's status is pending │ └── it should return true ├── given the stream's status is streaming diff --git a/test/integration/concrete/lockup/refundable-amount-of/refundableAmountOf.tree b/test/integration/concrete/lockup/refundable-amount-of/refundableAmountOf.tree index ebfdbcdad..e46acad0d 100644 --- a/test/integration/concrete/lockup/refundable-amount-of/refundableAmountOf.tree +++ b/test/integration/concrete/lockup/refundable-amount-of/refundableAmountOf.tree @@ -1,7 +1,7 @@ refundableAmountOf.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream is not cancelable │ └── it should return zero └── given the stream is cancelable diff --git a/test/integration/concrete/lockup/renounce/renounce.tree b/test/integration/concrete/lockup/renounce/renounce.tree index be03dbc40..1a80ac4d5 100644 --- a/test/integration/concrete/lockup/renounce/renounce.tree +++ b/test/integration/concrete/lockup/renounce/renounce.tree @@ -2,9 +2,9 @@ renounce.t.sol ├── when delegate called │ └── it should revert └── when not delegate called - ├── given the id references a null stream + ├── given the ID references a null stream │ └── it should revert - └── given the id does not reference a null stream + └── given the ID does not reference a null stream ├── given the stream is cold │ ├── given the stream's status is "DEPLETED" │ │ └── it should revert diff --git a/test/integration/concrete/lockup/status-of/statusOf.tree b/test/integration/concrete/lockup/status-of/statusOf.tree index 6d0bfda29..03c12a2ef 100644 --- a/test/integration/concrete/lockup/status-of/statusOf.tree +++ b/test/integration/concrete/lockup/status-of/statusOf.tree @@ -1,7 +1,7 @@ statusOf.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given assets have been fully withdrawn │ └── it should return DEPLETED └── given assets have not been fully withdrawn diff --git a/test/integration/concrete/lockup/streamed-amount-of/streamedAmountOf.tree b/test/integration/concrete/lockup/streamed-amount-of/streamedAmountOf.tree index dbc0970ab..f0784e8ea 100644 --- a/test/integration/concrete/lockup/streamed-amount-of/streamedAmountOf.tree +++ b/test/integration/concrete/lockup/streamed-amount-of/streamedAmountOf.tree @@ -1,7 +1,7 @@ streamedAmountOf.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream has been canceled │ ├── given the stream's status is "CANCELED" │ │ └── it should return the correct streamed amount diff --git a/test/integration/concrete/lockup/was-canceled/wasCanceled.tree b/test/integration/concrete/lockup/was-canceled/wasCanceled.tree index 5dd4e1e3a..0be9ecbda 100644 --- a/test/integration/concrete/lockup/was-canceled/wasCanceled.tree +++ b/test/integration/concrete/lockup/was-canceled/wasCanceled.tree @@ -1,7 +1,7 @@ wasCanceled.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream was not canceled │ └── it should return false └── given the stream was canceled diff --git a/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.t.sol b/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.t.sol index 6261abcbf..55268ccaf 100644 --- a/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.t.sol +++ b/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.t.sol @@ -1,5 +1,4 @@ // SPDX-License-Identifier: UNLICENSED -// solhint-disable max-line-length pragma solidity >=0.8.22 <0.9.0; import { ISablierV2Recipient } from "src/interfaces/hooks/ISablierV2Recipient.sol"; @@ -9,8 +8,11 @@ import { Integration_Test } from "../../../Integration.t.sol"; import { Withdraw_Integration_Shared_Test } from "../../../shared/lockup/withdraw.t.sol"; abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, Withdraw_Integration_Shared_Test { + uint128 internal withdrawAmount; + function setUp() public virtual override(Integration_Test, Withdraw_Integration_Shared_Test) { Withdraw_Integration_Shared_Test.setUp(); + withdrawAmount = defaults.WITHDRAW_AMOUNT(); } modifier givenDifferentSenderAndRecipient() { @@ -25,7 +27,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W { address unknownCaller = address(0xCAFE); - // Create the stream with sender and recipient as contracts. + // Create the stream with both the sender and the recipient as contracts. uint256 streamId = createDefaultStreamWithUsers(address(goodRecipient), address(goodSender)); // Make `unknownCaller` the caller in this test. @@ -34,16 +36,13 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - // Expect a call to the recipient hook. vm.expectCall({ callee: address(goodRecipient), data: abi.encodeCall( ISablierV2Recipient.onLockupStreamWithdrawn, (streamId, unknownCaller, address(goodRecipient), withdrawAmount) - ), + ), count: 1 }); @@ -52,7 +51,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W callee: address(goodSender), data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, unknownCaller, address(goodRecipient), withdrawAmount) - ), + ), count: 1 }); @@ -66,7 +65,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W givenRecipientContract givenDifferentSenderAndRecipient { - // Create the stream with sender and recipient as contracts. + // Create the stream with both the sender and the recipient as contracts. uint256 streamId = createDefaultStreamWithUsers(address(goodRecipient), address(goodSender)); // Approve the operator to handle the stream. @@ -79,16 +78,13 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - // Expect a call to the recipient hook. vm.expectCall({ callee: address(goodRecipient), data: abi.encodeCall( ISablierV2Recipient.onLockupStreamWithdrawn, (streamId, users.operator, address(goodRecipient), withdrawAmount) - ), + ), count: 1 }); @@ -97,7 +93,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W callee: address(goodSender), data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, users.operator, address(goodRecipient), withdrawAmount) - ), + ), count: 1 }); @@ -111,7 +107,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W givenRecipientContract givenDifferentSenderAndRecipient { - // Create the stream with sender and recipient as contracts. + // Create the stream with both the sender and the recipient as contracts. uint256 streamId = createDefaultStreamWithUsers(address(goodRecipient), address(goodSender)); // Make the sender the caller in this test. @@ -120,26 +116,23 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - // Expect 1 call to the recipient hook. vm.expectCall({ callee: address(goodRecipient), data: abi.encodeCall( ISablierV2Recipient.onLockupStreamWithdrawn, (streamId, address(goodSender), address(goodRecipient), withdrawAmount) - ), + ), count: 1 }); - // Expect 0 calls to the sender hook. + // Expect no calls to the sender hook. vm.expectCall({ callee: address(goodSender), data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, address(goodSender), address(goodRecipient), withdrawAmount) - ), + ), count: 0 }); @@ -153,7 +146,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W givenRecipientContract givenDifferentSenderAndRecipient { - // Create the stream with sender and recipient as contracts. + // Create the stream with both the sender and the recipient as contracts. uint256 streamId = createDefaultStreamWithUsers(address(goodRecipient), address(goodSender)); // Make the recipient the caller in this test. @@ -162,16 +155,13 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - - // Expect 0 calls to the recipient hook. + // Expect no calls to the recipient hook. vm.expectCall({ callee: address(goodRecipient), data: abi.encodeCall( ISablierV2Recipient.onLockupStreamWithdrawn, (streamId, address(goodRecipient), address(goodRecipient), withdrawAmount) - ), + ), count: 0 }); @@ -181,7 +171,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, address(goodRecipient), address(goodRecipient), withdrawAmount) - ), + ), count: 1 }); @@ -196,8 +186,8 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W function test_WithdrawHooks_SenderHook_CallerUnknown() external givenSenderContract givenSameSenderAndRecipient { address unknownCaller = address(0xCAFE); - // Create the stream with recipient which is same as the sender contract. - uint256 streamId = createDefaultStreamToSender(address(goodSender)); + // Create the stream with the recipient as the sender. + uint256 streamId = createDefaultStreamWithIdenticalUsers(address(goodSender)); // Make unknownCaller the caller in this test. changePrank({ msgSender: unknownCaller }); @@ -205,15 +195,12 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - // Expect a call to the sender hook. vm.expectCall({ callee: address(goodSender), data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, unknownCaller, address(goodSender), withdrawAmount) - ), + ), count: 1 }); @@ -227,7 +214,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W givenSameSenderAndRecipient { // Create the stream with recipient which is same as the sender contract. - uint256 streamId = createDefaultStreamToSender(address(goodSender)); + uint256 streamId = createDefaultStreamWithIdenticalUsers(address(goodSender)); // Approve the operator to handle the stream. changePrank({ msgSender: address(goodSender) }); @@ -239,15 +226,12 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - // Expect a call to the sender hook. vm.expectCall({ callee: address(goodSender), data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, users.operator, address(goodSender), withdrawAmount) - ), + ), count: 1 }); @@ -257,7 +241,7 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W function test_WithdrawHooks_SenderHook_CallerSender() external givenSenderContract givenSameSenderAndRecipient { // Create the stream with the sender as the recipient. - uint256 streamId = createDefaultStreamToSender(address(goodSender)); + uint256 streamId = createDefaultStreamWithIdenticalUsers(address(goodSender)); // Approve the operator to handle the stream. changePrank({ msgSender: address(goodSender) }); @@ -265,16 +249,13 @@ abstract contract WithdrawHooks_Integration_Concrete_Test is Integration_Test, W // Simulate the passage of time. vm.warp({ newTimestamp: defaults.WARP_26_PERCENT() }); - // Set the withdraw amount to the default amount. - uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - - // Expect 0 calls to the sender hook. + // Expect no calls to the sender hook. vm.expectCall({ callee: address(goodSender), data: abi.encodeCall( ISablierV2Sender.onLockupStreamWithdrawn, (streamId, address(goodSender), address(goodSender), withdrawAmount) - ), + ), count: 0 }); diff --git a/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.tree b/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.tree index 79a896aa2..f0500c61a 100644 --- a/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.tree +++ b/test/integration/concrete/lockup/withdraw-hooks/withdrawHooks.tree @@ -12,7 +12,7 @@ withdrawHooks.t.sol │ └── when the caller is the recipient │ ├── it should make one hook call to the sender │ └── it should not make any hook call to the recipient -└── given the recipient is same as the sender +└── given the recipient is the same as the sender ├── when the caller is unknown │ └── it should make one hook call to the sender ├── when the caller is an approved third party diff --git a/test/integration/concrete/lockup/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree b/test/integration/concrete/lockup/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree index f53682e9e..cb45e2a6e 100644 --- a/test/integration/concrete/lockup/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree +++ b/test/integration/concrete/lockup/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree @@ -2,9 +2,9 @@ withdrawMaxAndTransfer.t.sol ├── when delegate called │ └── it should revert └── when not delegate called - ├── given the id references a null stream + ├── given the ID references a null stream │ └── it should revert - └── given the id does not reference a null stream + └── given the ID does not reference a null stream ├── given the stream is not transferable │ └── it should revert └── given the stream is transferable diff --git a/test/integration/concrete/lockup/withdraw-multiple/withdrawMultiple.tree b/test/integration/concrete/lockup/withdraw-multiple/withdrawMultiple.tree index 6759b6aa2..c9fbb0d35 100644 --- a/test/integration/concrete/lockup/withdraw-multiple/withdrawMultiple.tree +++ b/test/integration/concrete/lockup/withdraw-multiple/withdrawMultiple.tree @@ -8,11 +8,11 @@ withdrawMultiple.t.sol ├── when the array counts are zero │ └── it should do nothing └── when the array counts are not zero - ├── given the stream ids array references only null streams + ├── given the stream IDs array references only null streams │ └── it should revert - ├── given the stream ids array references some null streams + ├── given the stream IDs array references some null streams │ └── it should revert - └── given the stream ids array references only non-null streams + └── given the stream IDs array references only non-null streams ├── given all streams' statuses are "DEPLETED" │ └── it should revert ├── given some streams' statuses are "DEPLETED" diff --git a/test/integration/concrete/lockup/withdraw/withdraw.t.sol b/test/integration/concrete/lockup/withdraw/withdraw.t.sol index 55d0d05c8..e7a72167e 100644 --- a/test/integration/concrete/lockup/withdraw/withdraw.t.sol +++ b/test/integration/concrete/lockup/withdraw/withdraw.t.sol @@ -46,7 +46,7 @@ abstract contract Withdraw_Integration_Concrete_Test is Integration_Test, Withdr function test_RevertWhen_ToZeroAddress() external whenNotDelegateCalled givenNotNull givenStreamNotDepleted { uint128 withdrawAmount = defaults.WITHDRAW_AMOUNT(); - vm.expectRevert(Errors.SablierV2Lockup_WithdrawToZeroAddress.selector); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2Lockup_WithdrawToZeroAddress.selector, defaultStreamId)); lockup.withdraw({ streamId: defaultStreamId, to: address(0), amount: withdrawAmount }); } diff --git a/test/integration/concrete/lockup/withdraw/withdraw.tree b/test/integration/concrete/lockup/withdraw/withdraw.tree index fccd07685..8cf51bdf3 100644 --- a/test/integration/concrete/lockup/withdraw/withdraw.tree +++ b/test/integration/concrete/lockup/withdraw/withdraw.tree @@ -2,9 +2,9 @@ withdraw.t.sol ├── when delegate called │ └── it should revert └── when not delegate called - ├── given the id references a null stream + ├── given the ID references a null stream │ └── it should revert - └── given the id does not reference a null stream + └── given the ID does not reference a null stream ├── given the stream's status is "DEPLETED" │ └── it should revert └── given the stream's status is not "DEPLETED" diff --git a/test/integration/concrete/lockup/withdrawable-amount-of/withdrawableAmountOf.tree b/test/integration/concrete/lockup/withdrawable-amount-of/withdrawableAmountOf.tree index 27c4896ef..183bddf1b 100644 --- a/test/integration/concrete/lockup/withdrawable-amount-of/withdrawableAmountOf.tree +++ b/test/integration/concrete/lockup/withdrawable-amount-of/withdrawableAmountOf.tree @@ -1,7 +1,7 @@ withdrawableAmountOf.t.sol -├── given the id references a null stream +├── given the ID references a null stream │ └── it should revert -└── given the id does not reference a null stream +└── given the ID does not reference a null stream ├── given the stream has been canceled │ ├── given the stream's status is "CANCELED" │ │ └── it should return the correct withdrawable amount diff --git a/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol b/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol index 4d7e7e2e2..07461069b 100644 --- a/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol +++ b/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ERC721Mock } from "../../../../mocks/erc721/ERC721Mock.sol"; +import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; +import { MockERC721 } from "forge-std/src/mocks/MockERC721.sol"; import { Errors } from "src/libraries/Errors.sol"; @@ -9,9 +10,10 @@ import { NFTDescriptor_Integration_Concrete_Test } from "../NFTDescriptor.t.sol" contract MapSymbol_Integration_Concrete_Test is NFTDescriptor_Integration_Concrete_Test { function test_RevertGiven_UnknownNFT() external { - ERC721Mock nft = new ERC721Mock("Foo NFT", "FOO"); + MockERC721 nft = new MockERC721(); + nft.initialize("Foo", "FOO"); vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2NFTDescriptor_UnknownNFT.selector, nft, "FOO")); - nftDescriptorMock.mapSymbol_(nft); + nftDescriptorMock.mapSymbol_(IERC721Metadata(address(nft))); } modifier givenKnownNFT() { @@ -19,14 +21,20 @@ contract MapSymbol_Integration_Concrete_Test is NFTDescriptor_Integration_Concre } function test_MapSymbol_LockupDynamic() external view givenKnownNFT { - string memory actualStreamingModel = nftDescriptorMock.mapSymbol_(lockupDynamic); - string memory expectedStreamingModel = "Lockup Dynamic"; - assertEq(actualStreamingModel, expectedStreamingModel, "streamingModel"); + string memory actualSablierModel = nftDescriptorMock.mapSymbol_(lockupDynamic); + string memory expectedSablierModel = "Lockup Dynamic"; + assertEq(actualSablierModel, expectedSablierModel, "sablierModel"); } function test_MapSymbol_LockupLinear() external view givenKnownNFT { - string memory actualStreamingModel = nftDescriptorMock.mapSymbol_(lockupLinear); - string memory expectedStreamingModel = "Lockup Linear"; - assertEq(actualStreamingModel, expectedStreamingModel, "streamingModel"); + string memory actualSablierModel = nftDescriptorMock.mapSymbol_(lockupLinear); + string memory expectedSablierModel = "Lockup Linear"; + assertEq(actualSablierModel, expectedSablierModel, "sablierModel"); + } + + function test_MapSymbol_LockupTranched() external view givenKnownNFT { + string memory actualSablierModel = nftDescriptorMock.mapSymbol_(lockupTranched); + string memory expectedSablierModel = "Lockup Tranched"; + assertEq(actualSablierModel, expectedSablierModel, "sablierModel"); } } diff --git a/test/integration/fuzz/lockup-dynamic/createWithDurations.t.sol b/test/integration/fuzz/lockup-dynamic/createWithDurations.t.sol index 7cd7869d1..49dee2114 100644 --- a/test/integration/fuzz/lockup-dynamic/createWithDurations.t.sol +++ b/test/integration/fuzz/lockup-dynamic/createWithDurations.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; -import { CreateWithDurations_Integration_Shared_Test } from "../../shared/lockup-dynamic/createWithDurations.t.sol"; +import { CreateWithDurations_Integration_Shared_Test } from "../../shared/lockup/createWithDurations.t.sol"; import { LockupDynamic_Integration_Fuzz_Test } from "./LockupDynamic.t.sol"; contract CreateWithDurations_LockupDynamic_Integration_Fuzz_Test is @@ -105,9 +105,9 @@ contract CreateWithDurations_LockupDynamic_Integration_Fuzz_Test is assertEq(actualStream.asset, dai, "asset"); assertEq(actualStream.endTime, range.end, "endTime"); assertEq(actualStream.isCancelable, vars.isCancelable, "isCancelable"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isDepleted, false, "isDepleted"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, users.recipient, "recipient"); assertEq(actualStream.segments, vars.segmentsWithTimestamps, "segments"); assertEq(actualStream.sender, users.sender, "sender"); @@ -119,7 +119,7 @@ contract CreateWithDurations_LockupDynamic_Integration_Fuzz_Test is vars.expectedStatus = vars.isSettled ? Lockup.Status.SETTLED : Lockup.Status.STREAMING; assertEq(vars.actualStatus, vars.expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupDynamic.nextStreamId(); vars.expectedNextStreamId = streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/fuzz/lockup-dynamic/createWithTimestamps.t.sol b/test/integration/fuzz/lockup-dynamic/createWithTimestamps.t.sol index 22a98f8d2..bbedfef03 100644 --- a/test/integration/fuzz/lockup-dynamic/createWithTimestamps.t.sol +++ b/test/integration/fuzz/lockup-dynamic/createWithTimestamps.t.sol @@ -7,7 +7,7 @@ import { stdError } from "forge-std/src/StdError.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Broker, Lockup, LockupDynamic } from "src/types/DataTypes.sol"; -import { CreateWithTimestamps_Integration_Shared_Test } from "../../shared/lockup-dynamic/createWithTimestamps.t.sol"; +import { CreateWithTimestamps_Integration_Shared_Test } from "../../shared/lockup/createWithTimestamps.t.sol"; import { LockupDynamic_Integration_Fuzz_Test } from "./LockupDynamic.t.sol"; contract CreateWithTimestamps_LockupDynamic_Integration_Fuzz_Test is @@ -30,7 +30,8 @@ contract CreateWithTimestamps_LockupDynamic_Integration_Fuzz_Test is whenDepositAmountNotZero whenSegmentCountNotZero { - segmentCount = _bound(segmentCount, defaults.MAX_COUNT() + 1 seconds, defaults.MAX_COUNT() * 10); + uint256 defaultMax = defaults.MAX_SEGMENT_COUNT(); + segmentCount = _bound(segmentCount, defaultMax + 1, defaultMax * 10); LockupDynamic.Segment[] memory segments = new LockupDynamic.Segment[](segmentCount); vm.expectRevert( abi.encodeWithSelector(Errors.SablierV2LockupDynamic_SegmentCountTooHigh.selector, segmentCount) @@ -267,9 +268,9 @@ contract CreateWithTimestamps_LockupDynamic_Integration_Fuzz_Test is assertEq(actualStream.asset, dai, "asset"); assertEq(actualStream.endTime, range.end, "endTime"); assertEq(actualStream.isCancelable, vars.isCancelable, "isCancelable"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isDepleted, false, "isStream"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.sender, params.sender, "sender"); assertEq(actualStream.segments, params.segments, "segments"); @@ -287,7 +288,7 @@ contract CreateWithTimestamps_LockupDynamic_Integration_Fuzz_Test is } assertEq(vars.actualStatus, vars.expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupDynamic.nextStreamId(); vars.expectedNextStreamId = streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol b/test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol index 4ea56540c..0e1cc38ee 100644 --- a/test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol +++ b/test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol @@ -57,12 +57,12 @@ contract StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test is uint256 streamId = lockupDynamic.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualStreamedAmount = lockupDynamic.streamedAmountOf(streamId); - uint128 expectedStreamedAmount = calculateStreamedAmountForOneSegment(currentTime, segment); + uint128 expectedStreamedAmount = calculateStreamedAmountForOneSegment(blockTimestamp, segment); assertEq(actualStreamedAmount, expectedStreamedAmount, "streamedAmount"); } @@ -118,12 +118,13 @@ contract StreamedAmountOf_LockupDynamic_Integration_Fuzz_Test is uint256 streamId = lockupDynamic.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualStreamedAmount = lockupDynamic.streamedAmountOf(streamId); - uint128 expectedStreamedAmount = calculateStreamedAmountForMultipleSegments(currentTime, segments, totalAmount); + uint128 expectedStreamedAmount = + calculateStreamedAmountForMultipleSegments(blockTimestamp, segments, totalAmount); assertEq(actualStreamedAmount, expectedStreamedAmount, "streamedAmount"); } diff --git a/test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol b/test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol index 045ebc2c5..27751e524 100644 --- a/test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol +++ b/test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol @@ -45,13 +45,13 @@ contract WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test is uint256 streamId = lockupDynamic.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualWithdrawableAmount = lockupDynamic.withdrawableAmountOf(streamId); uint128 expectedWithdrawableAmount = - calculateStreamedAmountForMultipleSegments(currentTime, defaults.segments(), defaults.DEPOSIT_AMOUNT()); + calculateStreamedAmountForMultipleSegments(blockTimestamp, defaults.segments(), defaults.DEPOSIT_AMOUNT()); assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawableAmount"); } @@ -79,12 +79,12 @@ contract WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test is { timeJump = boundUint40(timeJump, defaults.CLIFF_DURATION(), defaults.TOTAL_DURATION() * 2); - // Define the current time. - uint40 currentTime = defaults.START_TIME() + timeJump; + // Define the block timestamp. + uint40 blockTimestamp = defaults.START_TIME() + timeJump; // Bound the withdraw amount. uint128 streamedAmount = - calculateStreamedAmountForMultipleSegments(currentTime, defaults.segments(), defaults.DEPOSIT_AMOUNT()); + calculateStreamedAmountForMultipleSegments(blockTimestamp, defaults.segments(), defaults.DEPOSIT_AMOUNT()); withdrawAmount = boundUint128(withdrawAmount, 1, streamedAmount); // Create the stream with a custom total amount. The broker fee is disabled so that it doesn't interfere with @@ -95,7 +95,7 @@ contract WithdrawableAmountOf_LockupDynamic_Integration_Fuzz_Test is uint256 streamId = lockupDynamic.createWithTimestamps(params); // Simulate the passage of time. - vm.warp({ newTimestamp: currentTime }); + vm.warp({ newTimestamp: blockTimestamp }); // Make the withdrawal. lockupDynamic.withdraw({ streamId: streamId, to: users.recipient, amount: withdrawAmount }); diff --git a/test/integration/fuzz/lockup-linear/createWithDurations.t.sol b/test/integration/fuzz/lockup-linear/createWithDurations.t.sol index 9e69b82af..50c78efef 100644 --- a/test/integration/fuzz/lockup-linear/createWithDurations.t.sol +++ b/test/integration/fuzz/lockup-linear/createWithDurations.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22 <0.9.0; import { Errors } from "src/libraries/Errors.sol"; import { Lockup, LockupLinear } from "src/types/DataTypes.sol"; -import { CreateWithDurations_Integration_Shared_Test } from "../../shared/lockup-linear/createWithDurations.t.sol"; +import { CreateWithDurations_Integration_Shared_Test } from "../../shared/lockup/createWithDurations.t.sol"; import { LockupLinear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; contract CreateWithDurations_LockupLinear_Integration_Fuzz_Test is @@ -26,7 +26,7 @@ contract CreateWithDurations_LockupLinear_Integration_Fuzz_Test is whenCliffDurationCalculationDoesNotOverflow { uint40 startTime = getBlockTimestamp(); - durations.cliff = boundUint40(durations.cliff, 0, MAX_UINT40 - startTime); + durations.cliff = boundUint40(durations.cliff, 1 seconds, MAX_UINT40 - startTime); durations.total = boundUint40(durations.total, MAX_UINT40 - startTime + 1 seconds, MAX_UINT40); // Calculate the cliff time and the end time. Needs to be "unchecked" to allow an overflow. @@ -40,7 +40,7 @@ contract CreateWithDurations_LockupLinear_Integration_Fuzz_Test is // Expect the relevant error to be thrown. vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2LockupLinear_StartTimeNotLessThanEndTime.selector, startTime, endTime + Errors.SablierV2LockupLinear_CliffTimeNotLessThanEndTime.selector, cliffTime, endTime ) ); @@ -54,7 +54,7 @@ contract CreateWithDurations_LockupLinear_Integration_Fuzz_Test is whenCliffDurationCalculationDoesNotOverflow whenTotalDurationCalculationDoesNotOverflow { - durations.total = boundUint40(durations.total, 1, MAX_UNIX_TIMESTAMP); + durations.total = boundUint40(durations.total, 1 seconds, MAX_UNIX_TIMESTAMP); vm.assume(durations.cliff < durations.total); // Make the Sender the stream's funder (recall that the Sender is the default caller). @@ -104,7 +104,7 @@ contract CreateWithDurations_LockupLinear_Integration_Fuzz_Test is Lockup.Status expectedStatus = Lockup.Status.STREAMING; assertEq(actualStatus, expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. uint256 actualNextStreamId = lockupLinear.nextStreamId(); uint256 expectedNextStreamId = streamId + 1; assertEq(actualNextStreamId, expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/fuzz/lockup-linear/createWithTimestamps.t.sol b/test/integration/fuzz/lockup-linear/createWithTimestamps.t.sol index 09ad044fa..444a0e7e9 100644 --- a/test/integration/fuzz/lockup-linear/createWithTimestamps.t.sol +++ b/test/integration/fuzz/lockup-linear/createWithTimestamps.t.sol @@ -6,7 +6,7 @@ import { MAX_UD60x18, ud } from "@prb/math/src/UD60x18.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Broker, Lockup, LockupLinear } from "src/types/DataTypes.sol"; -import { CreateWithTimestamps_Integration_Shared_Test } from "../../shared/lockup-linear/createWithTimestamps.t.sol"; +import { CreateWithTimestamps_Integration_Shared_Test } from "../../shared/lockup/createWithTimestamps.t.sol"; import { LockupLinear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is @@ -22,7 +22,21 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is CreateWithTimestamps_Integration_Shared_Test.setUp(); } - function testFuzz_RevertWhen_StartTimeGreaterThanCliffTime(uint40 startTime) + function testFuzz_RevertWhen_BrokerFeeTooHigh(Broker memory broker) + external + whenNotDelegateCalled + whenRecipientNonZeroAddress + whenDepositAmountNotZero + { + vm.assume(broker.account != address(0)); + broker.fee = _bound(broker.fee, MAX_BROKER_FEE + ud(1), MAX_UD60x18); + vm.expectRevert( + abi.encodeWithSelector(Errors.SablierV2Lockup_BrokerFeeTooHigh.selector, broker.fee, MAX_BROKER_FEE) + ); + createDefaultStreamWithBroker(broker); + } + + function testFuzz_RevertWhen_StartTimeNotLessThanCliffTime(uint40 startTime) external whenNotDelegateCalled whenRecipientNonZeroAddress @@ -45,10 +59,9 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is whenNotDelegateCalled whenRecipientNonZeroAddress whenDepositAmountNotZero - whenStartTimeNotGreaterThanCliffTime { uint40 startTime = defaults.START_TIME(); - endTime = boundUint40(endTime, startTime + 1, startTime + 2 weeks); + endTime = boundUint40(endTime, startTime + 1 seconds, startTime + 2 weeks); cliffTime = boundUint40(cliffTime, endTime, MAX_UNIX_TIMESTAMP); vm.expectRevert( @@ -59,23 +72,6 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is createDefaultStreamWithRange(LockupLinear.Range({ start: startTime, cliff: cliffTime, end: endTime })); } - function testFuzz_RevertWhen_BrokerFeeTooHigh(Broker memory broker) - external - whenNotDelegateCalled - whenRecipientNonZeroAddress - whenDepositAmountNotZero - whenStartTimeNotGreaterThanCliffTime - whenCliffTimeLessThanEndTime - whenEndTimeInTheFuture - { - vm.assume(broker.account != address(0)); - broker.fee = _bound(broker.fee, MAX_BROKER_FEE + ud(1), MAX_UD60x18); - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2Lockup_BrokerFeeTooHigh.selector, broker.fee, MAX_BROKER_FEE) - ); - createDefaultStreamWithBroker(broker); - } - struct Vars { uint256 actualNextStreamId; address actualNFTOwner; @@ -95,6 +91,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is /// - Start time in the present /// - Start time in the future /// - Start time lower than and equal to cliff time + /// - Cliff time zero and not zero /// - Multiple values for the cliff time and the end time /// - Multiple values for the broker fee, including zero function testFuzz_CreateWithTimestamps( @@ -105,7 +102,6 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is whenNotDelegateCalled whenDepositAmountNotZero whenStartTimeNotZero - whenStartTimeNotGreaterThanCliffTime whenCliffTimeLessThanEndTime whenEndTimeInTheFuture whenBrokerFeeNotTooHigh @@ -116,11 +112,18 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is vm.assume(params.totalAmount != 0); params.range.start = boundUint40(params.range.start, defaults.START_TIME(), defaults.START_TIME() + 10_000 seconds); - params.range.cliff = boundUint40(params.range.cliff, params.range.start + 1, params.range.start + 52 weeks); - params.range.end = boundUint40(params.range.end, params.range.cliff + 1 seconds, MAX_UNIX_TIMESTAMP); params.broker.fee = _bound(params.broker.fee, 0, MAX_BROKER_FEE); params.transferable = true; + // The cliff time must be either zero or greater than the start time. + if (params.range.cliff > 0) { + params.range.cliff = + boundUint40(params.range.cliff, params.range.start + 1 seconds, params.range.start + 52 weeks); + params.range.end = boundUint40(params.range.end, params.range.cliff + 1 seconds, MAX_UNIX_TIMESTAMP); + } else { + params.range.end = boundUint40(params.range.end, params.range.start + 1 seconds, MAX_UNIX_TIMESTAMP); + } + // Calculate the fee amounts and the deposit amount. Vars memory vars; @@ -181,8 +184,8 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is assertEq(actualStream.endTime, params.range.end, "endTime"); assertEq(actualStream.isCancelable, params.cancelable, "isCancelable"); assertEq(actualStream.isDepleted, false, "isStream"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.sender, params.sender, "sender"); assertEq(actualStream.startTime, params.range.start, "startTime"); @@ -193,7 +196,7 @@ contract CreateWithTimestamps_LockupLinear_Integration_Fuzz_Test is vars.expectedStatus = params.range.start > getBlockTimestamp() ? Lockup.Status.PENDING : Lockup.Status.STREAMING; assertEq(vars.actualStatus, vars.expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupLinear.nextStreamId(); vars.expectedNextStreamId = streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol b/test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol index c8f452713..4f7abddc9 100644 --- a/test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol +++ b/test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol @@ -70,12 +70,12 @@ contract StreamedAmountOf_LockupLinear_Integration_Fuzz_Test is uint256 streamId = lockupLinear.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualStreamedAmount = lockupLinear.streamedAmountOf(streamId); - uint128 expectedStreamedAmount = calculateStreamedAmount(currentTime, depositAmount); + uint128 expectedStreamedAmount = calculateStreamedAmount(blockTimestamp, depositAmount); assertEq(actualStreamedAmount, expectedStreamedAmount, "streamedAmount"); } diff --git a/test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol b/test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol index bdd34946c..7bb8d459b 100644 --- a/test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol +++ b/test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol @@ -67,12 +67,12 @@ contract WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test is uint256 streamId = lockupLinear.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualWithdrawableAmount = lockupLinear.withdrawableAmountOf(streamId); - uint128 expectedWithdrawableAmount = calculateStreamedAmount(currentTime, depositAmount); + uint128 expectedWithdrawableAmount = calculateStreamedAmount(blockTimestamp, depositAmount); assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawableAmount"); } @@ -105,11 +105,11 @@ contract WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test is timeJump = boundUint40(timeJump, defaults.CLIFF_DURATION(), defaults.TOTAL_DURATION() * 2); depositAmount = boundUint128(depositAmount, 10_000, MAX_UINT128); - // Define the current time. - uint40 currentTime = defaults.START_TIME() + timeJump; + // Define the block timestamp. + uint40 blockTimestamp = defaults.START_TIME() + timeJump; // Bound the withdraw amount. - uint128 streamedAmount = calculateStreamedAmount(currentTime, depositAmount); + uint128 streamedAmount = calculateStreamedAmount(blockTimestamp, depositAmount); withdrawAmount = boundUint128(withdrawAmount, 1, streamedAmount); // Mint enough assets to the Sender. @@ -122,7 +122,7 @@ contract WithdrawableAmountOf_LockupLinear_Integration_Fuzz_Test is uint256 streamId = lockupLinear.createWithTimestamps(params); // Simulate the passage of time. - vm.warp({ newTimestamp: currentTime }); + vm.warp({ newTimestamp: blockTimestamp }); // Make the withdrawal. lockupLinear.withdraw({ streamId: streamId, to: users.recipient, amount: withdrawAmount }); diff --git a/test/integration/fuzz/lockup-tranched/createWithDurations.t.sol b/test/integration/fuzz/lockup-tranched/createWithDurations.t.sol index 6a1468668..2a50e7a21 100644 --- a/test/integration/fuzz/lockup-tranched/createWithDurations.t.sol +++ b/test/integration/fuzz/lockup-tranched/createWithDurations.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; -import { CreateWithDurations_Integration_Shared_Test } from "../../shared/lockup-tranched/createWithDurations.t.sol"; +import { CreateWithDurations_Integration_Shared_Test } from "../../shared/lockup/createWithDurations.t.sol"; import { LockupTranched_Integration_Fuzz_Test } from "./LockupTranched.t.sol"; contract CreateWithDurations_LockupTranched_Integration_Fuzz_Test is @@ -105,9 +105,9 @@ contract CreateWithDurations_LockupTranched_Integration_Fuzz_Test is assertEq(actualStream.asset, dai, "asset"); assertEq(actualStream.endTime, range.end, "endTime"); assertEq(actualStream.isCancelable, vars.isCancelable, "isCancelable"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isDepleted, false, "isDepleted"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.tranches, vars.tranchesWithTimestamps, "tranches"); assertEq(actualStream.sender, users.sender, "sender"); @@ -119,7 +119,7 @@ contract CreateWithDurations_LockupTranched_Integration_Fuzz_Test is vars.expectedStatus = vars.isSettled ? Lockup.Status.SETTLED : Lockup.Status.STREAMING; assertEq(vars.actualStatus, vars.expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupTranched.nextStreamId(); vars.expectedNextStreamId = streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/fuzz/lockup-tranched/createWithTimestamps.t.sol b/test/integration/fuzz/lockup-tranched/createWithTimestamps.t.sol index 251bbf1e7..a81214e25 100644 --- a/test/integration/fuzz/lockup-tranched/createWithTimestamps.t.sol +++ b/test/integration/fuzz/lockup-tranched/createWithTimestamps.t.sol @@ -7,7 +7,7 @@ import { stdError } from "forge-std/src/StdError.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Broker, Lockup, LockupTranched } from "src/types/DataTypes.sol"; -import { CreateWithTimestamps_Integration_Shared_Test } from "../../shared/lockup-tranched/createWithTimestamps.t.sol"; +import { CreateWithTimestamps_Integration_Shared_Test } from "../../shared/lockup/createWithTimestamps.t.sol"; import { LockupTranched_Integration_Fuzz_Test } from "./LockupTranched.t.sol"; contract CreateWithTimestamps_LockupTranched_Integration_Fuzz_Test is @@ -30,7 +30,8 @@ contract CreateWithTimestamps_LockupTranched_Integration_Fuzz_Test is whenDepositAmountNotZero whenTrancheCountNotZero { - trancheCount = _bound(trancheCount, defaults.MAX_COUNT() + 1 seconds, defaults.MAX_COUNT() * 10); + uint256 defaultMax = defaults.MAX_TRANCHE_COUNT(); + trancheCount = _bound(trancheCount, defaultMax + 1, defaultMax * 10); LockupTranched.Tranche[] memory tranches = new LockupTranched.Tranche[](trancheCount); vm.expectRevert( abi.encodeWithSelector(Errors.SablierV2LockupTranched_TrancheCountTooHigh.selector, trancheCount) @@ -270,9 +271,9 @@ contract CreateWithTimestamps_LockupTranched_Integration_Fuzz_Test is assertEq(actualStream.asset, dai, "asset"); assertEq(actualStream.endTime, range.end, "endTime"); assertEq(actualStream.isCancelable, vars.isCancelable, "isCancelable"); - assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.isDepleted, false, "isStream"); assertEq(actualStream.isStream, true, "isStream"); + assertEq(actualStream.isTransferable, true, "isTransferable"); assertEq(actualStream.recipient, params.recipient, "recipient"); assertEq(actualStream.sender, params.sender, "sender"); assertEq(actualStream.tranches, params.tranches, "tranches"); @@ -290,7 +291,7 @@ contract CreateWithTimestamps_LockupTranched_Integration_Fuzz_Test is } assertEq(vars.actualStatus, vars.expectedStatus); - // Assert that the next stream id has been bumped. + // Assert that the next stream ID has been bumped. vars.actualNextStreamId = lockupTranched.nextStreamId(); vars.expectedNextStreamId = streamId + 1; assertEq(vars.actualNextStreamId, vars.expectedNextStreamId, "nextStreamId"); diff --git a/test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol b/test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol index 35ab45655..29c105b53 100644 --- a/test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol +++ b/test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol @@ -74,12 +74,12 @@ contract StreamedAmountOf_LockupTranched_Integration_Fuzz_Test is uint256 streamId = lockupTranched.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualStreamedAmount = lockupTranched.streamedAmountOf(streamId); - uint128 expectedStreamedAmount = calculateStreamedAmountForTranches(currentTime, tranches, totalAmount); + uint128 expectedStreamedAmount = calculateStreamedAmountForTranches(blockTimestamp, tranches, totalAmount); assertEq(actualStreamedAmount, expectedStreamedAmount, "streamedAmount"); } diff --git a/test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol b/test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol index 35d86f64c..407414ba6 100644 --- a/test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol +++ b/test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol @@ -45,13 +45,13 @@ contract WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test is uint256 streamId = lockupTranched.createWithTimestamps(params); // Simulate the passage of time. - uint40 currentTime = defaults.START_TIME() + timeJump; - vm.warp({ newTimestamp: currentTime }); + uint40 blockTimestamp = defaults.START_TIME() + timeJump; + vm.warp({ newTimestamp: blockTimestamp }); // Run the test. uint128 actualWithdrawableAmount = lockupTranched.withdrawableAmountOf(streamId); uint128 expectedWithdrawableAmount = - calculateStreamedAmountForTranches(currentTime, defaults.tranches(), defaults.DEPOSIT_AMOUNT()); + calculateStreamedAmountForTranches(blockTimestamp, defaults.tranches(), defaults.DEPOSIT_AMOUNT()); assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawableAmount"); } @@ -79,12 +79,12 @@ contract WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test is { timeJump = boundUint40(timeJump, defaults.CLIFF_DURATION(), defaults.TOTAL_DURATION() * 2); - // Define the current time. - uint40 currentTime = defaults.START_TIME() + timeJump; + // Define the block timestamp. + uint40 blockTimestamp = defaults.START_TIME() + timeJump; // Bound the withdraw amount. uint128 streamedAmount = - calculateStreamedAmountForTranches(currentTime, defaults.tranches(), defaults.DEPOSIT_AMOUNT()); + calculateStreamedAmountForTranches(blockTimestamp, defaults.tranches(), defaults.DEPOSIT_AMOUNT()); withdrawAmount = boundUint128(withdrawAmount, 1, streamedAmount); // Create the stream with a custom total amount. The broker fee is disabled so that it doesn't interfere with @@ -95,7 +95,7 @@ contract WithdrawableAmountOf_LockupTranched_Integration_Fuzz_Test is uint256 streamId = lockupTranched.createWithTimestamps(params); // Simulate the passage of time. - vm.warp({ newTimestamp: currentTime }); + vm.warp({ newTimestamp: blockTimestamp }); // Make the withdrawal. lockupTranched.withdraw({ streamId: streamId, to: users.recipient, amount: withdrawAmount }); diff --git a/test/integration/fuzz/lockup/cancel.t.sol b/test/integration/fuzz/lockup/cancel.t.sol index c4188c082..3597ba4bb 100644 --- a/test/integration/fuzz/lockup/cancel.t.sol +++ b/test/integration/fuzz/lockup/cancel.t.sol @@ -39,7 +39,7 @@ abstract contract Cancel_Integration_Fuzz_Test is Integration_Test, Cancel_Integ /// @dev Given enough fuzz runs, all of the following scenarios will be fuzzed: /// - /// - Multiple values for the current time + /// - Multiple values for the block timestamp /// - With and without withdrawals function testFuzz_Cancel( uint256 timeJump, diff --git a/test/integration/fuzz/lockup/cancelMultiple.t.sol b/test/integration/fuzz/lockup/cancelMultiple.t.sol index aac5f1d6c..eac94ed5c 100644 --- a/test/integration/fuzz/lockup/cancelMultiple.t.sol +++ b/test/integration/fuzz/lockup/cancelMultiple.t.sol @@ -33,7 +33,7 @@ abstract contract CancelMultiple_Integration_Fuzz_Test is Integration_Test, Canc // Simulate the passage of time. vm.warp({ newTimestamp: defaults.START_TIME() + timeJump }); - // Create the stream ids array. + // Create the stream IDs array. uint256[] memory streamIds = Solarray.uint256s(testStreamIds[0], streamId); // Expect the assets to be refunded to the Sender. diff --git a/test/integration/fuzz/lockup/withdraw.t.sol b/test/integration/fuzz/lockup/withdraw.t.sol index fd4dbecd9..a5b6d5618 100644 --- a/test/integration/fuzz/lockup/withdraw.t.sol +++ b/test/integration/fuzz/lockup/withdraw.t.sol @@ -83,7 +83,7 @@ abstract contract Withdraw_Integration_Fuzz_Test is Integration_Test, Withdraw_I /// @dev Given enough fuzz runs, all of the following scenarios will be fuzzed: /// - /// - Multiple values for the current time. + /// - Multiple values for the block timestamp. /// - Multiple values for the withdrawal address. /// - Multiple withdraw amounts. function testFuzz_Withdraw_StreamHasBeenCanceled( diff --git a/test/integration/shared/lockup-dynamic/LockupDynamic.t.sol b/test/integration/shared/lockup-dynamic/LockupDynamic.t.sol index 08ee66844..f5809e894 100644 --- a/test/integration/shared/lockup-dynamic/LockupDynamic.t.sol +++ b/test/integration/shared/lockup-dynamic/LockupDynamic.t.sol @@ -47,19 +47,19 @@ abstract contract LockupDynamic_Integration_Shared_Test is Lockup_Integration_Sh } } - /// @dev Creates the default stream. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStream() internal override returns (uint256 streamId) { streamId = lockupDynamic.createWithTimestamps(_params.createWithTimestamps); } - /// @dev Creates the default stream with the provided asset. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithAsset(IERC20 asset) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.asset = asset; streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided broker. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithBroker(Broker memory broker) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.broker = broker; @@ -81,21 +81,21 @@ abstract contract LockupDynamic_Integration_Shared_Test is Lockup_Integration_Sh streamId = lockupDynamic.createWithDurations(params); } - /// @dev Creates the default stream with the provided end time. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithEndTime(uint40 endTime) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.segments[1].timestamp = endTime; streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates a stream that will not be cancelable. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamNotCancelable() internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.cancelable = false; streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the NFT transfer disabled. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamNotTransferable() internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.transferable = false; @@ -110,7 +110,7 @@ abstract contract LockupDynamic_Integration_Shared_Test is Lockup_Integration_Sh streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided recipient. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithRecipient(address recipient) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.recipient = recipient; @@ -127,28 +127,28 @@ abstract contract LockupDynamic_Integration_Shared_Test is Lockup_Integration_Sh streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided sender. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithSender(address sender) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.sender = sender; streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided start time.. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithStartTime(uint40 startTime) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.startTime = startTime; streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided total amount. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithTotalAmount(uint128 totalAmount) internal override returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; params.totalAmount = totalAmount; streamId = lockupDynamic.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided sender and recipient. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithUsers( address recipient, address sender @@ -158,8 +158,8 @@ abstract contract LockupDynamic_Integration_Shared_Test is Lockup_Integration_Sh returns (uint256 streamId) { LockupDynamic.CreateWithTimestamps memory params = _params.createWithTimestamps; - params.sender = sender; params.recipient = recipient; + params.sender = sender; streamId = lockupDynamic.createWithTimestamps(params); } } diff --git a/test/integration/shared/lockup-dynamic/createWithTimestamps.t.sol b/test/integration/shared/lockup-dynamic/createWithTimestamps.t.sol deleted file mode 100644 index b9a7a5fd2..000000000 --- a/test/integration/shared/lockup-dynamic/createWithTimestamps.t.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { LockupDynamic_Integration_Shared_Test } from "./LockupDynamic.t.sol"; - -contract CreateWithTimestamps_Integration_Shared_Test is LockupDynamic_Integration_Shared_Test { - uint256 internal streamId; - - function setUp() public virtual override { - streamId = lockupDynamic.nextStreamId(); - } - - modifier whenNotDelegateCalled() { - _; - } - - modifier whenRecipientNonZeroAddress() { - _; - } - - modifier whenDepositAmountNotZero() { - _; - } - - modifier whenStartTimeNotZero() { - _; - } - - modifier whenSegmentCountNotZero() { - _; - } - - modifier whenSegmentCountNotTooHigh() { - _; - } - - modifier whenSegmentAmountsSumDoesNotOverflow() { - _; - } - - modifier whenStartTimeLessThanFirstSegmentTimestamp() { - _; - } - - modifier whenSegmentTimestampsOrdered() { - _; - } - - modifier whenEndTimeInTheFuture() { - _; - } - - modifier whenDepositAmountEqualToSegmentAmountsSum() { - _; - } - - modifier whenBrokerFeeNotTooHigh() { - _; - } - - modifier whenAssetContract() { - _; - } - - modifier whenAssetERC20() { - _; - } -} diff --git a/test/integration/shared/lockup-linear/LockupLinear.t.sol b/test/integration/shared/lockup-linear/LockupLinear.t.sol index eed455052..0dd6b92ee 100644 --- a/test/integration/shared/lockup-linear/LockupLinear.t.sol +++ b/test/integration/shared/lockup-linear/LockupLinear.t.sol @@ -24,19 +24,19 @@ abstract contract LockupLinear_Integration_Shared_Test is Lockup_Integration_Sha _params.createWithTimestamps = defaults.createWithTimestampsLL(); } - /// @dev Creates the default stream. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStream() internal override returns (uint256 streamId) { streamId = lockupLinear.createWithTimestamps(_params.createWithTimestamps); } - /// @dev Creates the default stream with the provided address. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithAsset(IERC20 asset) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.asset = asset; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided broker. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithBroker(Broker memory broker) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.broker = broker; @@ -58,21 +58,21 @@ abstract contract LockupLinear_Integration_Shared_Test is Lockup_Integration_Sha streamId = lockupLinear.createWithDurations(params); } - /// @dev Creates the default stream that is not cancelable. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamNotCancelable() internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.cancelable = false; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the NFT transfer disabled. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamNotTransferable() internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.transferable = false; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided end time. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithEndTime(uint40 endTime) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.range.end = endTime; @@ -86,35 +86,35 @@ abstract contract LockupLinear_Integration_Shared_Test is Lockup_Integration_Sha streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided recipient. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithRecipient(address recipient) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.recipient = recipient; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided sender. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithSender(address sender) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.sender = sender; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided start time. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithStartTime(uint40 startTime) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.range.start = startTime; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided total amount. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithTotalAmount(uint128 totalAmount) internal override returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; params.totalAmount = totalAmount; streamId = lockupLinear.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided sender and recipient. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithUsers( address recipient, address sender @@ -124,8 +124,8 @@ abstract contract LockupLinear_Integration_Shared_Test is Lockup_Integration_Sha returns (uint256 streamId) { LockupLinear.CreateWithTimestamps memory params = _params.createWithTimestamps; - params.sender = sender; params.recipient = recipient; + params.sender = sender; streamId = lockupLinear.createWithTimestamps(params); } } diff --git a/test/integration/shared/lockup-linear/createWithDurations.t.sol b/test/integration/shared/lockup-linear/createWithDurations.t.sol deleted file mode 100644 index f851e18e1..000000000 --- a/test/integration/shared/lockup-linear/createWithDurations.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { LockupLinear_Integration_Shared_Test } from "./LockupLinear.t.sol"; - -contract CreateWithDurations_Integration_Shared_Test is LockupLinear_Integration_Shared_Test { - uint256 internal streamId; - - function setUp() public virtual override { - streamId = lockupLinear.nextStreamId(); - } - - modifier whenNotDelegateCalled() { - _; - } - - modifier whenCliffDurationCalculationDoesNotOverflow() { - _; - } - - modifier whenTotalDurationCalculationDoesNotOverflow() { - _; - } -} diff --git a/test/integration/shared/lockup-linear/createWithTimestamps.t.sol b/test/integration/shared/lockup-linear/createWithTimestamps.t.sol deleted file mode 100644 index 09975a86c..000000000 --- a/test/integration/shared/lockup-linear/createWithTimestamps.t.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { LockupLinear_Integration_Shared_Test } from "./LockupLinear.t.sol"; - -abstract contract CreateWithTimestamps_Integration_Shared_Test is LockupLinear_Integration_Shared_Test { - uint256 internal streamId; - - function setUp() public virtual override { - streamId = lockupLinear.nextStreamId(); - } - - modifier whenNotDelegateCalled() { - _; - } - - modifier whenRecipientNonZeroAddress() { - _; - } - - modifier whenDepositAmountNotZero() { - _; - } - - modifier whenStartTimeNotZero() { - _; - } - - modifier whenStartTimeNotGreaterThanCliffTime() { - _; - } - - modifier whenCliffTimeLessThanEndTime() { - _; - } - - modifier whenEndTimeInTheFuture() { - _; - } - - modifier whenBrokerFeeNotTooHigh() { - _; - } - - modifier whenAssetContract() { - _; - } - - modifier whenAssetERC20() { - _; - } -} diff --git a/test/integration/shared/lockup-tranched/LockupTranched.t.sol b/test/integration/shared/lockup-tranched/LockupTranched.t.sol index e9413d848..73d97ec2f 100644 --- a/test/integration/shared/lockup-tranched/LockupTranched.t.sol +++ b/test/integration/shared/lockup-tranched/LockupTranched.t.sol @@ -52,14 +52,14 @@ abstract contract LockupTranched_Integration_Shared_Test is Lockup_Integration_S streamId = lockupTranched.createWithTimestamps(_params.createWithTimestamps); } - /// @dev Creates the default stream with the provided asset. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithAsset(IERC20 asset) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.asset = asset; streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided broker. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithBroker(Broker memory broker) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.broker = broker; @@ -81,7 +81,7 @@ abstract contract LockupTranched_Integration_Shared_Test is Lockup_Integration_S streamId = lockupTranched.createWithDurations(params); } - /// @dev Creates the default stream with the provided end time. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithEndTime(uint40 endTime) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.tranches[2].timestamp = endTime; @@ -97,14 +97,14 @@ abstract contract LockupTranched_Integration_Shared_Test is Lockup_Integration_S streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates a stream that will not be cancelable. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamNotCancelable() internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.cancelable = false; streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the NFT transfer disabled. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamNotTransferable() internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.transferable = false; @@ -119,7 +119,7 @@ abstract contract LockupTranched_Integration_Shared_Test is Lockup_Integration_S streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided recipient. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithRecipient(address recipient) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.recipient = recipient; @@ -136,28 +136,28 @@ abstract contract LockupTranched_Integration_Shared_Test is Lockup_Integration_S streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided sender. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithSender(address sender) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.sender = sender; streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided start time.. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithStartTime(uint40 startTime) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.startTime = startTime; streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided total amount. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithTotalAmount(uint128 totalAmount) internal override returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; params.totalAmount = totalAmount; streamId = lockupTranched.createWithTimestamps(params); } - /// @dev Creates the default stream with the provided sender and recipient. + /// @inheritdoc Lockup_Integration_Shared_Test function createDefaultStreamWithUsers( address recipient, address sender @@ -167,8 +167,8 @@ abstract contract LockupTranched_Integration_Shared_Test is Lockup_Integration_S returns (uint256 streamId) { LockupTranched.CreateWithTimestamps memory params = _params.createWithTimestamps; - params.sender = sender; params.recipient = recipient; + params.sender = sender; streamId = lockupTranched.createWithTimestamps(params); } } diff --git a/test/integration/shared/lockup-tranched/createWithDurations.t.sol b/test/integration/shared/lockup-tranched/createWithDurations.t.sol deleted file mode 100644 index ec4609379..000000000 --- a/test/integration/shared/lockup-tranched/createWithDurations.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { LockupTranched_Integration_Shared_Test } from "./LockupTranched.t.sol"; - -contract CreateWithDurations_Integration_Shared_Test is LockupTranched_Integration_Shared_Test { - uint256 internal streamId; - - function setUp() public virtual override { - streamId = lockupTranched.nextStreamId(); - } - - modifier whenNotDelegateCalled() { - _; - } - - modifier whenLoopCalculationsDoNotOverflowBlockGasLimit() { - _; - } - - modifier whenDurationsNotZero() { - _; - } - - modifier whenTimestampsCalculationsDoNotOverflow() { - _; - } -} diff --git a/test/integration/shared/lockup/Lockup.t.sol b/test/integration/shared/lockup/Lockup.t.sol index 6ee2a4d8e..b7da0ea18 100644 --- a/test/integration/shared/lockup/Lockup.t.sol +++ b/test/integration/shared/lockup/Lockup.t.sol @@ -41,11 +41,6 @@ abstract contract Lockup_Integration_Shared_Test is Base_Test { /// @dev Creates the default stream with the NFT transfer disabled. function createDefaultStreamNotTransferable() internal virtual returns (uint256 streamId); - /// @dev Creates the default stream with recipient as the sender. - function createDefaultStreamToSender(address sender) internal virtual returns (uint256 streamId) { - return createDefaultStreamWithUsers(sender, sender); - } - /// @dev Creates the default stream with the provided address. function createDefaultStreamWithAsset(IERC20 asset) internal virtual returns (uint256 streamId); @@ -55,6 +50,11 @@ abstract contract Lockup_Integration_Shared_Test is Base_Test { /// @dev Creates the default stream with the provided end time. function createDefaultStreamWithEndTime(uint40 endTime) internal virtual returns (uint256 streamId); + /// @dev Creates the default stream with the provided user as the recipient and the sender. + function createDefaultStreamWithIdenticalUsers(address user) internal virtual returns (uint256 streamId) { + return createDefaultStreamWithUsers({ recipient: user, sender: user }); + } + /// @dev Creates the default stream with the provided recipient. function createDefaultStreamWithRecipient(address recipient) internal virtual returns (uint256 streamId); diff --git a/test/integration/shared/lockup-dynamic/createWithDurations.t.sol b/test/integration/shared/lockup/createWithDurations.t.sol similarity index 54% rename from test/integration/shared/lockup-dynamic/createWithDurations.t.sol rename to test/integration/shared/lockup/createWithDurations.t.sol index 31460ec2b..8446dc2c3 100644 --- a/test/integration/shared/lockup-dynamic/createWithDurations.t.sol +++ b/test/integration/shared/lockup/createWithDurations.t.sol @@ -1,16 +1,20 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { LockupDynamic_Integration_Shared_Test } from "./LockupDynamic.t.sol"; +import { Lockup_Integration_Shared_Test } from "./Lockup.t.sol"; -contract CreateWithDurations_Integration_Shared_Test is LockupDynamic_Integration_Shared_Test { +abstract contract CreateWithDurations_Integration_Shared_Test is Lockup_Integration_Shared_Test { uint256 internal streamId; function setUp() public virtual override { - streamId = lockupDynamic.nextStreamId(); + streamId = lockup.nextStreamId(); } - modifier whenNotDelegateCalled() { + modifier whenCliffDurationCalculationDoesNotOverflow() { + _; + } + + modifier whenDurationsNotZero() { _; } @@ -18,11 +22,15 @@ contract CreateWithDurations_Integration_Shared_Test is LockupDynamic_Integratio _; } - modifier whenDurationsNotZero() { + modifier whenNotDelegateCalled() { _; } modifier whenTimestampsCalculationsDoNotOverflow() { _; } + + modifier whenTotalDurationCalculationDoesNotOverflow() { + _; + } } diff --git a/test/integration/shared/lockup-tranched/createWithTimestamps.t.sol b/test/integration/shared/lockup/createWithTimestamps.t.sol similarity index 54% rename from test/integration/shared/lockup-tranched/createWithTimestamps.t.sol rename to test/integration/shared/lockup/createWithTimestamps.t.sol index 854d97960..252104613 100644 --- a/test/integration/shared/lockup-tranched/createWithTimestamps.t.sol +++ b/test/integration/shared/lockup/createWithTimestamps.t.sol @@ -1,13 +1,53 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { LockupTranched_Integration_Shared_Test } from "./LockupTranched.t.sol"; +import { Lockup_Integration_Shared_Test } from "./Lockup.t.sol"; -contract CreateWithTimestamps_Integration_Shared_Test is LockupTranched_Integration_Shared_Test { +abstract contract CreateWithTimestamps_Integration_Shared_Test is Lockup_Integration_Shared_Test { uint256 internal streamId; function setUp() public virtual override { - streamId = lockupTranched.nextStreamId(); + streamId = lockup.nextStreamId(); + } + + modifier whenAssetContract() { + _; + } + + modifier whenAssetERC20() { + _; + } + + modifier whenBrokerFeeNotTooHigh() { + _; + } + + modifier whenCliffTimeGreaterThanZero() { + _; + } + + modifier whenCliffTimeLessThanEndTime() { + _; + } + + modifier whenCliffTimeZero() { + _; + } + + modifier whenDepositAmountEqualToSegmentAmountsSum() { + _; + } + + modifier whenDepositAmountEqualToTrancheAmountsSum() { + _; + } + + modifier whenDepositAmountNotZero() { + _; + } + + modifier whenEndTimeInTheFuture() { + _; } modifier whenNotDelegateCalled() { @@ -18,51 +58,51 @@ contract CreateWithTimestamps_Integration_Shared_Test is LockupTranched_Integrat _; } - modifier whenDepositAmountNotZero() { + modifier whenSegmentAmountsSumDoesNotOverflow() { _; } - modifier whenStartTimeNotZero() { + modifier whenSegmentCountNotTooHigh() { _; } - modifier whenTrancheCountNotZero() { + modifier whenSegmentCountNotZero() { _; } - modifier whenTrancheCountNotTooHigh() { + modifier whenSegmentTimestampsOrdered() { _; } - modifier whenTrancheAmountsSumDoesNotOverflow() { + modifier whenStartTimeLessThanEndTime() { _; } - modifier whenStartTimeLessThanFirstTrancheTimestamp() { + modifier whenStartTimeLessThanFirstSegmentTimestamp() { _; } - modifier whenTrancheTimestampsOrdered() { + modifier whenStartTimeLessThanFirstTrancheTimestamp() { _; } - modifier whenEndTimeInTheFuture() { + modifier whenStartTimeNotZero() { _; } - modifier whenDepositAmountEqualToTrancheAmountsSum() { + modifier whenTrancheAmountsSumDoesNotOverflow() { _; } - modifier whenBrokerFeeNotTooHigh() { + modifier whenTrancheCountNotTooHigh() { _; } - modifier whenAssetContract() { + modifier whenTrancheCountNotZero() { _; } - modifier whenAssetERC20() { + modifier whenTrancheTimestampsOrdered() { _; } } diff --git a/test/invariant/Lockup.t.sol b/test/invariant/Lockup.t.sol index bf44eabb5..c6fb7d62c 100644 --- a/test/invariant/Lockup.t.sol +++ b/test/invariant/Lockup.t.sol @@ -120,7 +120,7 @@ abstract contract Lockup_Invariant_Test is Invariant_Test { uint256 lastStreamId = lockupStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { uint256 nextStreamId = lockup.nextStreamId(); - assertEq(nextStreamId, lastStreamId + 1, "Invariant violation: next stream id not incremented"); + assertEq(nextStreamId, lastStreamId + 1, "Invariant violation: next stream ID not incremented"); } } diff --git a/test/invariant/LockupLinear.t.sol b/test/invariant/LockupLinear.t.sol index 6c76c8d29..17bdd4ab3 100644 --- a/test/invariant/LockupLinear.t.sol +++ b/test/invariant/LockupLinear.t.sol @@ -58,7 +58,7 @@ contract LockupLinear_Invariant_Test is Lockup_Invariant_Test { INVARIANTS //////////////////////////////////////////////////////////////////////////*/ - /// @dev The cliff time must be greater than the start time, if it is not zero. + /// @dev If it is not zero, the cliff time must be strictly greater than the start time. function invariant_CliffTimeGtStartTimeOrZero() external useCurrentTimestamp { uint256 lastStreamId = lockupStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { diff --git a/test/invariant/handlers/LockupDynamicCreateHandler.sol b/test/invariant/handlers/LockupDynamicCreateHandler.sol index 4cd0f7d7f..d918403f0 100644 --- a/test/invariant/handlers/LockupDynamicCreateHandler.sol +++ b/test/invariant/handlers/LockupDynamicCreateHandler.sol @@ -84,7 +84,7 @@ contract LockupDynamicCreateHandler is BaseHandler { params.asset = asset; uint256 streamId = lockupDynamic.createWithDurations(params); - // Store the stream id. + // Store the stream ID. lockupStore.pushStreamId(streamId, params.sender, params.recipient); } @@ -131,7 +131,7 @@ contract LockupDynamicCreateHandler is BaseHandler { params.asset = asset; uint256 streamId = lockupDynamic.createWithTimestamps(params); - // Store the stream id. + // Store the stream ID. lockupStore.pushStreamId(streamId, params.sender, params.recipient); } } diff --git a/test/invariant/handlers/LockupDynamicHandler.sol b/test/invariant/handlers/LockupDynamicHandler.sol index b18945add..29ec97aa8 100644 --- a/test/invariant/handlers/LockupDynamicHandler.sol +++ b/test/invariant/handlers/LockupDynamicHandler.sol @@ -9,7 +9,7 @@ import { LockupStore } from "../stores/LockupStore.sol"; import { TimestampStore } from "../stores/TimestampStore.sol"; import { LockupHandler } from "./LockupHandler.sol"; -/// @dev This contract and not {SablierV2LockupDynamic} is exposed to Foundry for invariant testing. The point is +/// @dev This contract and not {SablierV2LockupDynamic} is exposed to Foundry for invariant testing. The goal is /// to bound and restrict the inputs that get passed to the real-world contract to avoid getting reverts. contract LockupDynamicHandler is LockupHandler { constructor( diff --git a/test/invariant/handlers/LockupHandler.sol b/test/invariant/handlers/LockupHandler.sol index f137b6f39..dcb145f3c 100644 --- a/test/invariant/handlers/LockupHandler.sol +++ b/test/invariant/handlers/LockupHandler.sol @@ -283,7 +283,7 @@ abstract contract LockupHandler is BaseHandler { // Make the max withdrawal and transfer the NFT. lockup.withdrawMaxAndTransfer({ streamId: currentStreamId, newRecipient: newRecipient }); - // Update the recipient associated with this stream id. + // Update the recipient associated with this stream ID. lockupStore.updateRecipient(currentStreamId, newRecipient); } @@ -320,7 +320,7 @@ abstract contract LockupHandler is BaseHandler { // Transfer the NFT to the new recipient. lockup.transferFrom({ from: currentRecipient, to: newRecipient, tokenId: currentStreamId }); - // Update the recipient associated with this stream id. + // Update the recipient associated with this stream ID. lockupStore.updateRecipient(currentStreamId, newRecipient); } } diff --git a/test/invariant/handlers/LockupLinearCreateHandler.sol b/test/invariant/handlers/LockupLinearCreateHandler.sol index cc6b7b498..ff8e3ac4f 100644 --- a/test/invariant/handlers/LockupLinearCreateHandler.sol +++ b/test/invariant/handlers/LockupLinearCreateHandler.sol @@ -73,7 +73,7 @@ contract LockupLinearCreateHandler is BaseHandler { params.asset = asset; uint256 streamId = lockupLinear.createWithDurations(params); - // Store the stream id. + // Store the stream ID. lockupStore.pushStreamId(streamId, params.sender, params.recipient); } @@ -92,19 +92,20 @@ contract LockupLinearCreateHandler is BaseHandler { return; } - uint40 currentTime = getBlockTimestamp(); + uint40 blockTimestamp = getBlockTimestamp(); params.broker.fee = _bound(params.broker.fee, 0, MAX_BROKER_FEE); - params.range.start = boundUint40(params.range.start, 1, currentTime); - params.range.cliff = boundUint40(params.range.cliff, params.range.start + 1, params.range.start + 52 weeks); + params.range.start = boundUint40(params.range.start, 1 seconds, blockTimestamp); params.totalAmount = boundUint128(params.totalAmount, 1, 1_000_000_000e18); - // Bound the end time so that it is always greater than both the current time and the cliff time (this is - // a requirement of the protocol). - params.range.end = boundUint40( - params.range.end, - (params.range.cliff <= currentTime ? currentTime : params.range.cliff) + 1 seconds, - MAX_UNIX_TIMESTAMP - ); + // The cliff time must be either zero or greater than the start time. + if (params.range.cliff > 0) { + params.range.cliff = + boundUint40(params.range.cliff, params.range.start + 1 seconds, params.range.start + 52 weeks); + } + + // Bound the end time so that it is always greater than the start time, the cliff time, and the block timestamp. + uint40 endTimeLowerBound = maxOfThree(params.range.start, params.range.cliff, blockTimestamp); + params.range.end = boundUint40(params.range.end, endTimeLowerBound + 1 seconds, MAX_UNIX_TIMESTAMP); // Mint enough assets to the Sender. deal({ token: address(asset), to: params.sender, give: asset.balanceOf(params.sender) + params.totalAmount }); @@ -116,7 +117,7 @@ contract LockupLinearCreateHandler is BaseHandler { params.asset = asset; uint256 streamId = lockupLinear.createWithTimestamps(params); - // Store the stream id. + // Store the stream ID. lockupStore.pushStreamId(streamId, params.sender, params.recipient); } } diff --git a/test/invariant/handlers/LockupLinearHandler.sol b/test/invariant/handlers/LockupLinearHandler.sol index 83bca10e4..f27fafccd 100644 --- a/test/invariant/handlers/LockupLinearHandler.sol +++ b/test/invariant/handlers/LockupLinearHandler.sol @@ -9,7 +9,7 @@ import { LockupStore } from "../stores/LockupStore.sol"; import { TimestampStore } from "../stores/TimestampStore.sol"; import { LockupHandler } from "./LockupHandler.sol"; -/// @dev This contract and not {SablierV2LockupLinear} is exposed to Foundry for invariant testing. The point is +/// @dev This contract and not {SablierV2LockupLinear} is exposed to Foundry for invariant testing. The goal is /// to bound and restrict the inputs that get passed to the real-world contract to avoid getting reverts. contract LockupLinearHandler is LockupHandler { constructor( diff --git a/test/invariant/handlers/LockupTranchedCreateHandler.sol b/test/invariant/handlers/LockupTranchedCreateHandler.sol index 6661a7863..8a292be82 100644 --- a/test/invariant/handlers/LockupTranchedCreateHandler.sol +++ b/test/invariant/handlers/LockupTranchedCreateHandler.sol @@ -84,7 +84,7 @@ contract LockupTranchedCreateHandler is BaseHandler { params.asset = asset; uint256 streamId = lockupTranched.createWithDurations(params); - // Store the stream id. + // Store the stream ID. lockupStore.pushStreamId(streamId, params.sender, params.recipient); } @@ -131,7 +131,7 @@ contract LockupTranchedCreateHandler is BaseHandler { params.asset = asset; uint256 streamId = lockupTranched.createWithTimestamps(params); - // Store the stream id. + // Store the stream ID. lockupStore.pushStreamId(streamId, params.sender, params.recipient); } } diff --git a/test/invariant/handlers/LockupTranchedHandler.sol b/test/invariant/handlers/LockupTranchedHandler.sol index ab62a23fa..9194168e6 100644 --- a/test/invariant/handlers/LockupTranchedHandler.sol +++ b/test/invariant/handlers/LockupTranchedHandler.sol @@ -9,7 +9,7 @@ import { LockupStore } from "../stores/LockupStore.sol"; import { TimestampStore } from "../stores/TimestampStore.sol"; import { LockupHandler } from "./LockupHandler.sol"; -/// @dev This contract and not {SablierV2LockupTranched} is exposed to Foundry for invariant testing. The point is +/// @dev This contract and not {SablierV2LockupTranched} is exposed to Foundry for invariant testing. The goal is /// to bound and restrict the inputs that get passed to the real-world contract to avoid getting reverts. contract LockupTranchedHandler is LockupHandler { constructor( diff --git a/test/invariant/stores/LockupStore.sol b/test/invariant/stores/LockupStore.sol index f74d5d0c7..0314ac96a 100644 --- a/test/invariant/stores/LockupStore.sol +++ b/test/invariant/stores/LockupStore.sol @@ -21,12 +21,12 @@ contract LockupStore { //////////////////////////////////////////////////////////////////////////*/ function pushStreamId(uint256 streamId, address sender, address recipient) external { - // Store the stream ids, the senders, and the recipients. + // Store the stream IDs, the senders, and the recipients. streamIds.push(streamId); senders[streamId] = sender; recipients[streamId] = recipient; - // Update the last stream id. + // Update the last stream ID. lastStreamId = streamId; } diff --git a/test/mocks/NFTDescriptorMock.sol b/test/mocks/NFTDescriptorMock.sol index 47bcf5aee..adac6ec55 100644 --- a/test/mocks/NFTDescriptorMock.sol +++ b/test/mocks/NFTDescriptorMock.sol @@ -52,7 +52,7 @@ contract NFTDescriptorMock is SablierV2NFTDescriptor { } function generateDescription_( - string memory streamingModel, + string memory sablierModel, string memory assetSymbol, string memory sablierAddress, string memory assetAddress, @@ -63,18 +63,11 @@ contract NFTDescriptorMock is SablierV2NFTDescriptor { pure returns (string memory) { - return generateDescription(streamingModel, assetSymbol, sablierAddress, assetAddress, streamId, isTransferable); + return generateDescription(sablierModel, assetSymbol, sablierAddress, assetAddress, streamId, isTransferable); } - function generateName_( - string memory streamingModel, - string memory streamId - ) - external - pure - returns (string memory) - { - return generateName(streamingModel, streamId); + function generateName_(string memory sablierModel, string memory streamId) external pure returns (string memory) { + return generateName(sablierModel, streamId); } function generateSVG_(NFTSVG.SVGParams memory params) external pure returns (string memory) { diff --git a/test/mocks/Noop.sol b/test/mocks/Noop.sol index 9b46e3a14..8f441ef3e 100644 --- a/test/mocks/Noop.sol +++ b/test/mocks/Noop.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; /// @dev This contract does nothing (no-op = no operation). diff --git a/test/mocks/erc721/ERC721Mock.sol b/test/mocks/erc721/ERC721Mock.sol deleted file mode 100644 index 004190ba6..000000000 --- a/test/mocks/erc721/ERC721Mock.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; - -contract ERC721Mock is ERC721 { - constructor(string memory name, string memory symbol) ERC721(name, symbol) { } -} diff --git a/test/unit/concrete/nft-descriptor/generateName.t.sol b/test/unit/concrete/nft-descriptor/generateName.t.sol index b65208ac8..3efedc0e5 100644 --- a/test/unit/concrete/nft-descriptor/generateName.t.sol +++ b/test/unit/concrete/nft-descriptor/generateName.t.sol @@ -4,8 +4,8 @@ pragma solidity >=0.8.22 <0.9.0; import { NFTDescriptor_Unit_Concrete_Test } from "./NFTDescriptor.t.sol"; contract GenerateName_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_Test { - function gn(string memory streamingModel, string memory streamId) internal view returns (string memory) { - return nftDescriptorMock.generateName_(streamingModel, streamId); + function gn(string memory sablierModel, string memory streamId) internal view returns (string memory) { + return nftDescriptorMock.generateName_(sablierModel, streamId); } function dyn(string memory streamId) internal pure returns (string memory) { diff --git a/test/unit/concrete/nft-descriptor/generateSVG.t.sol b/test/unit/concrete/nft-descriptor/generateSVG.t.sol index 8322a26ed..290a4c802 100644 --- a/test/unit/concrete/nft-descriptor/generateSVG.t.sol +++ b/test/unit/concrete/nft-descriptor/generateSVG.t.sol @@ -22,8 +22,8 @@ contract GenerateSVG_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_Test { progress: "0%", progressNumerical: 0, sablierAddress: "0xf3a045dc986015be9ae43bb3462ae5981b0816e0", - status: "Pending", - streamingModel: "Lockup Linear" + sablierModel: "Lockup Linear", + status: "Pending" }) ); string memory expectedSVG = @@ -42,8 +42,8 @@ contract GenerateSVG_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_Test { progress: "42.35%", progressNumerical: 4235, sablierAddress: "0xf3a045dc986015be9ae43bb3462ae5981b0816e0", - status: "Streaming", - streamingModel: "Lockup Linear" + sablierModel: "Lockup Linear", + status: "Streaming" }) ); string memory expectedSVG = @@ -62,8 +62,8 @@ contract GenerateSVG_Unit_Concrete_Test is NFTDescriptor_Unit_Concrete_Test { progress: "100%", progressNumerical: 100, sablierAddress: "0xf3a045dc986015be9ae43bb3462ae5981b0816e0", - status: "Depleted", - streamingModel: "Lockup Linear" + sablierModel: "Lockup Linear", + status: "Depleted" }) ); string memory expectedSVG = diff --git a/test/utils/Assertions.sol b/test/utils/Assertions.sol index a174981dc..7b2be5b81 100644 --- a/test/utils/Assertions.sol +++ b/test/utils/Assertions.sol @@ -41,32 +41,32 @@ abstract contract Assertions is PRBMathAssertions { assertEq(address(a), address(b), err); } - /// @dev Compares two {LockupLinear.Stream} struct entities. - function assertEq(LockupLinear.StreamLL memory a, LockupLinear.StreamLL memory b) internal { - assertEq(a.amounts, b.amounts); + /// @dev Compares two {LockupDynamic.Stream} struct entities. + function assertEq(LockupDynamic.StreamLD memory a, LockupDynamic.StreamLD memory b) internal { assertEq(a.asset, b.asset, "asset"); - assertEq(a.cliffTime, b.cliffTime, "cliffTime"); assertEq(a.endTime, b.endTime, "endTime"); assertEq(a.isCancelable, b.isCancelable, "isCancelable"); assertEq(a.isDepleted, b.isDepleted, "isDepleted"); - assertEq(a.isTransferable, b.isTransferable, "isTransferable"); assertEq(a.isStream, b.isStream, "isStream"); + assertEq(a.isTransferable, b.isTransferable, "isTransferable"); assertEq(a.recipient, b.recipient, "recipient"); + assertEq(a.segments, b.segments, "segments"); assertEq(a.sender, b.sender, "sender"); assertEq(a.startTime, b.startTime, "startTime"); assertEq(a.wasCanceled, b.wasCanceled, "wasCanceled"); } - /// @dev Compares two {LockupDynamic.Stream} struct entities. - function assertEq(LockupDynamic.StreamLD memory a, LockupDynamic.StreamLD memory b) internal { + /// @dev Compares two {LockupLinear.Stream} struct entities. + function assertEq(LockupLinear.StreamLL memory a, LockupLinear.StreamLL memory b) internal { + assertEq(a.amounts, b.amounts); assertEq(a.asset, b.asset, "asset"); + assertEq(a.cliffTime, b.cliffTime, "cliffTime"); assertEq(a.endTime, b.endTime, "endTime"); assertEq(a.isCancelable, b.isCancelable, "isCancelable"); assertEq(a.isDepleted, b.isDepleted, "isDepleted"); - assertEq(a.isTransferable, b.isTransferable, "isTransferable"); assertEq(a.isStream, b.isStream, "isStream"); + assertEq(a.isTransferable, b.isTransferable, "isTransferable"); assertEq(a.recipient, b.recipient, "recipient"); - assertEq(a.segments, b.segments, "segments"); assertEq(a.sender, b.sender, "sender"); assertEq(a.startTime, b.startTime, "startTime"); assertEq(a.wasCanceled, b.wasCanceled, "wasCanceled"); @@ -78,8 +78,8 @@ abstract contract Assertions is PRBMathAssertions { assertEq(a.endTime, b.endTime, "endTime"); assertEq(a.isCancelable, b.isCancelable, "isCancelable"); assertEq(a.isDepleted, b.isDepleted, "isDepleted"); - assertEq(a.isTransferable, b.isTransferable, "isTransferable"); assertEq(a.isStream, b.isStream, "isStream"); + assertEq(a.isTransferable, b.isTransferable, "isTransferable"); assertEq(a.recipient, b.recipient, "recipient"); assertEq(a.sender, b.sender, "sender"); assertEq(a.startTime, b.startTime, "startTime"); @@ -87,15 +87,15 @@ abstract contract Assertions is PRBMathAssertions { assertEq(a.wasCanceled, b.wasCanceled, "wasCanceled"); } - /// @dev Compares two {LockupLinear.Range} struct entities. - function assertEq(LockupLinear.Range memory a, LockupLinear.Range memory b) internal { - assertEqUint40(a.cliff, b.cliff, "range.cliff"); + /// @dev Compares two {LockupDynamic.Range} struct entities. + function assertEq(LockupDynamic.Range memory a, LockupDynamic.Range memory b) internal { assertEqUint40(a.end, b.end, "range.end"); assertEqUint40(a.start, b.start, "range.start"); } - /// @dev Compares two {LockupDynamic.Range} struct entities. - function assertEq(LockupDynamic.Range memory a, LockupDynamic.Range memory b) internal { + /// @dev Compares two {LockupLinear.Range} struct entities. + function assertEq(LockupLinear.Range memory a, LockupLinear.Range memory b) internal { + assertEqUint40(a.cliff, b.cliff, "range.cliff"); assertEqUint40(a.end, b.end, "range.end"); assertEqUint40(a.start, b.start, "range.start"); } @@ -106,7 +106,7 @@ abstract contract Assertions is PRBMathAssertions { assertEqUint40(a.start, b.start, "range.start"); } - /// @dev Compares two {LockupDynamic.Segment[]} arrays. + /// @dev Compares two {LockupDynamic.Segment} arrays. function assertEq(LockupDynamic.Segment[] memory a, LockupDynamic.Segment[] memory b) internal { if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { emit log("Error: a == b not satisfied [LockupDynamic.Segment[]]"); @@ -116,7 +116,7 @@ abstract contract Assertions is PRBMathAssertions { } } - /// @dev Compares two `LockupDynamic.Segment[]` arrays. + /// @dev Compares two {LockupDynamic.Segment} arrays. function assertEq(LockupDynamic.Segment[] memory a, LockupDynamic.Segment[] memory b, string memory err) internal { if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { emit log_named_string("Error", err); @@ -124,7 +124,7 @@ abstract contract Assertions is PRBMathAssertions { } } - /// @dev Compares two {LockupTranched.Tranche[]} arrays. + /// @dev Compares two {LockupTranched.Tranche} arrays. function assertEq(LockupTranched.Tranche[] memory a, LockupTranched.Tranche[] memory b) internal { if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { emit log("Error: a == b not satisfied [LockupTranched.Tranche[]]"); @@ -134,7 +134,7 @@ abstract contract Assertions is PRBMathAssertions { } } - /// @dev Compares two `LockupTranched.Tranche[]` arrays. + /// @dev Compares two {LockupTranched.Tranche} arrays. function assertEq( LockupTranched.Tranche[] memory a, LockupTranched.Tranche[] memory b, diff --git a/test/utils/Calculations.sol b/test/utils/Calculations.sol index 2beda673a..1290e64bf 100644 --- a/test/utils/Calculations.sol +++ b/test/utils/Calculations.sol @@ -23,21 +23,21 @@ abstract contract Calculations { } /// @dev Helper function that replicates the logic of {SablierV2LockupLinear.streamedAmountOf}. - function calculateStreamedAmount(uint40 currentTime, uint128 depositAmount) internal view returns (uint128) { - if (currentTime > defaults.END_TIME()) { + function calculateStreamedAmount(uint40 blockTimestamp, uint128 depositAmount) internal view returns (uint128) { + if (blockTimestamp > defaults.END_TIME()) { return depositAmount; } unchecked { - UD60x18 elapsedTime = ud(currentTime - defaults.START_TIME()); - UD60x18 totalTime = ud(defaults.TOTAL_DURATION()); - UD60x18 elapsedTimePercentage = elapsedTime.div(totalTime); + UD60x18 elapsedTime = ud(blockTimestamp - defaults.START_TIME()); + UD60x18 totalDuration = ud(defaults.TOTAL_DURATION()); + UD60x18 elapsedTimePercentage = elapsedTime.div(totalDuration); return elapsedTimePercentage.mul(ud(depositAmount)).intoUint128(); } } /// @dev Replicates the logic of {SablierV2LockupDynamic._calculateStreamedAmountForMultipleSegments}. function calculateStreamedAmountForMultipleSegments( - uint40 currentTime, + uint40 blockTimestamp, LockupDynamic.Segment[] memory segments, uint128 depositAmount ) @@ -45,7 +45,7 @@ abstract contract Calculations { view returns (uint128) { - if (currentTime >= segments[segments.length - 1].timestamp) { + if (blockTimestamp >= segments[segments.length - 1].timestamp) { return depositAmount; } @@ -53,7 +53,7 @@ abstract contract Calculations { uint128 previousSegmentAmounts; uint40 currentSegmentTimestamp = segments[0].timestamp; uint256 index = 0; - while (currentSegmentTimestamp < currentTime) { + while (currentSegmentTimestamp < blockTimestamp) { previousSegmentAmounts += segments[index].amount; index += 1; currentSegmentTimestamp = segments[index].timestamp; @@ -70,11 +70,11 @@ abstract contract Calculations { previousTimestamp = defaults.START_TIME(); } - SD59x18 elapsedSegmentTime = (currentTime - previousTimestamp).intoSD59x18(); - SD59x18 totalSegmentTime = (currentSegmentTimestamp - previousTimestamp).intoSD59x18(); + SD59x18 elapsedTime = (blockTimestamp - previousTimestamp).intoSD59x18(); + SD59x18 segmentDuration = (currentSegmentTimestamp - previousTimestamp).intoSD59x18(); - SD59x18 elapsedSegmentTimePercentage = elapsedSegmentTime.div(totalSegmentTime); - SD59x18 multiplier = elapsedSegmentTimePercentage.pow(currentSegmentExponent); + SD59x18 elapsedTimePercentage = elapsedTime.div(segmentDuration); + SD59x18 multiplier = elapsedTimePercentage.pow(currentSegmentExponent); SD59x18 segmentStreamedAmount = multiplier.mul(currentSegmentAmount); return previousSegmentAmounts + uint128(segmentStreamedAmount.intoUint256()); } @@ -82,30 +82,30 @@ abstract contract Calculations { /// @dev Replicates the logic of {SablierV2LockupDynamic._calculateStreamedAmountForOneSegment}. function calculateStreamedAmountForOneSegment( - uint40 currentTime, + uint40 blockTimestamp, LockupDynamic.Segment memory segment ) internal view returns (uint128) { - if (currentTime >= segment.timestamp) { + if (blockTimestamp >= segment.timestamp) { return segment.amount; } unchecked { - SD59x18 elapsedTime = (currentTime - defaults.START_TIME()).intoSD59x18(); - SD59x18 totalTime = (segment.timestamp - defaults.START_TIME()).intoSD59x18(); + SD59x18 elapsedTime = (blockTimestamp - defaults.START_TIME()).intoSD59x18(); + SD59x18 totalDuration = (segment.timestamp - defaults.START_TIME()).intoSD59x18(); - SD59x18 elapsedTimePercentage = elapsedTime.div(totalTime); + SD59x18 elapsedTimePercentage = elapsedTime.div(totalDuration); SD59x18 multiplier = elapsedTimePercentage.pow(segment.exponent.intoSD59x18()); - SD59x18 streamedAmountSd = multiplier.mul(segment.amount.intoSD59x18()); - return uint128(streamedAmountSd.intoUint256()); + SD59x18 streamedAmount = multiplier.mul(segment.amount.intoSD59x18()); + return uint128(streamedAmount.intoUint256()); } } /// @dev Helper function that replicates the logic of {SablierV2LockupTranched._calculateStreamedAmount}. function calculateStreamedAmountForTranches( - uint40 currentTime, + uint40 blockTimestamp, LockupTranched.Tranche[] memory tranches, uint128 depositAmount ) @@ -113,18 +113,18 @@ abstract contract Calculations { pure returns (uint128) { - if (currentTime >= tranches[tranches.length - 1].timestamp) { + if (blockTimestamp >= tranches[tranches.length - 1].timestamp) { return depositAmount; } - // Sum the amounts in all tranches that precede the current time. + // Sum the amounts in all tranches that precede the block timestamp. uint128 streamedAmount = tranches[0].amount; uint40 currentTrancheTimestamp = tranches[1].timestamp; uint256 index = 1; // Using unchecked arithmetic is safe because the tranches amounts sum equal to total amount at this point. unchecked { - while (currentTrancheTimestamp <= currentTime) { + while (currentTrancheTimestamp <= blockTimestamp) { streamedAmount += tranches[index].amount; index += 1; currentTrancheTimestamp = tranches[index].timestamp; diff --git a/test/utils/Defaults.sol b/test/utils/Defaults.sol index 8a22b5ec7..b39e36998 100644 --- a/test/utils/Defaults.sol +++ b/test/utils/Defaults.sol @@ -23,8 +23,9 @@ contract Defaults is Constants { uint40 public constant CLIFF_DURATION = 2500 seconds; uint128 public constant DEPOSIT_AMOUNT = 10_000e18; uint40 public immutable END_TIME; - uint256 public constant MAX_COUNT = 500; + uint256 public constant MAX_SEGMENT_COUNT = 500; uint40 public immutable MAX_SEGMENT_DURATION; + uint256 public constant MAX_TRANCHE_COUNT = 500; uint128 public constant REFUND_AMOUNT = DEPOSIT_AMOUNT - CLIFF_AMOUNT; uint256 public SEGMENT_COUNT; uint40 public immutable START_TIME; @@ -45,7 +46,7 @@ contract Defaults is Constants { START_TIME = uint40(MAY_1_2024) + 2 days; CLIFF_TIME = START_TIME + CLIFF_DURATION; END_TIME = START_TIME + TOTAL_DURATION; - MAX_SEGMENT_DURATION = TOTAL_DURATION / uint40(MAX_COUNT); + MAX_SEGMENT_DURATION = TOTAL_DURATION / uint40(MAX_SEGMENT_COUNT); SEGMENT_COUNT = 2; TRANCHE_COUNT = 3; WARP_26_PERCENT = START_TIME + CLIFF_DURATION + 100 seconds; diff --git a/test/utils/DeployOptimized.sol b/test/utils/DeployOptimized.sol index cb7418f99..226ac9af6 100644 --- a/test/utils/DeployOptimized.sol +++ b/test/utils/DeployOptimized.sol @@ -67,7 +67,8 @@ abstract contract DeployOptimized is StdCheats { function deployOptimizedCore( address initialAdmin, - uint256 maxCount + uint256 maxSegmentCount, + uint256 maxTrancheCount ) internal returns ( @@ -78,8 +79,8 @@ abstract contract DeployOptimized is StdCheats { ) { nftDescriptor_ = deployOptimizedNFTDescriptor(); - lockupDynamic_ = deployOptimizedLockupDynamic(initialAdmin, nftDescriptor_, maxCount); + lockupDynamic_ = deployOptimizedLockupDynamic(initialAdmin, nftDescriptor_, maxSegmentCount); lockupLinear_ = deployOptimizedLockupLinear(initialAdmin, nftDescriptor_); - lockupTranched_ = deployOptimizedLockupTranched(initialAdmin, nftDescriptor_, maxCount); + lockupTranched_ = deployOptimizedLockupTranched(initialAdmin, nftDescriptor_, maxTrancheCount); } } diff --git a/test/utils/Fuzzers.sol b/test/utils/Fuzzers.sol index a4183491f..8496d4299 100644 --- a/test/utils/Fuzzers.sol +++ b/test/utils/Fuzzers.sol @@ -106,7 +106,7 @@ abstract contract Fuzzers is Constants, Utils { segments[segments.length - 1].amount += (createAmounts.deposit - estimatedDepositAmount); } - /// @dev Fuzzes the durations. + /// @dev Fuzzes the segment durations. function fuzzSegmentDurations(LockupDynamic.SegmentWithDuration[] memory segments) internal view { unchecked { // Precompute the first segment duration. @@ -127,8 +127,8 @@ abstract contract Fuzzers is Constants, Utils { uint40 segmentCount = uint40(segments.length); if (segmentCount == 1) { // The end time must be in the future. - uint40 currentTime = getBlockTimestamp(); - segments[0].timestamp = (startTime < currentTime ? currentTime : startTime) + 2 days; + uint40 blockTimestamp = getBlockTimestamp(); + segments[0].timestamp = (startTime < blockTimestamp ? blockTimestamp : startTime) + 2 days; return; } @@ -154,6 +154,50 @@ abstract contract Fuzzers is Constants, Utils { LOCKUP-TRANCHED //////////////////////////////////////////////////////////////////////////*/ + /// @dev Fuzzes the tranche durations. + function fuzzTrancheDurations(LockupTranched.TrancheWithDuration[] memory tranches) internal view { + unchecked { + // Precompute the first tranche duration. + tranches[0].duration = uint40(_bound(tranches[0].duration, 1, 100)); + + // Bound the durations so that none is zero and the calculations don't overflow. + uint256 durationCount = tranches.length; + uint40 maxDuration = (MAX_UNIX_TIMESTAMP - getBlockTimestamp()) / uint40(durationCount); + for (uint256 i = 1; i < durationCount; ++i) { + tranches[i].duration = boundUint40(tranches[i].duration, 1, maxDuration); + } + } + } + + /// @dev Fuzzes the tranche timestamps. + function fuzzTrancheTimestamps(LockupTranched.Tranche[] memory tranches, uint40 startTime) internal view { + // Return here if there's only one tranche to not run into division by zero. + uint40 trancheCount = uint40(tranches.length); + if (trancheCount == 1) { + // The end time must be in the future. + uint40 blockTimestamp = getBlockTimestamp(); + tranches[0].timestamp = (startTime < blockTimestamp ? blockTimestamp : startTime) + 2 days; + return; + } + + // The first timestamps is precomputed to avoid an underflow in the first loop iteration. We have to + // add 1 because the first timestamp must be greater than the start time. + tranches[0].timestamp = startTime + 1 seconds; + + // Fuzz the timestamps while preserving their order in the array. For each timestamp, set its initial guess + // as the sum of the starting timestamp and the step size multiplied by the current index. This ensures that + // the initial guesses are evenly spaced. Next, we bound the timestamp within a range of half the step size + // around the initial guess. + uint256 start = tranches[0].timestamp; + uint40 step = (MAX_UNIX_TIMESTAMP - tranches[0].timestamp) / (trancheCount - 1); + uint40 halfStep = step / 2; + for (uint256 i = 1; i < trancheCount; ++i) { + uint256 timestamp = start + i * step; + timestamp = _bound(timestamp, timestamp - halfStep, timestamp + halfStep); + tranches[i].timestamp = uint40(timestamp); + } + } + /// @dev Just like {fuzzTranchedStreamAmounts} but with defaults. function fuzzTranchedStreamAmounts(LockupTranched.Tranche[] memory tranches) internal @@ -240,48 +284,4 @@ abstract contract Fuzzers is Constants, Utils { createAmounts.deposit = totalAmount - createAmounts.brokerFee; tranches[tranches.length - 1].amount += (createAmounts.deposit - estimatedDepositAmount); } - - /// @dev Fuzzes the durations. - function fuzzTrancheDurations(LockupTranched.TrancheWithDuration[] memory tranches) internal view { - unchecked { - // Precompute the first tranche duration. - tranches[0].duration = uint40(_bound(tranches[0].duration, 1, 100)); - - // Bound the durations so that none is zero and the calculations don't overflow. - uint256 durationCount = tranches.length; - uint40 maxDuration = (MAX_UNIX_TIMESTAMP - getBlockTimestamp()) / uint40(durationCount); - for (uint256 i = 1; i < durationCount; ++i) { - tranches[i].duration = boundUint40(tranches[i].duration, 1, maxDuration); - } - } - } - - /// @dev Fuzzes the tranche timestamps. - function fuzzTrancheTimestamps(LockupTranched.Tranche[] memory tranches, uint40 startTime) internal view { - // Return here if there's only one tranche to not run into division by zero. - uint40 trancheCount = uint40(tranches.length); - if (trancheCount == 1) { - // The end time must be in the future. - uint40 currentTime = getBlockTimestamp(); - tranches[0].timestamp = (startTime < currentTime ? currentTime : startTime) + 2 days; - return; - } - - // The first timestamps is precomputed to avoid an underflow in the first loop iteration. We have to - // add 1 because the first timestamp must be greater than the start time. - tranches[0].timestamp = startTime + 1 seconds; - - // Fuzz the timestamps while preserving their order in the array. For each timestamp, set its initial guess - // as the sum of the starting timestamp and the step size multiplied by the current index. This ensures that - // the initial guesses are evenly spaced. Next, we bound the timestamp within a range of half the step size - // around the initial guess. - uint256 start = tranches[0].timestamp; - uint40 step = (MAX_UNIX_TIMESTAMP - tranches[0].timestamp) / (trancheCount - 1); - uint40 halfStep = step / 2; - for (uint256 i = 1; i < trancheCount; ++i) { - uint256 timestamp = start + i * step; - timestamp = _bound(timestamp, timestamp - halfStep, timestamp + halfStep); - tranches[i].timestamp = uint40(timestamp); - } - } } diff --git a/test/utils/Precompiles.t.sol b/test/utils/Precompiles.t.sol index d38753d7c..8272487e4 100644 --- a/test/utils/Precompiles.t.sol +++ b/test/utils/Precompiles.t.sol @@ -25,7 +25,7 @@ contract Precompiles_Test is Base_Test { function test_DeployLockupDynamic() external onlyTestOptimizedProfile { address actualLockupDynamic = address(precompiles.deployLockupDynamic(users.admin, nftDescriptor)); address expectedLockupDynamic = - address(deployOptimizedLockupDynamic(users.admin, nftDescriptor, defaults.MAX_COUNT())); + address(deployOptimizedLockupDynamic(users.admin, nftDescriptor, defaults.MAX_SEGMENT_COUNT())); bytes memory expectedLockupDynamicCode = adjustBytecode(expectedLockupDynamic.code, expectedLockupDynamic, actualLockupDynamic); assertEq(actualLockupDynamic.code, expectedLockupDynamicCode, "bytecodes mismatch"); @@ -42,7 +42,7 @@ contract Precompiles_Test is Base_Test { function test_DeployLockupTranched() external onlyTestOptimizedProfile { address actualLockupTranched = address(precompiles.deployLockupTranched(users.admin, nftDescriptor)); address expectedLockupTranched = - address(deployOptimizedLockupTranched(users.admin, nftDescriptor, defaults.MAX_COUNT())); + address(deployOptimizedLockupTranched(users.admin, nftDescriptor, defaults.MAX_TRANCHE_COUNT())); bytes memory expectedLockupTranchedCode = adjustBytecode(expectedLockupTranched.code, expectedLockupTranched, actualLockupTranched); assertEq(actualLockupTranched.code, expectedLockupTranchedCode, "bytecodes mismatch"); @@ -67,7 +67,7 @@ contract Precompiles_Test is Base_Test { ISablierV2LockupLinear expectedLockupLinear, ISablierV2LockupTranched expectedLockupTranched, ISablierV2NFTDescriptor expectedNFTDescriptor - ) = deployOptimizedCore(users.admin, defaults.MAX_COUNT()); + ) = deployOptimizedCore(users.admin, defaults.MAX_SEGMENT_COUNT(), defaults.MAX_TRANCHE_COUNT()); bytes memory expectedLockupDynamicCode = adjustBytecode( address(expectedLockupDynamic).code, address(expectedLockupDynamic), address(actualLockupDynamic) diff --git a/test/utils/Utils.sol b/test/utils/Utils.sol index 0a1b1b644..9a5257388 100644 --- a/test/utils/Utils.sol +++ b/test/utils/Utils.sol @@ -73,6 +73,18 @@ abstract contract Utils is CommonBase, PRBMathUtils { return Strings.equal(profile, "test-optimized"); } + /// @dev Returns the largest of the provided `uint40` numbers. + function maxOfThree(uint40 a, uint40 b, uint40 c) internal pure returns (uint40) { + uint40 max = a; + if (b > max) { + max = b; + } + if (c > max) { + max = c; + } + return max; + } + /// @dev Stops the active prank and sets a new one. function resetPrank(address msgSender) internal { vm.stopPrank();