From f9d329ccc21ec61610dcbcfa84f39fcb1d34c96f Mon Sep 17 00:00:00 2001 From: smol-ninja Date: Thu, 21 Nov 2024 11:36:27 +0000 Subject: [PATCH] refactor: remove merkle contracts (#1089) * refactor: remove merkle contracts * docs: update license ens * refactor: rebase from staging --- .github/workflows/ci-deep.yml | 2 +- .github/workflows/ci-fork.yml | 2 +- .github/workflows/ci.yml | 10 +- .github/workflows/generate-svg.yml | 2 +- LICENSE.md | 4 +- benchmark/BatchLockup.Gas.t.sol | 6 +- benchmark/Benchmark.t.sol | 4 +- benchmark/LockupDynamic.Gas.t.sol | 2 +- benchmark/LockupLinear.Gas.t.sol | 15 +- benchmark/LockupTranched.Gas.t.sol | 2 +- benchmark/results/SablierBatchLockup.md | 60 ++-- benchmark/results/SablierLockup_Dynamic.md | 54 ++-- benchmark/results/SablierLockup_Linear.md | 30 +- benchmark/results/SablierLockup_Tranched.md | 54 ++-- codecov.yml | 4 +- foundry.toml | 8 +- package.json | 6 +- precompiles/Precompiles.sol | 66 +--- script/{core => }/DeployBatchLockup.t.sol | 4 +- .../DeployDeterministicBatchLockup.t.sol | 4 +- .../DeployDeterministicLockup.s.sol | 6 +- .../DeployDeterministicNFTDescriptor.s.sol | 4 +- script/DeployDeterministicProtocol.s.sol | 43 +++ script/{core => }/DeployLockup.s.sol | 6 +- script/{core => }/DeployNFTDescriptor.s.sol | 4 +- script/DeployProtocol.s.sol | 43 +++ script/{protocol => }/DeploymentLogger.s.sol | 59 +--- script/{core => }/GenerateSVG.s.sol | 8 +- script/{core => }/Init.s.sol | 6 +- script/core/DeployCore.s.sol | 22 -- script/core/DeployDeterministicCore.s.sol | 22 -- script/periphery/CreateMerkleInstant.s.sol | 33 -- script/periphery/CreateMerkleLL.s.sol | 46 --- script/periphery/CreateMerkleLT.s.sol | 48 --- script/periphery/DeployMerkleFactory.s.sol | 13 - .../DeployDeterministicProtocol.s.sol | 64 ---- script/protocol/DeployProtocol.s.sol | 64 ---- shell/generate-svg.sh | 2 +- shell/prepare-artifacts.sh | 58 ++-- shell/update-precompiles.sh | 2 - src/{core => }/LockupNFTDescriptor.sol | 0 src/{core => }/SablierBatchLockup.sol | 0 src/{core => }/SablierLockup.sol | 0 src/{core => }/abstracts/Adminable.sol | 0 src/{core => }/abstracts/Batch.sol | 0 src/{core => }/abstracts/NoDelegateCall.sol | 0 .../abstracts/SablierLockupBase.sol | 0 src/{core => }/interfaces/IAdminable.sol | 0 src/{core => }/interfaces/IBatch.sol | 0 .../interfaces/ILockupNFTDescriptor.sol | 0 .../interfaces/ISablierBatchLockup.sol | 2 +- src/{core => }/interfaces/ISablierLockup.sol | 0 .../interfaces/ISablierLockupBase.sol | 0 .../interfaces/ISablierLockupRecipient.sol | 0 src/{core => }/libraries/Errors.sol | 0 src/{core => }/libraries/Helpers.sol | 0 src/{core => }/libraries/NFTSVG.sol | 0 src/{core => }/libraries/SVGElements.sol | 0 src/{core => }/libraries/VestingMath.sol | 0 src/periphery/SablierMerkleFactory.sol | 302 ------------------ src/periphery/SablierMerkleInstant.sol | 43 --- src/periphery/SablierMerkleLL.sol | 108 ------- src/periphery/SablierMerkleLT.sol | 201 ------------ src/periphery/abstracts/SablierMerkleBase.sol | 200 ------------ .../interfaces/ISablierMerkleBase.sol | 103 ------ .../interfaces/ISablierMerkleFactory.sol | 233 -------------- .../interfaces/ISablierMerkleInstant.sol | 15 - src/periphery/interfaces/ISablierMerkleLL.sol | 40 --- src/periphery/interfaces/ISablierMerkleLT.sol | 42 --- src/periphery/libraries/Errors.sol | 48 --- src/periphery/types/DataTypes.sol | 66 ---- src/{core => }/types/DataTypes.sol | 0 test/Base.t.sol | 59 ++-- test/{core => }/fork/Fork.t.sol | 2 +- test/{core => }/fork/LockupDynamic.t.sol | 6 +- test/{core => }/fork/LockupLinear.t.sol | 6 +- test/{core => }/fork/LockupTranched.t.sol | 6 +- test/{core => }/fork/NFTDescriptor.t.sol | 4 +- test/{core => }/fork/assets/DAI.t.sol | 0 test/{core => }/fork/assets/EURS.t.sol | 0 test/{core => }/fork/assets/SHIB.t.sol | 0 test/{core => }/fork/assets/USDC.t.sol | 0 test/{core => }/fork/assets/USDT.t.sol | 0 test/{core => }/integration/Integration.t.sol | 8 +- .../createWithDurationsLD.t.sol | 20 +- .../createWithDurationsLD.tree | 0 .../createWithDurationsLL.t.sol | 17 +- .../createWithDurationsLL.tree | 0 .../createWithDurationsLT.t.sol | 17 +- .../createWithDurationsLT.tree | 0 .../createWithTimestampsLD.t.sol | 17 +- .../createWithTimestampsLD.tree | 0 .../createWithTimestamps.t.sol | 17 +- .../createWithTimestamps.tree | 0 .../createWithTimestampsLT.t.sol | 17 +- .../createWithTimestampsLT.tree | 0 .../integration/concrete/constructor.t.sol | 4 +- .../allow-to-hook/allowToHook.t.sol | 4 +- .../allow-to-hook/allowToHook.tree | 0 .../concrete/lockup-base/batch/batch.t.sol | 4 +- .../concrete/lockup-base/batch/batch.tree | 0 .../concrete/lockup-base/burn/burn.t.sol | 4 +- .../concrete/lockup-base/burn/burn.tree | 0 .../cancel-multiple/cancelMultiple.t.sol | 6 +- .../cancel-multiple/cancelMultiple.tree | 0 .../concrete/lockup-base/cancel/cancel.t.sol | 8 +- .../concrete/lockup-base/cancel/cancel.tree | 0 .../createWithTimestamps.t.sol | 6 +- .../createWithTimestamps.tree | 0 .../lockup-base/getters/getters.t.sol | 2 +- .../concrete/lockup-base/getters/getters.tree | 0 .../refundableAmountOf.t.sol | 0 .../refundableAmountOf.tree | 0 .../renounce-multiple/renounceMultiple.t.sol | 4 +- .../renounce-multiple/renounceMultiple.tree | 0 .../lockup-base/renounce/renounce.t.sol | 4 +- .../lockup-base/renounce/renounce.tree | 0 .../set-nft-descriptor/setNFTDescriptor.t.sol | 10 +- .../set-nft-descriptor/setNFTDescriptor.tree | 0 .../lockup-base/status-of/statusOf.t.sol | 2 +- .../lockup-base/status-of/statusOf.tree | 0 .../streamed-amount-of/streamedAmountOf.t.sol | 0 .../streamed-amount-of/streamedAmountOf.tree | 0 .../transfer-from/transferFrom.t.sol | 2 +- .../transfer-from/transferFrom.tree | 0 .../withdraw-hooks/withdrawHooks.t.sol | 2 +- .../withdraw-hooks/withdrawHooks.tree | 0 .../withdrawMaxAndTransfer.t.sol | 6 +- .../withdrawMaxAndTransfer.tree | 0 .../withdraw-max/withdrawMax.t.sol | 4 +- .../lockup-base/withdraw-max/withdrawMax.tree | 0 .../withdraw-multiple/withdrawMultiple.t.sol | 6 +- .../withdraw-multiple/withdrawMultiple.tree | 0 .../lockup-base/withdraw/withdraw.t.sol | 8 +- .../lockup-base/withdraw/withdraw.tree | 0 .../withdrawableAmountOf.t.sol | 0 .../withdrawableAmountOf.tree | 0 .../lockup-dynamic/LockupDynamic.t.sol | 12 +- .../createWithDurationsLD.t.sol | 6 +- .../createWithDurationsLD.tree | 0 .../createWithTimestampsLD.t.sol | 6 +- .../createWithTimestampsLD.tree | 0 .../get-segments/getSegments.t.sol | 4 +- .../get-segments/getSegments.tree | 0 .../streamed-amount-of/streamedAmountOf.t.sol | 5 +- .../streamed-amount-of/streamedAmountOf.tree | 0 .../lockup-dynamic/token-uri/tokenURI.t.sol | 2 +- .../lockup-dynamic/token-uri/tokenURI.tree | 0 .../withdrawableAmountOf.t.sol | 2 +- .../withdrawableAmountOf.tree | 0 .../concrete/lockup-linear/LockupLinear.t.sol | 12 +- .../createWithDurationsLL.t.sol | 6 +- .../createWithDurationsLL.tree | 0 .../createWithTimestampsLL.t.sol | 6 +- .../createWithTimestampsLL.tree | 0 .../get-cliff-time/getCliffTime.t.sol | 4 +- .../get-cliff-time/getCliffTime.tree | 0 .../get-unlock-amounts/getUnlockAmounts.t.sol | 4 +- .../get-unlock-amounts/getUnlockAmounts.tree | 0 .../streamed-amount-of/streamedAmountOf.t.sol | 3 +- .../streamed-amount-of/streamedAmountOf.tree | 0 .../lockup-linear/token-uri/tokenURI.t.sol | 0 .../lockup-linear/token-uri/tokenURI.tree | 0 .../withdrawableAmountOf.t.sol | 2 +- .../withdrawableAmountOf.tree | 0 .../lockup-tranched/LockupTranched.t.sol | 12 +- .../createWithDurationsLT.t.sol | 6 +- .../createWithDurationsLT.tree | 0 .../createWithTimestampsLT.t.sol | 6 +- .../createWithTimestampsLT.tree | 0 .../get-tranches/getTranches.t.sol | 4 +- .../get-tranches/getTranches.tree | 0 .../streamed-amount-of/streamedAmountOf.t.sol | 3 +- .../streamed-amount-of/streamedAmountOf.tree | 0 .../lockup-tranched/token-uri/tokenURI.t.sol | 0 .../lockup-tranched/token-uri/tokenURI.tree | 0 .../withdrawableAmountOf.t.sol | 2 +- .../withdrawableAmountOf.tree | 0 .../nft-descriptor/generateAccentColor.t.sol | 0 .../IsAllowedCharacter.t.sol | 0 .../IsAllowedCharacter.tree | 0 .../nft-descriptor/map-symbol/mapSymbol.t.sol | 2 +- .../nft-descriptor/map-symbol/mapSymbol.tree | 0 .../safeAssetDecimals.t.sol | 0 .../safeAssetDecimals.tree | 0 .../safe-asset-symbol/safeAssetSymbol.t.sol | 0 .../safe-asset-symbol/safeAssetSymbol.tree | 0 .../integration/fuzz/lockup-base/cancel.t.sol | 8 +- .../fuzz/lockup-base/refundableAmountOf.t.sol | 0 .../fuzz/lockup-base/withdraw.t.sol | 4 +- .../fuzz/lockup-base/withdrawMax.t.sol | 4 +- .../lockup-base/withdrawMaxAndTransfer.t.sol | 2 +- .../fuzz/lockup-dynamic/LockupDynamic.t.sol | 4 +- .../createWithDurationsLD.t.sol | 4 +- .../createWithTimestampsLD.t.sol | 6 +- .../lockup-dynamic/streamedAmountOf.t.sol | 2 +- .../fuzz/lockup-dynamic/withdraw.t.sol | 4 +- .../lockup-dynamic/withdrawableAmountOf.t.sol | 2 +- .../fuzz/lockup-linear/LockupLinear.t.sol | 4 +- .../lockup-linear/createWithDurationsLL.t.sol | 6 +- .../createWithTimestampsLL.t.sol | 6 +- .../fuzz/lockup-linear/streamedAmountOf.t.sol | 2 +- .../lockup-linear/withdrawableAmountOf.t.sol | 2 +- .../fuzz/lockup-tranched/LockupTranched.t.sol | 2 +- .../createWithDurationsLT.t.sol | 4 +- .../createWithTimestampsLT.t.sol | 6 +- .../lockup-tranched/streamedAmountOf.t.sol | 2 +- .../fuzz/lockup-tranched/withdraw.t.sol | 4 +- .../withdrawableAmountOf.t.sol | 2 +- .../nft-descriptor/isAllowedCharacter.t.sol | 0 test/{core => }/invariant/Invariant.t.sol | 4 +- .../invariant/handlers/BaseHandler.sol | 6 +- .../handlers/LockupCreateHandler.sol | 4 +- .../invariant/handlers/LockupHandler.sol | 4 +- .../invariant/stores/LockupStore.sol | 2 +- test/mocks/AdminableMock.sol | 2 +- test/mocks/Hooks.sol | 4 +- test/mocks/NFTDescriptorMock.sol | 8 +- test/mocks/ReceiveEth.sol | 10 - test/periphery/Periphery.t.sol | 251 --------------- test/periphery/fork/Fork.t.sol | 57 ---- test/periphery/fork/assets/USDC.t.sol | 26 -- test/periphery/fork/assets/USDT.t.sol | 26 -- .../batch-lockup/createWithTimestampsLD.t.sol | 84 ----- .../batch-lockup/createWithTimestampsLL.t.sol | 87 ----- .../batch-lockup/createWithTimestampsLT.t.sol | 83 ----- .../fork/merkle-campaign/MerkleInstant.t.sol | 236 -------------- .../fork/merkle-campaign/MerkleLL.t.sol | 263 --------------- .../fork/merkle-campaign/MerkleLT.t.sol | 267 ---------------- .../merkle-campaign/MerkleCampaign.t.sol | 290 ----------------- .../merkle-campaign/factory/constructor.t.sol | 18 -- .../createMerkleInstant.t.sol | 132 -------- .../createMerkleInstant.tree | 15 - .../create-merkle-ll/createMerkleLL.t.sol | 150 --------- .../create-merkle-ll/createMerkleLL.tree | 15 - .../create-merkle-lt/createMerkleLT.t.sol | 155 --------- .../create-merkle-lt/createMerkleLT.tree | 15 - .../isPercentagesSum100.t.sol | 48 --- .../isPercentagesSum100.tree | 11 - .../resetSablierFeeByUser.t.sol | 60 ---- .../resetSablierFeeByUser.tree | 12 - .../setDefaultSablierFee.t.sol | 33 -- .../setDefaultSablierFee.tree | 6 - .../set-fee-by-user/setSablierFeeByUser.t.sol | 66 ---- .../set-fee-by-user/setSablierFeeByUser.tree | 11 - .../factory/withdraw-fees/withdrawFees.t.sol | 100 ------ .../factory/withdraw-fees/withdrawFees.tree | 21 -- .../instant/MerkleInstant.t.sol | 69 ---- .../merkle-campaign/instant/claim/claim.t.sol | 37 --- .../merkle-campaign/instant/constructor.t.sol | 70 ---- .../merkle-campaign/ll/MerkleLL.t.sol | 60 ---- .../merkle-campaign/ll/claim/claim.t.sol | 106 ------ .../merkle-campaign/ll/claim/claim.tree | 14 - .../merkle-campaign/ll/constructor.t.sol | 117 ------- .../merkle-campaign/lt/MerkleLT.t.sol | 60 ---- .../merkle-campaign/lt/claim/claim.t.sol | 159 --------- .../merkle-campaign/lt/claim/claim.tree | 14 - .../merkle-campaign/lt/constructor.t.sol | 120 ------- .../merkle-campaign/shared/claim/claim.t.sol | 122 ------- .../merkle-campaign/shared/claim/claim.tree | 25 -- .../shared/clawback/clawback.t.sol | 72 ----- .../shared/clawback/clawback.tree | 17 - .../getFirstClaimTime.t.sol | 21 -- .../getFirstClaimTime.tree | 5 - .../shared/has-claimed/hasClaimed.t.sol | 24 -- .../shared/has-claimed/hasClaimed.tree | 8 - .../shared/has-expired/hasExpired.t.sol | 27 -- .../shared/has-expired/hasExpired.tree | 10 - .../shared/withdraw-fees/withdrawFees.t.sol | 64 ---- .../shared/withdraw-fees/withdrawFees.tree | 13 - .../transfer-admin/transferAdmin.t.sol | 4 +- .../transfer-admin/transferAdmin.tree | 0 .../nft-descriptor/abbreviateAmount.t.sol | 2 +- .../calculateDurationInDays.t.sol | 2 +- .../nft-descriptor/calculatePixelWidth.t.sol | 0 .../calculateStreamedPercentage.t.sol | 0 .../nft-descriptor/generateAttributes.t.sol | 0 .../nft-descriptor/generateDescription.t.sol | 0 .../nft-descriptor/generateName.t.sol | 0 .../concrete/nft-descriptor/generateSVG.t.sol | 4 +- .../concrete/nft-descriptor/hourglass.t.sol | 2 +- .../nft-descriptor/stringifyCardType.t.sol | 2 +- .../stringifyFractionalAmount.t.sol | 0 .../nft-descriptor/stringifyPercentage.t.sol | 0 .../nft-descriptor/stringifyStatus.t.sol | 2 +- test/{core => }/unit/fuzz/transferAdmin.t.sol | 4 +- test/{core => }/unit/shared/Adminable.t.sol | 4 +- test/utils/Assertions.sol | 35 +- test/utils/BatchLockupBuilder.sol | 2 +- test/utils/Calculations.sol | 2 +- test/utils/Defaults.sol | 171 +--------- test/utils/DeployOptimized.sol | 53 +-- test/utils/Fuzzers.sol | 2 +- test/utils/MerkleBuilder.sol | 59 ---- test/utils/MerkleBuilder.t.sol | 46 --- test/utils/Modifiers.sol | 88 +---- test/utils/Murky.sol | 223 ------------- test/utils/Precompiles.t.sol | 28 +- test/utils/Types.sol | 7 - test/utils/Utils.sol | 2 +- 300 files changed, 557 insertions(+), 6769 deletions(-) rename script/{core => }/DeployBatchLockup.t.sol (71%) rename script/{core => }/DeployDeterministicBatchLockup.t.sol (73%) rename script/{core => }/DeployDeterministicLockup.s.sol (74%) rename script/{core => }/DeployDeterministicNFTDescriptor.s.sol (78%) create mode 100644 script/DeployDeterministicProtocol.s.sol rename script/{core => }/DeployLockup.s.sol (69%) rename script/{core => }/DeployNFTDescriptor.s.sol (72%) create mode 100644 script/DeployProtocol.s.sol rename script/{protocol => }/DeploymentLogger.s.sol (82%) rename script/{core => }/GenerateSVG.s.sol (86%) rename script/{core => }/Init.s.sol (96%) delete mode 100644 script/core/DeployCore.s.sol delete mode 100644 script/core/DeployDeterministicCore.s.sol delete mode 100644 script/periphery/CreateMerkleInstant.s.sol delete mode 100644 script/periphery/CreateMerkleLL.s.sol delete mode 100644 script/periphery/CreateMerkleLT.s.sol delete mode 100644 script/periphery/DeployMerkleFactory.s.sol delete mode 100644 script/protocol/DeployDeterministicProtocol.s.sol delete mode 100644 script/protocol/DeployProtocol.s.sol rename src/{core => }/LockupNFTDescriptor.sol (100%) rename src/{core => }/SablierBatchLockup.sol (100%) rename src/{core => }/SablierLockup.sol (100%) rename src/{core => }/abstracts/Adminable.sol (100%) rename src/{core => }/abstracts/Batch.sol (100%) rename src/{core => }/abstracts/NoDelegateCall.sol (100%) rename src/{core => }/abstracts/SablierLockupBase.sol (100%) rename src/{core => }/interfaces/IAdminable.sol (100%) rename src/{core => }/interfaces/IBatch.sol (100%) rename src/{core => }/interfaces/ILockupNFTDescriptor.sol (100%) rename src/{core => }/interfaces/ISablierBatchLockup.sol (98%) rename src/{core => }/interfaces/ISablierLockup.sol (100%) rename src/{core => }/interfaces/ISablierLockupBase.sol (100%) rename src/{core => }/interfaces/ISablierLockupRecipient.sol (100%) rename src/{core => }/libraries/Errors.sol (100%) rename src/{core => }/libraries/Helpers.sol (100%) rename src/{core => }/libraries/NFTSVG.sol (100%) rename src/{core => }/libraries/SVGElements.sol (100%) rename src/{core => }/libraries/VestingMath.sol (100%) delete mode 100644 src/periphery/SablierMerkleFactory.sol delete mode 100644 src/periphery/SablierMerkleInstant.sol delete mode 100644 src/periphery/SablierMerkleLL.sol delete mode 100644 src/periphery/SablierMerkleLT.sol delete mode 100644 src/periphery/abstracts/SablierMerkleBase.sol delete mode 100644 src/periphery/interfaces/ISablierMerkleBase.sol delete mode 100644 src/periphery/interfaces/ISablierMerkleFactory.sol delete mode 100644 src/periphery/interfaces/ISablierMerkleInstant.sol delete mode 100644 src/periphery/interfaces/ISablierMerkleLL.sol delete mode 100644 src/periphery/interfaces/ISablierMerkleLT.sol delete mode 100644 src/periphery/libraries/Errors.sol delete mode 100644 src/periphery/types/DataTypes.sol rename src/{core => }/types/DataTypes.sol (100%) rename test/{core => }/fork/Fork.t.sol (98%) rename test/{core => }/fork/LockupDynamic.t.sol (98%) rename test/{core => }/fork/LockupLinear.t.sol (98%) rename test/{core => }/fork/LockupTranched.t.sol (98%) rename test/{core => }/fork/NFTDescriptor.t.sol (98%) rename test/{core => }/fork/assets/DAI.t.sol (100%) rename test/{core => }/fork/assets/EURS.t.sol (100%) rename test/{core => }/fork/assets/SHIB.t.sol (100%) rename test/{core => }/fork/assets/USDC.t.sol (100%) rename test/{core => }/fork/assets/USDT.t.sol (100%) rename test/{core => }/integration/Integration.t.sol (98%) rename test/{core => }/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol (78%) rename test/{core => }/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree (100%) rename test/{core => }/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol (81%) rename test/{core => }/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree (100%) rename test/{core => }/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol (81%) rename test/{core => }/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree (100%) rename test/{core => }/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol (81%) rename test/{core => }/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree (100%) rename test/{core => }/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol (81%) rename test/{core => }/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree (100%) rename test/{core => }/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol (81%) rename test/{core => }/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree (100%) rename test/{core => }/integration/concrete/constructor.t.sol (94%) rename test/{core => }/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol (93%) rename test/{core => }/integration/concrete/lockup-base/allow-to-hook/allowToHook.tree (100%) rename test/{core => }/integration/concrete/lockup-base/batch/batch.t.sol (91%) rename test/{core => }/integration/concrete/lockup-base/batch/batch.tree (100%) rename test/{core => }/integration/concrete/lockup-base/burn/burn.t.sol (97%) rename test/{core => }/integration/concrete/lockup-base/burn/burn.tree (100%) rename test/{core => }/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol (96%) rename test/{core => }/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.tree (100%) rename test/{core => }/integration/concrete/lockup-base/cancel/cancel.t.sol (97%) rename test/{core => }/integration/concrete/lockup-base/cancel/cancel.tree (100%) rename test/{core => }/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol (97%) rename test/{core => }/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.tree (100%) rename test/{core => }/integration/concrete/lockup-base/getters/getters.t.sol (99%) rename test/{core => }/integration/concrete/lockup-base/getters/getters.tree (100%) rename test/{core => }/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.t.sol (100%) rename test/{core => }/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol (96%) rename test/{core => }/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.tree (100%) rename test/{core => }/integration/concrete/lockup-base/renounce/renounce.t.sol (95%) rename test/{core => }/integration/concrete/lockup-base/renounce/renounce.tree (100%) rename test/{core => }/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol (86%) rename test/{core => }/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.tree (100%) rename test/{core => }/integration/concrete/lockup-base/status-of/statusOf.t.sol (97%) rename test/{core => }/integration/concrete/lockup-base/status-of/statusOf.tree (100%) rename test/{core => }/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.t.sol (100%) rename test/{core => }/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol (96%) rename test/{core => }/integration/concrete/lockup-base/transfer-from/transferFrom.tree (100%) rename test/{core => }/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol (98%) rename test/{core => }/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.tree (100%) rename test/{core => }/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol (97%) rename test/{core => }/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree (100%) rename test/{core => }/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol (96%) rename test/{core => }/integration/concrete/lockup-base/withdraw-max/withdrawMax.tree (100%) rename test/{core => }/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol (97%) rename test/{core => }/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.tree (100%) rename test/{core => }/integration/concrete/lockup-base/withdraw/withdraw.t.sol (98%) rename test/{core => }/integration/concrete/lockup-base/withdraw/withdraw.tree (100%) rename test/{core => }/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol (100%) rename test/{core => }/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-dynamic/LockupDynamic.t.sol (80%) rename test/{core => }/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol (97%) rename test/{core => }/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.tree (100%) rename test/{core => }/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol (98%) rename test/{core => }/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.tree (100%) rename test/{core => }/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol (89%) rename test/{core => }/integration/concrete/lockup-dynamic/get-segments/getSegments.tree (100%) rename test/{core => }/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol (91%) rename test/{core => }/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol (99%) rename test/{core => }/integration/concrete/lockup-dynamic/token-uri/tokenURI.tree (100%) rename test/{core => }/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol (96%) rename test/{core => }/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/LockupLinear.t.sol (80%) rename test/{core => }/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol (96%) rename test/{core => }/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol (97%) rename test/{core => }/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol (90%) rename test/{core => }/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol (95%) rename test/{core => }/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol (96%) rename test/{core => }/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol (100%) rename test/{core => }/integration/concrete/lockup-linear/token-uri/tokenURI.tree (100%) rename test/{core => }/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol (95%) rename test/{core => }/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-tranched/LockupTranched.t.sol (80%) rename test/{core => }/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol (97%) rename test/{core => }/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.tree (100%) rename test/{core => }/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol (98%) rename test/{core => }/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.tree (100%) rename test/{core => }/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol (89%) rename test/{core => }/integration/concrete/lockup-tranched/get-tranches/getTranches.tree (100%) rename test/{core => }/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol (94%) rename test/{core => }/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.tree (100%) rename test/{core => }/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol (100%) rename test/{core => }/integration/concrete/lockup-tranched/token-uri/tokenURI.tree (100%) rename test/{core => }/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol (96%) rename test/{core => }/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.tree (100%) rename test/{core => }/integration/concrete/nft-descriptor/generateAccentColor.t.sol (100%) rename test/{core => }/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.t.sol (100%) rename test/{core => }/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.tree (100%) rename test/{core => }/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol (94%) rename test/{core => }/integration/concrete/nft-descriptor/map-symbol/mapSymbol.tree (100%) rename test/{core => }/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.t.sol (100%) rename test/{core => }/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.tree (100%) rename test/{core => }/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.t.sol (100%) rename test/{core => }/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.tree (100%) rename test/{core => }/integration/fuzz/lockup-base/cancel.t.sol (93%) rename test/{core => }/integration/fuzz/lockup-base/refundableAmountOf.t.sol (100%) rename test/{core => }/integration/fuzz/lockup-base/withdraw.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-base/withdrawMax.t.sol (96%) rename test/{core => }/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol (96%) rename test/{core => }/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol (91%) rename test/{core => }/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol (97%) rename test/{core => }/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-dynamic/withdraw.t.sol (97%) rename test/{core => }/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-linear/LockupLinear.t.sol (93%) rename test/{core => }/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol (96%) rename test/{core => }/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol (97%) rename test/{core => }/integration/fuzz/lockup-linear/streamedAmountOf.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-tranched/LockupTranched.t.sol (96%) rename test/{core => }/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol (97%) rename test/{core => }/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol (98%) rename test/{core => }/integration/fuzz/lockup-tranched/withdraw.t.sol (97%) rename test/{core => }/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol (98%) rename test/{core => }/integration/fuzz/nft-descriptor/isAllowedCharacter.t.sol (100%) rename test/{core => }/invariant/Invariant.t.sol (99%) rename test/{core => }/invariant/handlers/BaseHandler.sol (94%) rename test/{core => }/invariant/handlers/LockupCreateHandler.sol (99%) rename test/{core => }/invariant/handlers/LockupHandler.sol (98%) rename test/{core => }/invariant/stores/LockupStore.sol (96%) delete mode 100644 test/mocks/ReceiveEth.sol delete mode 100644 test/periphery/Periphery.t.sol delete mode 100644 test/periphery/fork/Fork.t.sol delete mode 100644 test/periphery/fork/assets/USDC.t.sol delete mode 100644 test/periphery/fork/assets/USDT.t.sol delete mode 100644 test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol delete mode 100644 test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol delete mode 100644 test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol delete mode 100644 test/periphery/fork/merkle-campaign/MerkleInstant.t.sol delete mode 100644 test/periphery/fork/merkle-campaign/MerkleLL.t.sol delete mode 100644 test/periphery/fork/merkle-campaign/MerkleLT.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/constructor.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.tree delete mode 100644 test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.tree delete mode 100644 test/periphery/integration/merkle-campaign/instant/MerkleInstant.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/instant/claim/claim.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/instant/constructor.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/ll/MerkleLL.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/ll/claim/claim.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/ll/claim/claim.tree delete mode 100644 test/periphery/integration/merkle-campaign/ll/constructor.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/lt/MerkleLT.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/lt/claim/claim.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/lt/claim/claim.tree delete mode 100644 test/periphery/integration/merkle-campaign/lt/constructor.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/claim/claim.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/claim/claim.tree delete mode 100644 test/periphery/integration/merkle-campaign/shared/clawback/clawback.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/clawback/clawback.tree delete mode 100644 test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.tree delete mode 100644 test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.tree delete mode 100644 test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.tree delete mode 100644 test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.t.sol delete mode 100644 test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.tree rename test/{core => }/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol (94%) rename test/{core => }/unit/concrete/adminable/transfer-admin/transferAdmin.tree (100%) rename test/{core => }/unit/concrete/nft-descriptor/abbreviateAmount.t.sol (98%) rename test/{core => }/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol (97%) rename test/{core => }/unit/concrete/nft-descriptor/calculatePixelWidth.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/calculateStreamedPercentage.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/generateAttributes.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/generateDescription.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/generateName.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/generateSVG.t.sol (99%) rename test/{core => }/unit/concrete/nft-descriptor/hourglass.t.sol (96%) rename test/{core => }/unit/concrete/nft-descriptor/stringifyCardType.t.sol (90%) rename test/{core => }/unit/concrete/nft-descriptor/stringifyFractionalAmount.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/stringifyPercentage.t.sol (100%) rename test/{core => }/unit/concrete/nft-descriptor/stringifyStatus.t.sol (93%) rename test/{core => }/unit/fuzz/transferAdmin.t.sol (91%) rename test/{core => }/unit/shared/Adminable.t.sol (88%) delete mode 100644 test/utils/MerkleBuilder.sol delete mode 100644 test/utils/MerkleBuilder.t.sol delete mode 100644 test/utils/Murky.sol diff --git a/.github/workflows/ci-deep.yml b/.github/workflows/ci-deep.yml index 170e5df27..4a6139474 100644 --- a/.github/workflows/ci-deep.yml +++ b/.github/workflows/ci-deep.yml @@ -72,7 +72,7 @@ jobs: with: foundry-fuzz-runs: ${{ fromJSON(inputs.forkFuzzRuns || '1000') }} foundry-profile: "test-optimized" - match-path: "test/{core,periphery}fork/**/*.sol" + match-path: "test/fork/**/*.sol" name: "Fork tests" notify-on-failure: diff --git a/.github/workflows/ci-fork.yml b/.github/workflows/ci-fork.yml index 6809e2f62..20b3cec63 100644 --- a/.github/workflows/ci-fork.yml +++ b/.github/workflows/ci-fork.yml @@ -20,7 +20,7 @@ jobs: foundry-fuzz-runs: 100 foundry-profile: "test-optimized" fuzz-seed: true - match-path: "test/{core,periphery}fork/**/*.sol" + match-path: "test/fork/**/*.sol" name: "Fork tests" test-utils: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ab5f393c..ea16fcb8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: with: foundry-fuzz-runs: 2000 foundry-profile: "test-optimized" - match-path: "test/core/unit/**/*.sol" + match-path: "test/unit/**/*.sol" name: "Unit tests" test-integration: @@ -42,7 +42,7 @@ jobs: with: foundry-fuzz-runs: 2000 foundry-profile: "test-optimized" - match-path: "test/{core,periphery}/integration/**/*.sol" + match-path: "test/integration/**/*.sol" name: "Integration tests" test-invariant: @@ -50,7 +50,7 @@ jobs: uses: "sablier-labs/reusable-workflows/.github/workflows/forge-test.yml@main" with: foundry-profile: "test-optimized" - match-path: "test/core/invariant/**/*.sol" + match-path: "test/invariant/**/*.sol" name: "Invariant tests" test-fork: @@ -61,7 +61,7 @@ jobs: with: foundry-fuzz-runs: 20 foundry-profile: "test-optimized" - match-path: "test/{core,periphery}/fork/**/*.sol" + match-path: "test/fork/**/*.sol" name: "Fork tests" coverage: @@ -70,4 +70,4 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} uses: "sablier-labs/reusable-workflows/.github/workflows/forge-coverage.yml@main" with: - match-path: "test/{core,periphery}/{integration,unit}/**/*.sol" + match-path: "test/{integration,unit}/**/*.sol" diff --git a/.github/workflows/generate-svg.yml b/.github/workflows/generate-svg.yml index a3d9f4b01..3e774d567 100644 --- a/.github/workflows/generate-svg.yml +++ b/.github/workflows/generate-svg.yml @@ -28,7 +28,7 @@ jobs: - name: "Generate an NFT SVG using the user-provided parameters" run: >- - forge script script/core/GenerateSVG.s.sol + forge script script/GenerateSVG.s.sol --sig "run(uint256,string,string,uint256)" "${{ fromJSON(inputs.progress || true) }}", "${{ fromJSON(inputs.status || true) }}" diff --git a/LICENSE.md b/LICENSE.md index b6fdb6d23..59aedb41a 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -11,9 +11,9 @@ Licensor: Sablier Labs Ltd Licensed Work: Sablier Lockup The Licensed Work is (C) 2024 Sablier Labs Ltd -Additional Use Grant: Any uses listed and defined at v2-core-license-grants.sablier.eth +Additional Use Grant: Any uses listed and defined at license-grants.sablier.eth -Change Date: The earlier of 2028-07-03 or a date specified at v2-core-license-date.sablier.eth +Change Date: The earlier of 2028-07-03 or a date specified at license-date.sablier.eth Change License: GNU General Public License v3.0 or later diff --git a/benchmark/BatchLockup.Gas.t.sol b/benchmark/BatchLockup.Gas.t.sol index 0fd048d53..1d3621b89 100644 --- a/benchmark/BatchLockup.Gas.t.sol +++ b/benchmark/BatchLockup.Gas.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22; import { ud2x18 } from "@prb/math/src/UD2x18.sol"; -import { Lockup, LockupDynamic, LockupTranched } from "../src/core/types/DataTypes.sol"; -import { BatchLockup } from "../src/periphery/types/DataTypes.sol"; +import { Lockup, LockupDynamic, LockupTranched } from "../src//types/DataTypes.sol"; +import { BatchLockup } from "../src//types/DataTypes.sol"; import { BatchLockupBuilder } from "../test/utils/BatchLockupBuilder.sol"; import { Benchmark_Test } from "./Benchmark.t.sol"; @@ -112,6 +112,7 @@ contract BatchLockup_Gas_Test is Benchmark_Test { function gasCreateWithDurationsLL(uint256 batchSize) internal { BatchLockup.CreateWithDurationsLL[] memory params = BatchLockupBuilder.fillBatch({ params: defaults.createWithDurationsBrokerNull(), + unlockAmounts: defaults.unlockAmounts(), durations: defaults.durations(), batchSize: batchSize }); @@ -131,6 +132,7 @@ contract BatchLockup_Gas_Test is Benchmark_Test { function gasCreateWithTimestampsLL(uint256 batchSize) internal { BatchLockup.CreateWithTimestampsLL[] memory params = BatchLockupBuilder.fillBatch({ params: defaults.createWithTimestampsBrokerNull(), + unlockAmounts: defaults.unlockAmounts(), cliffTime: defaults.CLIFF_TIME(), batchSize: batchSize }); diff --git a/benchmark/Benchmark.t.sol b/benchmark/Benchmark.t.sol index 72ba000ae..0c17e7f9f 100644 --- a/benchmark/Benchmark.t.sol +++ b/benchmark/Benchmark.t.sol @@ -165,7 +165,9 @@ abstract contract Benchmark_Test is Base_Test { function _createFewStreams() internal { for (uint128 i = 0; i < 100; ++i) { lockup.createWithTimestampsLD(defaults.createWithTimestamps(), defaults.segments()); - lockup.createWithTimestampsLL(defaults.createWithTimestamps(), defaults.CLIFF_TIME()); + lockup.createWithTimestampsLL( + defaults.createWithTimestamps(), defaults.unlockAmounts(), defaults.CLIFF_TIME() + ); lockup.createWithTimestampsLT(defaults.createWithTimestamps(), defaults.tranches()); } } diff --git a/benchmark/LockupDynamic.Gas.t.sol b/benchmark/LockupDynamic.Gas.t.sol index d9df3478f..49b832ef7 100644 --- a/benchmark/LockupDynamic.Gas.t.sol +++ b/benchmark/LockupDynamic.Gas.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22; import { ud2x18 } from "@prb/math/src/UD2x18.sol"; import { UD60x18, ud } from "@prb/math/src/UD60x18.sol"; -import { Lockup, LockupDynamic } from "../src/core/types/DataTypes.sol"; +import { Lockup, LockupDynamic } from "../src//types/DataTypes.sol"; import { Benchmark_Test } from "./Benchmark.t.sol"; diff --git a/benchmark/LockupLinear.Gas.t.sol b/benchmark/LockupLinear.Gas.t.sol index 4d1e8b73b..08639e35b 100644 --- a/benchmark/LockupLinear.Gas.t.sol +++ b/benchmark/LockupLinear.Gas.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { ud } from "@prb/math/src/UD60x18.sol"; -import { Lockup, LockupLinear } from "../src/core/types/DataTypes.sol"; +import { Lockup, LockupLinear } from "../src//types/DataTypes.sol"; import { Benchmark_Test } from "./Benchmark.t.sol"; @@ -56,8 +56,11 @@ contract Lockup_Linear_Gas_Test is Benchmark_Test { LockupLinear.Durations memory durations = defaults.durations(); durations.cliff = cliffDuration; + LockupLinear.UnlockAmounts memory unlockAmounts = defaults.unlockAmounts(); + if (cliffDuration == 0) unlockAmounts.cliff = 0; + uint256 beforeGas = gasleft(); - lockup.createWithDurationsLL(params, durations); + lockup.createWithDurationsLL(params, unlockAmounts, durations); string memory gasUsed = vm.toString(beforeGas - gasleft()); string memory cliffSetOrNot = cliffDuration == 0 ? " (cliff not set)" : " (cliff set)"; @@ -73,7 +76,7 @@ contract Lockup_Linear_Gas_Test is Benchmark_Test { params.totalAmount = _calculateTotalAmount(defaults.DEPOSIT_AMOUNT(), ud(0)); beforeGas = gasleft(); - lockup.createWithDurationsLL(params, durations); + lockup.createWithDurationsLL(params, unlockAmounts, durations); gasUsed = vm.toString(beforeGas - gasleft()); contentToAppend = @@ -88,9 +91,11 @@ contract Lockup_Linear_Gas_Test is Benchmark_Test { resetPrank({ msgSender: users.sender }); Lockup.CreateWithTimestamps memory params = defaults.createWithTimestamps(); + LockupLinear.UnlockAmounts memory unlockAmounts = defaults.unlockAmounts(); + if (cliffTime == 0) unlockAmounts.cliff = 0; uint256 beforeGas = gasleft(); - lockup.createWithTimestampsLL(params, cliffTime); + lockup.createWithTimestampsLL(params, unlockAmounts, cliffTime); string memory gasUsed = vm.toString(beforeGas - gasleft()); string memory cliffSetOrNot = cliffTime == 0 ? " (cliff not set)" : " (cliff set)"; @@ -106,7 +111,7 @@ contract Lockup_Linear_Gas_Test is Benchmark_Test { params.totalAmount = _calculateTotalAmount(defaults.DEPOSIT_AMOUNT(), ud(0)); beforeGas = gasleft(); - lockup.createWithTimestampsLL(params, cliffTime); + lockup.createWithTimestampsLL(params, unlockAmounts, cliffTime); gasUsed = vm.toString(beforeGas - gasleft()); contentToAppend = diff --git a/benchmark/LockupTranched.Gas.t.sol b/benchmark/LockupTranched.Gas.t.sol index 42cae278f..06675fb16 100644 --- a/benchmark/LockupTranched.Gas.t.sol +++ b/benchmark/LockupTranched.Gas.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { UD60x18, ud } from "@prb/math/src/UD60x18.sol"; -import { Lockup, LockupTranched } from "../src/core/types/DataTypes.sol"; +import { Lockup, LockupTranched } from "../src//types/DataTypes.sol"; import { Benchmark_Test } from "./Benchmark.t.sol"; diff --git a/benchmark/results/SablierBatchLockup.md b/benchmark/results/SablierBatchLockup.md index 3a154f1dd..5ce68d2a8 100644 --- a/benchmark/results/SablierBatchLockup.md +++ b/benchmark/results/SablierBatchLockup.md @@ -2,33 +2,33 @@ | Function | Lockup Type | Segments/Tranches | Batch Size | Gas Usage | | ------------------------ | --------------- | ----------------- | ---------- | --------- | -| `createWithDurationsLL` | Lockup Linear | N/A | 5 | 778232 | -| `createWithTimestampsLL` | Lockup Linear | N/A | 5 | 738090 | -| `createWithDurationsLD` | Lockup Dynamic | 24 | 5 | 4117172 | -| `createWithTimestampsLD` | Lockup Dynamic | 24 | 5 | 3887412 | -| `createWithDurationsLT` | Lockup Tranched | 24 | 5 | 3993178 | -| `createWithTimestampsLT` | Lockup Tranched | 24 | 5 | 3806069 | -| `createWithDurationsLL` | Lockup Linear | N/A | 10 | 1423058 | -| `createWithTimestampsLL` | Lockup Linear | N/A | 10 | 1425240 | -| `createWithDurationsLD` | Lockup Dynamic | 24 | 10 | 8189792 | -| `createWithTimestampsLD` | Lockup Dynamic | 24 | 10 | 7725792 | -| `createWithDurationsLT` | Lockup Tranched | 24 | 10 | 7934383 | -| `createWithTimestampsLT` | Lockup Tranched | 24 | 10 | 7563478 | -| `createWithDurationsLL` | Lockup Linear | N/A | 20 | 2795598 | -| `createWithTimestampsLL` | Lockup Linear | N/A | 20 | 2801161 | -| `createWithDurationsLD` | Lockup Dynamic | 24 | 20 | 16350772 | -| `createWithTimestampsLD` | Lockup Dynamic | 24 | 20 | 15407205 | -| `createWithDurationsLT` | Lockup Tranched | 24 | 20 | 15815419 | -| `createWithTimestampsLT` | Lockup Tranched | 24 | 20 | 15082887 | -| `createWithDurationsLL` | Lockup Linear | N/A | 30 | 4162811 | -| `createWithTimestampsLL` | Lockup Linear | N/A | 30 | 4181289 | -| `createWithDurationsLD` | Lockup Dynamic | 24 | 30 | 24549048 | -| `createWithTimestampsLD` | Lockup Dynamic | 24 | 30 | 23102525 | -| `createWithDurationsLT` | Lockup Tranched | 24 | 30 | 23696100 | -| `createWithTimestampsLT` | Lockup Tranched | 24 | 30 | 22616357 | -| `createWithDurationsLL` | Lockup Linear | N/A | 50 | 6903841 | -| `createWithTimestampsLL` | Lockup Linear | N/A | 50 | 6947495 | -| `createWithDurationsLD` | Lockup Dynamic | 12 | 50 | 24028066 | -| `createWithTimestampsLD` | Lockup Dynamic | 12 | 50 | 22808040 | -| `createWithDurationsLT` | Lockup Tranched | 12 | 50 | 23292554 | -| `createWithTimestampsLT` | Lockup Tranched | 12 | 50 | 22433243 | +| `createWithDurationsLL` | Lockup Linear | N/A | 5 | 903159 | +| `createWithTimestampsLL` | Lockup Linear | N/A | 5 | 861441 | +| `createWithDurationsLD` | Lockup Dynamic | 24 | 5 | 4120769 | +| `createWithTimestampsLD` | Lockup Dynamic | 24 | 5 | 3891095 | +| `createWithDurationsLT` | Lockup Tranched | 24 | 5 | 3996698 | +| `createWithTimestampsLT` | Lockup Tranched | 24 | 5 | 3809816 | +| `createWithDurationsLL` | Lockup Linear | N/A | 10 | 1673021 | +| `createWithTimestampsLL` | Lockup Linear | N/A | 10 | 1672189 | +| `createWithDurationsLD` | Lockup Dynamic | 24 | 10 | 8197426 | +| `createWithTimestampsLD` | Lockup Dynamic | 24 | 10 | 7733344 | +| `createWithDurationsLT` | Lockup Tranched | 24 | 10 | 7941453 | +| `createWithTimestampsLT` | Lockup Tranched | 24 | 10 | 7571162 | +| `createWithDurationsLL` | Lockup Linear | N/A | 20 | 3296857 | +| `createWithTimestampsLL` | Lockup Linear | N/A | 20 | 3295805 | +| `createWithDurationsLD` | Lockup Dynamic | 24 | 20 | 16367660 | +| `createWithTimestampsLD` | Lockup Dynamic | 24 | 20 | 15422847 | +| `createWithDurationsLT` | Lockup Tranched | 24 | 20 | 15829541 | +| `createWithTimestampsLT` | Lockup Tranched | 24 | 20 | 15098785 | +| `createWithDurationsLL` | Lockup Linear | N/A | 30 | 4918016 | +| `createWithTimestampsLL` | Lockup Linear | N/A | 30 | 4924864 | +| `createWithDurationsLD` | Lockup Dynamic | 24 | 30 | 24577948 | +| `createWithTimestampsLD` | Lockup Dynamic | 24 | 30 | 23127215 | +| `createWithDurationsLT` | Lockup Tranched | 24 | 30 | 23717265 | +| `createWithTimestampsLT` | Lockup Tranched | 24 | 30 | 22641404 | +| `createWithDurationsLL` | Lockup Linear | N/A | 50 | 8178730 | +| `createWithTimestampsLL` | Lockup Linear | N/A | 50 | 8190836 | +| `createWithDurationsLD` | Lockup Dynamic | 12 | 50 | 24075414 | +| `createWithTimestampsLD` | Lockup Dynamic | 12 | 50 | 22851294 | +| `createWithDurationsLT` | Lockup Tranched | 12 | 50 | 23330071 | +| `createWithTimestampsLT` | Lockup Tranched | 12 | 50 | 22477363 | diff --git a/benchmark/results/SablierLockup_Dynamic.md b/benchmark/results/SablierLockup_Dynamic.md index 3d5bce19c..cc2532d30 100644 --- a/benchmark/results/SablierLockup_Dynamic.md +++ b/benchmark/results/SablierLockup_Dynamic.md @@ -2,30 +2,30 @@ | Implementation | Gas Usage | | ------------------------------------------------------------ | --------- | -| `burn` | 15759 | -| `cancel` | 68674 | -| `renounce` | 37726 | -| `createWithDurationsLD` (2 segments) (Broker fee set) | 210925 | -| `createWithDurationsLD` (2 segments) (Broker fee not set) | 194672 | -| `createWithTimestampsLD` (2 segments) (Broker fee set) | 191434 | -| `createWithTimestampsLD` (2 segments) (Broker fee not set) | 186483 | -| `withdraw` (2 segments) (After End Time) (by Recipient) | 19035 | -| `withdraw` (2 segments) (Before End Time) (by Recipient) | 28249 | -| `withdraw` (2 segments) (After End Time) (by Anyone) | 14291 | -| `withdraw` (2 segments) (Before End Time) (by Anyone) | 28305 | -| `createWithDurationsLD` (10 segments) (Broker fee set) | 418459 | -| `createWithDurationsLD` (10 segments) (Broker fee not set) | 413521 | -| `createWithTimestampsLD` (10 segments) (Broker fee set) | 398011 | -| `createWithTimestampsLD` (10 segments) (Broker fee not set) | 393076 | -| `withdraw` (10 segments) (After End Time) (by Recipient) | 14222 | -| `withdraw` (10 segments) (Before End Time) (by Recipient) | 35552 | -| `withdraw` (10 segments) (After End Time) (by Anyone) | 14299 | -| `withdraw` (10 segments) (Before End Time) (by Anyone) | 35608 | -| `createWithDurationsLD` (100 segments) (Broker fee set) | 2918719 | -| `createWithDurationsLD` (100 segments) (Broker fee not set) | 2914766 | -| `createWithTimestampsLD` (100 segments) (Broker fee set) | 2726237 | -| `createWithTimestampsLD` (100 segments) (Broker fee not set) | 2722308 | -| `withdraw` (100 segments) (After End Time) (by Recipient) | 14222 | -| `withdraw` (100 segments) (Before End Time) (by Recipient) | 118136 | -| `withdraw` (100 segments) (After End Time) (by Anyone) | 14278 | -| `withdraw` (100 segments) (Before End Time) (by Anyone) | 118192 | +| `burn` | 15791 | +| `cancel` | 65885 | +| `renounce` | 27466 | +| `createWithDurationsLD` (2 segments) (Broker fee set) | 211605 | +| `createWithDurationsLD` (2 segments) (Broker fee not set) | 195353 | +| `createWithTimestampsLD` (2 segments) (Broker fee set) | 192136 | +| `createWithTimestampsLD` (2 segments) (Broker fee not set) | 187185 | +| `withdraw` (2 segments) (After End Time) (by Recipient) | 19121 | +| `withdraw` (2 segments) (Before End Time) (by Recipient) | 28328 | +| `withdraw` (2 segments) (After End Time) (by Anyone) | 14377 | +| `withdraw` (2 segments) (Before End Time) (by Anyone) | 28384 | +| `createWithDurationsLD` (10 segments) (Broker fee set) | 419147 | +| `createWithDurationsLD` (10 segments) (Broker fee not set) | 414209 | +| `createWithTimestampsLD` (10 segments) (Broker fee set) | 398718 | +| `createWithTimestampsLD` (10 segments) (Broker fee not set) | 393783 | +| `withdraw` (10 segments) (After End Time) (by Recipient) | 14308 | +| `withdraw` (10 segments) (Before End Time) (by Recipient) | 35631 | +| `withdraw` (10 segments) (After End Time) (by Anyone) | 14385 | +| `withdraw` (10 segments) (Before End Time) (by Anyone) | 35687 | +| `createWithDurationsLD` (100 segments) (Broker fee set) | 2919492 | +| `createWithDurationsLD` (100 segments) (Broker fee not set) | 2915538 | +| `createWithTimestampsLD` (100 segments) (Broker fee set) | 2727003 | +| `createWithTimestampsLD` (100 segments) (Broker fee not set) | 2723074 | +| `withdraw` (100 segments) (After End Time) (by Recipient) | 14308 | +| `withdraw` (100 segments) (Before End Time) (by Recipient) | 118217 | +| `withdraw` (100 segments) (After End Time) (by Anyone) | 14364 | +| `withdraw` (100 segments) (Before End Time) (by Anyone) | 118273 | diff --git a/benchmark/results/SablierLockup_Linear.md b/benchmark/results/SablierLockup_Linear.md index f62e872ea..ecbd9521f 100644 --- a/benchmark/results/SablierLockup_Linear.md +++ b/benchmark/results/SablierLockup_Linear.md @@ -2,18 +2,18 @@ | Implementation | Gas Usage | | ------------------------------------------------------------- | --------- | -| `burn` | 15759 | -| `cancel` | 68674 | -| `renounce` | 37726 | -| `createWithDurationsLL` (Broker fee set) (cliff not set) | 131057 | -| `createWithDurationsLL` (Broker fee not set) (cliff not set) | 114740 | -| `createWithDurationsLL` (Broker fee set) (cliff set) | 139354 | -| `createWithDurationsLL` (Broker fee not set) (cliff set) | 134336 | -| `createWithTimestampsLL` (Broker fee set) (cliff not set) | 116950 | -| `createWithTimestampsLL` (Broker fee not set) (cliff not set) | 111929 | -| `createWithTimestampsLL` (Broker fee set) (cliff set) | 139254 | -| `createWithTimestampsLL` (Broker fee not set) (cliff set) | 134231 | -| `withdraw` (After End Time) (by Recipient) | 29422 | -| `withdraw` (Before End Time) (by Recipient) | 22353 | -| `withdraw` (After End Time) (by Anyone) | 24678 | -| `withdraw` (Before End Time) (by Anyone) | 20457 | +| `burn` | 15791 | +| `cancel` | 65885 | +| `renounce` | 27466 | +| `createWithDurationsLL` (Broker fee set) (cliff not set) | 133431 | +| `createWithDurationsLL` (Broker fee not set) (cliff not set) | 117148 | +| `createWithDurationsLL` (Broker fee set) (cliff set) | 163961 | +| `createWithDurationsLL` (Broker fee not set) (cliff set) | 158978 | +| `createWithTimestampsLL` (Broker fee set) (cliff not set) | 118944 | +| `createWithTimestampsLL` (Broker fee not set) (cliff not set) | 113957 | +| `createWithTimestampsLL` (Broker fee set) (cliff set) | 163481 | +| `createWithTimestampsLL` (Broker fee not set) (cliff set) | 158494 | +| `withdraw` (After End Time) (by Recipient) | 29508 | +| `withdraw` (Before End Time) (by Recipient) | 21608 | +| `withdraw` (After End Time) (by Anyone) | 24764 | +| `withdraw` (Before End Time) (by Anyone) | 21420 | diff --git a/benchmark/results/SablierLockup_Tranched.md b/benchmark/results/SablierLockup_Tranched.md index 15e9b513f..9a768d1a0 100644 --- a/benchmark/results/SablierLockup_Tranched.md +++ b/benchmark/results/SablierLockup_Tranched.md @@ -2,30 +2,30 @@ | Implementation | Gas Usage | | ------------------------------------------------------------ | --------- | -| `burn` | 15759 | -| `cancel` | 68674 | -| `renounce` | 37726 | -| `createWithDurationsLT` (2 tranches) (Broker fee set) | 209043 | -| `createWithDurationsLT` (2 tranches) (Broker fee not set) | 192794 | -| `createWithTimestampsLT` (2 tranches) (Broker fee set) | 191023 | -| `createWithTimestampsLT` (2 tranches) (Broker fee not set) | 186072 | -| `withdraw` (2 tranches) (After End Time) (by Recipient) | 19035 | -| `withdraw` (2 tranches) (Before End Time) (by Recipient) | 16714 | -| `withdraw` (2 tranches) (After End Time) (by Anyone) | 14292 | -| `withdraw` (2 tranches) (Before End Time) (by Anyone) | 16770 | -| `createWithDurationsLT` (10 tranches) (Broker fee set) | 408861 | -| `createWithDurationsLT` (10 tranches) (Broker fee not set) | 403916 | -| `createWithTimestampsLT` (10 tranches) (Broker fee set) | 392335 | -| `createWithTimestampsLT` (10 tranches) (Broker fee not set) | 387399 | -| `withdraw` (10 tranches) (After End Time) (by Recipient) | 14235 | -| `withdraw` (10 tranches) (Before End Time) (by Recipient) | 23465 | -| `withdraw` (10 tranches) (After End Time) (by Anyone) | 14298 | -| `withdraw` (10 tranches) (Before End Time) (by Anyone) | 23521 | -| `createWithDurationsLT` (100 tranches) (Broker fee set) | 2818875 | -| `createWithDurationsLT` (100 tranches) (Broker fee not set) | 2814433 | -| `createWithTimestampsLT` (100 tranches) (Broker fee set) | 2659191 | -| `createWithTimestampsLT` (100 tranches) (Broker fee not set) | 2654768 | -| `withdraw` (100 tranches) (After End Time) (by Recipient) | 14222 | -| `withdraw` (100 tranches) (Before End Time) (by Recipient) | 99780 | -| `withdraw` (100 tranches) (After End Time) (by Anyone) | 14278 | -| `withdraw` (100 tranches) (Before End Time) (by Anyone) | 99836 | +| `burn` | 15791 | +| `cancel` | 65885 | +| `renounce` | 27466 | +| `createWithDurationsLT` (2 tranches) (Broker fee set) | 209723 | +| `createWithDurationsLT` (2 tranches) (Broker fee not set) | 193473 | +| `createWithTimestampsLT` (2 tranches) (Broker fee set) | 191747 | +| `createWithTimestampsLT` (2 tranches) (Broker fee not set) | 186795 | +| `withdraw` (2 tranches) (After End Time) (by Recipient) | 19121 | +| `withdraw` (2 tranches) (Before End Time) (by Recipient) | 16808 | +| `withdraw` (2 tranches) (After End Time) (by Anyone) | 14378 | +| `withdraw` (2 tranches) (Before End Time) (by Anyone) | 16864 | +| `createWithDurationsLT` (10 tranches) (Broker fee set) | 409546 | +| `createWithDurationsLT` (10 tranches) (Broker fee not set) | 404601 | +| `createWithTimestampsLT` (10 tranches) (Broker fee set) | 393063 | +| `createWithTimestampsLT` (10 tranches) (Broker fee not set) | 388126 | +| `withdraw` (10 tranches) (After End Time) (by Recipient) | 14321 | +| `withdraw` (10 tranches) (Before End Time) (by Recipient) | 23704 | +| `withdraw` (10 tranches) (After End Time) (by Anyone) | 14384 | +| `withdraw` (10 tranches) (Before End Time) (by Anyone) | 23760 | +| `createWithDurationsLT` (100 tranches) (Broker fee set) | 2819619 | +| `createWithDurationsLT` (100 tranches) (Broker fee not set) | 2815177 | +| `createWithTimestampsLT` (100 tranches) (Broker fee set) | 2659961 | +| `createWithTimestampsLT` (100 tranches) (Broker fee not set) | 2655537 | +| `withdraw` (100 tranches) (After End Time) (by Recipient) | 14308 | +| `withdraw` (100 tranches) (Before End Time) (by Recipient) | 101639 | +| `withdraw` (100 tranches) (After End Time) (by Anyone) | 14364 | +| `withdraw` (100 tranches) (Before End Time) (by Anyone) | 101695 | diff --git a/codecov.yml b/codecov.yml index c4868077c..1ab56482e 100644 --- a/codecov.yml +++ b/codecov.yml @@ -7,6 +7,6 @@ coverage: ignore: - "precompiles" - "script" - - "src/core/libraries/NFTSVG.sol" - - "src/core/libraries/SVGElements.sol" + - "src/libraries/NFTSVG.sol" + - "src/libraries/SVGElements.sol" - "test" diff --git a/foundry.toml b/foundry.toml index 70f9532a8..3aade3789 100644 --- a/foundry.toml +++ b/foundry.toml @@ -41,8 +41,8 @@ # https://book.getfoundry.sh/reference/config/solidity-compiler#libraries # TODO: Update addresses once deployed. libraries = [ - "src/core/libraries/Helpers.sol:Helpers:0x7715bE116061E014Bb721b46Dc78Dd57C91FDF9b", - "src/core/libraries/VestingMath.sol:VestingMath:0x26F9d826BDed47Fc472526aE8095B75ac336963C" + "src/libraries/Helpers.sol:Helpers:0x7715bE116061E014Bb721b46Dc78Dd57C91FDF9b", + "src/libraries/VestingMath.sol:VestingMath:0x26F9d826BDed47Fc472526aE8095B75ac336963C" ] out = "out-optimized" test = "test/mocks" @@ -76,8 +76,8 @@ ] [profile.smt.model_checker.contracts] - "src/core/LockupNFTDescriptor.sol" = ["LockupNFTDescriptor"] - "src/core/SablierLockup.sol" = ["SablierLockup"] + "src/LockupNFTDescriptor.sol" = ["LockupNFTDescriptor"] + "src/SablierLockup.sol" = ["SablierLockup"] # Test the optimized contracts without re-compiling them [profile.test-optimized] diff --git a/package.json b/package.json index 4e4d77e4c..c38025a3b 100644 --- a/package.json +++ b/package.json @@ -75,10 +75,8 @@ "prepare": "husky", "prettier:check": "prettier --check \"**/*.{json,md,svg,yml}\"", "prettier:write": "prettier --write \"**/*.{json,md,svg,yml}\"", - "test": "forge test", - "test:core": "FOUNDRY_PROFILE=lite forge test --match-path \"test/core/**/*.sol\" --nmt \"testFork\"", + "test": "forge test --nmt \"testFork\"", "test:lite": "FOUNDRY_PROFILE=lite forge test", - "test:optimized": "bun run build:optimized && FOUNDRY_PROFILE=test-optimized forge test", - "test:periphery": "FOUNDRY_PROFILE=lite forge test --match-path \"test/periphery/**/*.sol\" --nmt \"testFork\"" + "test:optimized": "bun run build:optimized && FOUNDRY_PROFILE=test-optimized forge test" } } diff --git a/precompiles/Precompiles.sol b/precompiles/Precompiles.sol index bed370067..10163f298 100644 --- a/precompiles/Precompiles.sol +++ b/precompiles/Precompiles.sol @@ -2,11 +2,10 @@ // solhint-disable max-line-length,no-inline-assembly,reason-string pragma solidity >=0.8.22; -import { ILockupNFTDescriptor } from "./../src/core/interfaces/ILockupNFTDescriptor.sol"; -import { ISablierBatchLockup } from "./../src/core/interfaces/ISablierBatchLockup.sol"; -import { ISablierLockup } from "./../src/core/interfaces/ISablierLockup.sol"; -import { LockupNFTDescriptor } from "./../src/core/LockupNFTDescriptor.sol"; -import { ISablierMerkleFactory } from "./../src/periphery/interfaces/ISablierMerkleFactory.sol"; +import { ILockupNFTDescriptor } from "./../src/interfaces/ILockupNFTDescriptor.sol"; +import { ISablierBatchLockup } from "./../src/interfaces/ISablierBatchLockup.sol"; +import { ISablierLockup } from "./../src/interfaces/ISablierLockup.sol"; +import { LockupNFTDescriptor } from "./../src/LockupNFTDescriptor.sol"; /// @notice This is useful for external integrations seeking to test against the exact deployed bytecode, as recompiling /// with via IR enabled would be time-consuming. @@ -19,18 +18,16 @@ contract Precompiles { //////////////////////////////////////////////////////////////////////////*/ bytes public constant BYTECODE_BATCH_LOCKUP = - hex"60808060405234601557611744908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806337266dd314610cc857806349a32c4014610a36578063606ef875146107d55780639e743f29146105fb578063a10679d11461036f5763f7ca34eb1461005b575f80fd5b346102cf5761006936610f55565b928392919215610347579092905f90815b83811061031c57506001600160a01b036100979116918583611404565b6100a0826110e3565b926001600160a01b035f9516945b8381106100c757604051806100c38782610fd1565b0390f35b6100df6100d582868561131c565b60c08101906112a2565b6100ed6100d584888761131c565b5f19019182101590506103085761010b91606060409202010161133f565b9061020861012261011d83888761131c565b611115565b926101bb61013c6020610136868b8a61131c565b01611115565b91866001600160801b038a6001600160a01b0360e06101c98a61016b604061016583888b61131c565b0161102c565b94610182606061017c84848c61131c565b01611129565b9764ffffffffff610199608061017c86868661131c565b9a816101b160a06101ab88888861131c565b0161133f565b6040519e8f611070565b168d521660208c015261131c565b0196816040519b6101d98d61108c565b168b521660208a01521660408801528b606088015215156080870152151560a086015260c08501523690611136565b60e083015261021b6100d582878661131c565b9290836040519485937f1b1a433f00000000000000000000000000000000000000000000000000000000855261025a6101648601916004870190611351565b61016061014486015252610184830191905f905b8082106102e657505050908060209203815f885af180156102db575f906102a5575b6001925061029e828861127d565b52016100ae565b506020823d82116102d3575b816102be602093836110a9565b810103126102cf5760019151610290565b5f80fd5b3d91506102b1565b6040513d5f823e3d90fd5b91935091606080826102fa600194886112d8565b01940192018593929161026e565b634e487b7160e01b5f52603260045260245ffd5b916001906001600160801b0361033b604061016587898b9c9a9c61131c565b1601920194929461007a565b7f36186274000000000000000000000000000000000000000000000000000000005f5260045ffd5b346102cf5760603660031901126102cf57610388610f29565b610390610f3f565b6044359067ffffffffffffffff82116102cf57366023830112156102cf57816004013567ffffffffffffffff81116102cf5760248301926024369161014084020101116102cf578015610347575f935f5b8281106105d657506001600160a01b036103fe9116948386611404565b610407816110e3565b926001600160a01b035f9316925b82811061042a57604051806100c38782610fd1565b61043861011d8285856113f3565b9061044960206101368387876113f3565b61045960406101658488886113f3565b9061046a606061017c8589896113f3565b61047a608061017c868a8a6113f3565b906001600160801b0361048e868a8a6113f3565b946001600160a01b036101006104a5898d8d6113f3565b0195816040519a6104b58c61108c565b168a5216602089015216604087015288606087015215156080860152151560a08501526040609f1983360301126102cf576105219161051060c0604051926104fc84611070565b61050860a0820161123e565b84520161123e565b602082015260c08501523690611136565b60e083015264ffffffffff61053c60e06101ab8488886113f3565b610570604051947fab605ced0000000000000000000000000000000000000000000000000000000086526004860190611351565b16610144830152602082610164815f8b5af180156102db575f906105a4575b6001925061059d828861127d565b5201610415565b506020823d82116105ce575b816105bd602093836110a9565b810103126102cf576001915161058f565b3d91506105b0565b946001906001600160801b036105f260406101658a888b6113f3565b160195016103e1565b346102cf5761060936610f55565b928392919215610347579092905f90815b8381106107aa57506001600160a01b036106379116918583611404565b610640826110e3565b926001600160a01b035f9516945b83811061066357604051806100c38782610fd1565b61067b61067182868561131c565b60c081019061116f565b61068961067184888761131c565b5f1901918210159050610308576106a79160209160061b010161133f565b906106b961012261011d83888761131c565b60e08301526106cc61067182878661131c565b9290836040519485937fd6a03d3100000000000000000000000000000000000000000000000000000000855261070b6101648601916004870190611351565b61016061014486015252610184830191905f905b80821061078857505050908060209203815f885af180156102db575f90610756575b6001925061074f828861127d565b520161064e565b506020823d8211610780575b8161076f602093836110a9565b810103126102cf5760019151610741565b3d9150610762565b919350916040808261079c60019488611250565b01940192018593929161071f565b916001906001600160801b036107c9604061016587898b9c9a9c61131c565b1601920194929461061a565b346102cf576107e336610f55565b928392919215610347579092905f90815b838110610a0b57506001600160a01b036108119116918583611404565b61081a826110e3565b926001600160a01b035f9516945b83811061083d57604051806100c38782610fd1565b61084881858461100a565b61085190611115565b9061085d81868561100a565b60200161086990611115565b61087482878661100a565b6040016108809061102c565b61088b83888761100a565b60600161089790611129565b6108a284898861100a565b6080016108ae90611129565b916108ba858a8961100a565b60c00193604051966108cb88611040565b6001600160a01b031687526001600160a01b031660208701526001600160801b0316604086015289606086015215156080850152151560a08401523661091091611136565b60c083015261092081868561100a565b60a0810161092d916112a2565b9290836040519485937f42e94a7b0000000000000000000000000000000000000000000000000000000085526101248501906004860161096c916111a5565b61012061010486015252610144830191905f905b8082106109e957505050908060209203815f885af180156102db575f906109b7575b600192506109b0828861127d565b5201610828565b506020823d82116109e1575b816109d0602093836110a9565b810103126102cf57600191516109a2565b3d91506109c3565b91935091606080826109fd600194886112d8565b019401920185939291610980565b916001906001600160801b03610a2a604061016587898b9c9a9c61100a565b160192019492946107f4565b346102cf5760603660031901126102cf57610a4f610f29565b610a57610f3f565b6044359067ffffffffffffffff82116102cf57366023830112156102cf57816004013567ffffffffffffffff81116102cf5760248301926024369161012084020101116102cf57801561034757905f935f5b838110610c9d57506001600160a01b03610ac69116948286611404565b610acf826110e3565b926001600160a01b035f9216915b838110610af257604051806100c38782610fd1565b610afd818584611291565b610b0690611115565b90610b12818685611291565b602001610b1e90611115565b610b29828786611291565b604001610b359061102c565b610b40838887611291565b606001610b4c90611129565b610b57848988611291565b608001610b6390611129565b91610b6f858a89611291565b60e0019360405196610b8088611040565b6001600160a01b031687526001600160a01b031660208701526001600160801b0316604086015286606086015215156080850152151560a084015236610bc591611136565b60c0830152610bd5818685611291565b604051927f8222b69400000000000000000000000000000000000000000000000000000000845260048401610c09916111a5565b610c1560a0820161123e565b64ffffffffff1661010484015260c001610c2e9061123e565b64ffffffffff166101248301528180885a925f61014492602095f180156102db575f90610c6b575b60019250610c64828861127d565b5201610add565b506020823d8211610c95575b81610c84602093836110a9565b810103126102cf5760019151610c56565b3d9150610c77565b946001906001600160801b03610cbc60406101658a898b9a999a611291565b16019501929192610aa9565b346102cf57610cd636610f55565b928392919215610347579092905f90815b838110610efe57506001600160a01b03610d049116918583611404565b610d0d826110e3565b926001600160a01b035f9516945b838110610d3057604051806100c38782610fd1565b610d3b81858461100a565b610d4490611115565b90610d5081868561100a565b602001610d5c90611115565b610d6782878661100a565b604001610d739061102c565b610d7e83888761100a565b606001610d8a90611129565b610d9584898861100a565b608001610da190611129565b91610dad858a8961100a565b60c0019360405196610dbe88611040565b6001600160a01b031687526001600160a01b031660208701526001600160801b0316604086015289606086015215156080850152151560a084015236610e0391611136565b60c0830152610e1381868561100a565b60a08101610e209161116f565b9290836040519485937f6611ceab00000000000000000000000000000000000000000000000000000000855261012485019060048601610e5f916111a5565b61012061010486015252610144830191905f905b808210610edc57505050908060209203815f885af180156102db575f90610eaa575b60019250610ea3828861127d565b5201610d1b565b506020823d8211610ed4575b81610ec3602093836110a9565b810103126102cf5760019151610e95565b3d9150610eb6565b9193509160408082610ef060019488611250565b019401920185939291610e73565b916001906001600160801b03610f1d604061016587898b9c9a9c61100a565b16019201949294610ce7565b600435906001600160a01b03821682036102cf57565b602435906001600160a01b03821682036102cf57565b9060606003198301126102cf576004356001600160a01b03811681036102cf57916024356001600160a01b03811681036102cf579160443567ffffffffffffffff81116102cf5760040182601f820112156102cf5780359267ffffffffffffffff84116102cf576020808301928560051b0101116102cf579190565b60206040818301928281528451809452019201905f5b818110610ff45750505090565b8251845260209384019390920191600101610fe7565b91908110156103085760051b8101359060fe19813603018212156102cf570190565b356001600160801b03811681036102cf5790565b60e0810190811067ffffffffffffffff82111761105c57604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff82111761105c57604052565b610100810190811067ffffffffffffffff82111761105c57604052565b90601f8019910116810190811067ffffffffffffffff82111761105c57604052565b67ffffffffffffffff811161105c5760051b60200190565b906110ed826110cb565b6110fa60405191826110a9565b828152809261110b601f19916110cb565b0190602036910137565b356001600160a01b03811681036102cf5790565b3580151581036102cf5790565b91908260409103126102cf5760405161114e81611070565b809280356001600160a01b03811681036102cf578252602090810135910152565b903590601e19813603018212156102cf570180359067ffffffffffffffff82116102cf57602001918160061b360383136102cf57565b9060c080611228936001600160a01b0381511684526001600160a01b0360208201511660208501526001600160801b0360408201511660408501526001600160a01b03606082015116606085015260808101511515608085015260a0810151151560a08501520151910190602080916001600160a01b0381511684520151910152565b565b35906001600160801b03821682036102cf57565b359064ffffffffff821682036102cf57565b64ffffffffff611277602080936001600160801b0361126e8261122a565b1686520161123e565b16910152565b80518210156103085760209160051b010190565b919081101561030857610120020190565b903590601e19813603018212156102cf570180359067ffffffffffffffff82116102cf576020019160608202360383136102cf57565b6001600160801b036112e98261122a565b168252602081013567ffffffffffffffff81168091036102cf576112776040809364ffffffffff9360208701520161123e565b91908110156103085760051b8101359061011e19813603018212156102cf570190565b3564ffffffffff811681036102cf5790565b9061010060e0611228936001600160a01b0381511684526001600160a01b0360208201511660208501526001600160801b0360408201511660408501526001600160a01b03606082015116606085015260808101511515608085015260a0810151151560a085015264ffffffffff602060c08301518281511660c0880152015116828501520151910190602080916001600160a01b0381511684520151910152565b919081101561030857610140020190565b91906114596040517f23b872dd000000000000000000000000000000000000000000000000000000006020820152336024820152306044820152836064820152606481526114536084826110a9565b826115e7565b6001600160a01b0381166001600160a01b03604051947fdd62ed3e0000000000000000000000000000000000000000000000000000000086523060048701521693846024820152602081604481855afa80156102db5784915f9161159a575b50106114c5575b50505050565b5f8060405194602086019063095ea7b360e01b82528760248801526044870152604486526114f46064876110a9565b85519082855af19061150461166c565b82611568575b508161155d575b501561151e575b806114bf565b611550611555936040519063095ea7b360e01b602083015260248201525f6044820152604481526114536064826110a9565b6115e7565b5f8080611518565b90503b15155f611511565b80519192508115918215611580575b5050905f61150a565b61159392506020809183010191016115cf565b5f80611577565b9150506020813d6020116115c7575b816115b6602093836110a9565b810103126102cf578390515f6114b8565b3d91506115a9565b908160209103126102cf575180151581036102cf5790565b5f806001600160a01b0361161093169360208151910182865af161160961166c565b90836116ab565b8051908115159182611651575b50506116265750565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b61166492506020809183010191016115cf565b155f8061161d565b3d156116a6573d9067ffffffffffffffff821161105c576040519161169b601f8201601f1916602001846110a9565b82523d5f602084013e565b606090565b906116e857508051156116c057805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b8151158061172e575b6116f9575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b156116f156fea164736f6c634300081a000a"; + hex"608080604052346015576117a3908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806337266dd314610d05578063606ef87514610aa45780636927604e146107c75780639e743f29146105ed578063cb0aab8c1461036f5763f7ca34eb1461005b575f80fd5b346102cf5761006936610f92565b928392919215610347579092905f90815b83811061031c57506001600160a01b036100979116918583611463565b6100a082611120565b926001600160a01b035f9516945b8381106100c757604051806100c3878261100e565b0390f35b6100df6100d582868561142f565b60c08101906112ce565b6100ed6100d584888761142f565b5f19019182101590506103085761010b916060604092020101611359565b9061020861012261011d83888761142f565b611152565b926101bb61013c6020610136868b8a61142f565b01611152565b91866001600160801b038a6001600160a01b0360e06101c98a61016b604061016583888b61142f565b01611069565b94610182606061017c84848c61142f565b01611166565b9764ffffffffff610199608061017c86868661142f565b9a816101b160a06101ab88888861142f565b01611359565b6040519e8f6110ca565b168d521660208c015261142f565b0196816040519b6101d98d6110ad565b168b521660208a01521660408801528b606088015215156080870152151560a086015260c08501523690611173565b60e083015261021b6100d582878661142f565b9290836040519485937f1b1a433f00000000000000000000000000000000000000000000000000000000855261025a610164860191600487019061136b565b61016061014486015252610184830191905f905b8082106102e657505050908060209203815f885af180156102db575f906102a5575b6001925061029e82886112ba565b52016100ae565b506020823d82116102d3575b816102be602093836110e6565b810103126102cf5760019151610290565b5f80fd5b3d91506102b1565b6040513d5f823e3d90fd5b91935091606080826102fa60019488611304565b01940192018593929161026e565b634e487b7160e01b5f52603260045260245ffd5b916001906001600160801b0361033b604061016587898b9c9a9c61142f565b1601920194929461007a565b7f36186274000000000000000000000000000000000000000000000000000000005f5260045ffd5b346102cf5760603660031901126102cf57610388610f66565b610390610f7c565b6044359067ffffffffffffffff82116102cf57366023830112156102cf57816004013567ffffffffffffffff81116102cf5760248301926024369161016084020101116102cf578015610347575f93919291845b8281106105c357506001600160a01b036104019116948486611463565b61040a81611120565b926001600160a01b03165f5b82811061042b57604051806100c3878261100e565b61043961011d828587611452565b906104d761044d602061013684888a611452565b8661045e6040610165868a85611452565b6001600160801b03610476606061017c888c87611452565b916001600160a01b0361012061049d898d610497608061017c84848d611452565b98611452565b0195816040519a6104ad8c61107d565b168a5216602089015216604087015286606087015215156080860152151560a08501523690611173565b60c083015264ffffffffff61055d60c060e06104f485898b611452565b01610543610503868a8c611452565b91610538604051987fad7628cd000000000000000000000000000000000000000000000000000000008a5260048a01906111e2565b61010488019061140d565b8361055060a0830161127b565b166101448701520161127b565b16610164830152602082610184815f8b5af180156102db575f90610591575b6001925061058a82886112ba565b5201610416565b506020823d82116105bb575b816105aa602093836110e6565b810103126102cf576001915161057c565b3d915061059d565b946001906001600160801b036105e160406101658a888a9b9a611452565b160195019392936103e4565b346102cf576105fb36610f92565b928392919215610347579092905f90815b83811061079c57506001600160a01b036106299116918583611463565b61063282611120565b926001600160a01b035f9516945b83811061065557604051806100c3878261100e565b61066d61066382868561142f565b60c08101906111ac565b61067b61066384888761142f565b5f1901918210159050610308576106999160209160061b0101611359565b906106ab61012261011d83888761142f565b60e08301526106be61066382878661142f565b9290836040519485937fd6a03d310000000000000000000000000000000000000000000000000000000085526106fd610164860191600487019061136b565b61016061014486015252610184830191905f905b80821061077a57505050908060209203815f885af180156102db575f90610748575b6001925061074182886112ba565b5201610640565b506020823d8211610772575b81610761602093836110e6565b810103126102cf5760019151610733565b3d9150610754565b919350916040808261078e6001948861128d565b019401920185939291610711565b916001906001600160801b036107bb604061016587898b9c9a9c61142f565b1601920194929461060c565b346102cf5760603660031901126102cf576107e0610f66565b6107e8610f7c565b906044359167ffffffffffffffff83116102cf57366023840112156102cf5782600401359167ffffffffffffffff83116102cf5760248401936024369161018086020101116102cf578215610347579091905f90815b838110610a7957506001600160a01b0361085b9116918483611463565b61086482611120565b926001600160a01b03165f5b83811061088557604051806100c3878261100e565b610890818588611348565b61089990611152565b90846108a682828a611348565b6020016108b290611152565b6108bd83838b611348565b6040016108c990611069565b6108d484848c611348565b6060016108e090611166565b6108eb85858d611348565b6080016108f790611166565b918b86610905818884611348565b9661090f92611348565b610140019360405197610921896110ad565b6001600160a01b031688526001600160a01b031660208801526001600160801b0316604087015286606087015215156080860152151560a0850152609f19823603016040136102cf576109a59161099460c060405192610980846110ca565b61098c60a0820161127b565b84520161127b565b602082015260c08501523690611173565b60e083015264ffffffffff87610a136109d360e06101ab868b6101006109cc83838a611348565b0196611348565b91610a08604051967f7b73dd9d000000000000000000000000000000000000000000000000000000008852600488019061136b565b61014486019061140d565b166101848301526020826101a4815f885af180156102db575f90610a47575b60019250610a4082886112ba565b5201610870565b506020823d8211610a71575b81610a60602093836110e6565b810103126102cf5760019151610a32565b3d9150610a53565b916001906001600160801b03610a98604061016587898c9b9a9b611348565b1601920193929361083e565b346102cf57610ab236610f92565b928392919215610347579092905f90815b838110610cda57506001600160a01b03610ae09116918583611463565b610ae982611120565b926001600160a01b035f9516945b838110610b0c57604051806100c3878261100e565b610b17818584611047565b610b2090611152565b90610b2c818685611047565b602001610b3890611152565b610b43828786611047565b604001610b4f90611069565b610b5a838887611047565b606001610b6690611166565b610b71848988611047565b608001610b7d90611166565b91610b89858a89611047565b60c0019360405196610b9a8861107d565b6001600160a01b031687526001600160a01b031660208701526001600160801b0316604086015289606086015215156080850152151560a084015236610bdf91611173565b60c0830152610bef818685611047565b60a08101610bfc916112ce565b9290836040519485937f42e94a7b00000000000000000000000000000000000000000000000000000000855261012485019060048601610c3b916111e2565b61012061010486015252610144830191905f905b808210610cb857505050908060209203815f885af180156102db575f90610c86575b60019250610c7f82886112ba565b5201610af7565b506020823d8211610cb0575b81610c9f602093836110e6565b810103126102cf5760019151610c71565b3d9150610c92565b9193509160608082610ccc60019488611304565b019401920185939291610c4f565b916001906001600160801b03610cf9604061016587898b9c9a9c611047565b16019201949294610ac3565b346102cf57610d1336610f92565b928392919215610347579092905f90815b838110610f3b57506001600160a01b03610d419116918583611463565b610d4a82611120565b926001600160a01b035f9516945b838110610d6d57604051806100c3878261100e565b610d78818584611047565b610d8190611152565b90610d8d818685611047565b602001610d9990611152565b610da4828786611047565b604001610db090611069565b610dbb838887611047565b606001610dc790611166565b610dd2848988611047565b608001610dde90611166565b91610dea858a89611047565b60c0019360405196610dfb8861107d565b6001600160a01b031687526001600160a01b031660208701526001600160801b0316604086015289606086015215156080850152151560a084015236610e4091611173565b60c0830152610e50818685611047565b60a08101610e5d916111ac565b9290836040519485937f6611ceab00000000000000000000000000000000000000000000000000000000855261012485019060048601610e9c916111e2565b61012061010486015252610144830191905f905b808210610f1957505050908060209203815f885af180156102db575f90610ee7575b60019250610ee082886112ba565b5201610d58565b506020823d8211610f11575b81610f00602093836110e6565b810103126102cf5760019151610ed2565b3d9150610ef3565b9193509160408082610f2d6001948861128d565b019401920185939291610eb0565b916001906001600160801b03610f5a604061016587898b9c9a9c611047565b16019201949294610d24565b600435906001600160a01b03821682036102cf57565b602435906001600160a01b03821682036102cf57565b9060606003198301126102cf576004356001600160a01b03811681036102cf57916024356001600160a01b03811681036102cf579160443567ffffffffffffffff81116102cf5760040182601f820112156102cf5780359267ffffffffffffffff84116102cf576020808301928560051b0101116102cf579190565b60206040818301928281528451809452019201905f5b8181106110315750505090565b8251845260209384019390920191600101611024565b91908110156103085760051b8101359060fe19813603018212156102cf570190565b356001600160801b03811681036102cf5790565b60e0810190811067ffffffffffffffff82111761109957604052565b634e487b7160e01b5f52604160045260245ffd5b610100810190811067ffffffffffffffff82111761109957604052565b6040810190811067ffffffffffffffff82111761109957604052565b90601f8019910116810190811067ffffffffffffffff82111761109957604052565b67ffffffffffffffff81116110995760051b60200190565b9061112a82611108565b61113760405191826110e6565b8281528092611148601f1991611108565b0190602036910137565b356001600160a01b03811681036102cf5790565b3580151581036102cf5790565b91908260409103126102cf5760405161118b816110ca565b809280356001600160a01b03811681036102cf578252602090810135910152565b903590601e19813603018212156102cf570180359067ffffffffffffffff82116102cf57602001918160061b360383136102cf57565b9060c080611265936001600160a01b0381511684526001600160a01b0360208201511660208501526001600160801b0360408201511660408501526001600160a01b03606082015116606085015260808101511515608085015260a0810151151560a08501520151910190602080916001600160a01b0381511684520151910152565b565b35906001600160801b03821682036102cf57565b359064ffffffffff821682036102cf57565b64ffffffffff6112b4602080936001600160801b036112ab82611267565b1686520161127b565b16910152565b80518210156103085760209160051b010190565b903590601e19813603018212156102cf570180359067ffffffffffffffff82116102cf576020019160608202360383136102cf57565b6001600160801b0361131582611267565b168252602081013567ffffffffffffffff81168091036102cf576112b46040809364ffffffffff9360208701520161127b565b919081101561030857610180020190565b3564ffffffffff811681036102cf5790565b9061010060e0611265936001600160a01b0381511684526001600160a01b0360208201511660208501526001600160801b0360408201511660408501526001600160a01b03606082015116606085015260808101511515608085015260a0810151151560a085015264ffffffffff602060c08301518281511660c0880152015116828501520151910190602080916001600160a01b0381511684520151910152565b6001600160801b036112b4602080938361142682611267565b16865201611267565b91908110156103085760051b8101359061011e19813603018212156102cf570190565b919081101561030857610160020190565b91906114b86040517f23b872dd000000000000000000000000000000000000000000000000000000006020820152336024820152306044820152836064820152606481526114b26084826110e6565b82611646565b6001600160a01b0381166001600160a01b03604051947fdd62ed3e0000000000000000000000000000000000000000000000000000000086523060048701521693846024820152602081604481855afa80156102db5784915f916115f9575b5010611524575b50505050565b5f8060405194602086019063095ea7b360e01b82528760248801526044870152604486526115536064876110e6565b85519082855af1906115636116cb565b826115c7575b50816115bc575b501561157d575b8061151e565b6115af6115b4936040519063095ea7b360e01b602083015260248201525f6044820152604481526114b26064826110e6565b611646565b5f8080611577565b90503b15155f611570565b805191925081159182156115df575b5050905f611569565b6115f2925060208091830101910161162e565b5f806115d6565b9150506020813d602011611626575b81611615602093836110e6565b810103126102cf578390515f611517565b3d9150611608565b908160209103126102cf575180151581036102cf5790565b5f806001600160a01b0361166f93169360208151910182865af16116686116cb565b908361170a565b80519081151591826116b0575b50506116855750565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6116c3925060208091830101910161162e565b155f8061167c565b3d15611705573d9067ffffffffffffffff821161109957604051916116fa601f8201601f1916602001846110e6565b82523d5f602084013e565b606090565b90611747575080511561171f57805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b8151158061178d575b611758575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561175056fea164736f6c634300081a000a"; bytes public constant BYTECODE_LOCKUP = - hex"60c0604052346103ce57615f836060813803918261001c816103d2565b9384928339810103126103ce5780516001600160a01b038116908190036103ce5760208201516001600160a01b03811692908390036103ce576040015161006360406103d2565b92601284527114d8589b1a595c88131bd8dadd5c0813919560721b602085015261008d60406103d2565b600a81526905341422d4c4f434b55560b41b6020820152306080525f80546001600160a01b031916851781559093907fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a383516001600160401b0381116102df57600154600181811c911680156103c4575b60208210146102c157601f8111610361575b50602094601f82116001146102fe579481929394955f926102f3575b50508160011b915f199060031b1c1916176001555b82516001600160401b0381116102df57600254600181811c911680156102d5575b60208210146102c157601f811161025e575b506020601f82116001146101fb57819293945f926101f0575b50508160011b915f199060031b1c1916176002555b600880546001600160a01b03191691909117905560a0526001600755604051615b8b90816103f8823960805181614584015260a051818181612108015281816146d401526150450152f35b015190505f80610190565b601f1982169060025f52805f20915f5b8181106102465750958360019596971061022e575b505050811b016002556101a5565b01515f1960f88460031b161c191690555f8080610220565b9192602060018192868b01518155019401920161020b565b60025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c810191602084106102b7575b601f0160051c01905b8181106102ac5750610177565b5f815560010161029f565b9091508190610296565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610165565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061012f565b601f1982169560015f52805f20915f5b88811061034957508360019596979810610331575b505050811b01600155610144565b01515f1960f88460031b161c191690555f8080610323565b9192602060018192868501518155019401920161030e565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f830160051c810191602084106103ba575b601f0160051c01905b8181106103af5750610113565b5f81556001016103a2565b9091508190610399565b90607f1690610101565b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176102df5760405256fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a7146137e057508063027b6744146137be57806306fdde0314613703578063081812fc146136e5578063095ea7b3146135e05780631400ecec1461352f5780631b1a433f1461344f5780631c1cdd4c146133eb5780631e897afb146133065780631e99d569146132e957806323b872dd146132d2578063303acc8514613295578063406887cb1461312657806340e58ee514612e4f578063425d30dd14612dff57806342842e0e14612dd657806342966c6814612bfc57806342e94a7b14612935578063442675701461290f5780634857501f1461289e5780634869e12d146128645780634cc55e11146124bd5780636352211e146122035780636611ceab146122325780636d0cee751461220357806370a082311461219957806375829def1461212b57806377163c1d146120f1578063780a82c8146120525780637cad6cd114611f755780637de6b1db14611e285780637f5799f914611d145780638222b69414611be55780638659c2701461182d5780638f69b993146117ad5780639067b6771461175e57806395d89b4114611656578063a22cb465146115a2578063a80fc07114611551578063ab605ced14611508578063ad35efd4146114bd578063b25645691461146d578063b637b86514611346578063b88d4fde146112bc578063b8a3be6614611287578063b971302a14611239578063bc2be1be146111ea578063c156a11d14610dcb578063c87b56dd14610cc0578063d4dbd20b14610c6f578063d511609f14610c24578063d6a03d3114610b4e578063d975dfed14610b03578063e6c417eb14610a98578063e985e9c514610a3f578063ea5ead19146106fc578063eac8f5b8146106ab578063f590c1761461064f578063f851a4401461062a5763fdd46d60146102b0575f80fd5b34610626576060366003190112610626576004356102cc61390d565b906044356001600160801b038116809103610626576102e961457a565b815f52600a60205260ff600160405f20015460a81c161561061357815f52600a60205260ff600160405f20015460a01c16610600576001600160a01b03831680156105ed57825f5260036020526001600160a01b0360405f2054169384821415806105dc575b6105c25782156105af576001600160801b0361036a85615996565b168084116105955750835f52600a60205282600260405f20015460801c016001600160801b038111610581576103c990855f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b835f52600a6020526103e0600260405f2001614e77565b6001600160801b036104048160208401511692826040818351169201511690613bcc565b16111561054f575b835f52600a602052610430836001600160a01b03600160405f2001541692836159bc565b81847f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051878152a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051858152a18333141580610539575b61049657005b604051926392b9102b60e01b84526004840152336024840152604483015260648201526020816084815f865af190811561052e576392b9102b60e01b916001600160e01b0319915f916104ff575b5016036104ed57005b635f3a039d60e01b5f5260045260245ffd5b610521915060203d602011610527575b6105198183613b4a565b8101906141c4565b5f6104e4565b503d61050f565b6040513d5f823e3d90fd5b50835f52600960205260ff60405f205416610490565b5f848152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b1916905561040c565b634e487b7160e01b5f52601160045260245ffd5b8385632176546160e01b5f5260045260245260445260645ffd5b83633dd1eadf60e21b5f5260045260245ffd5b50826297d0a360e61b5f526004523360245260445260645ffd5b506105e78585614ea9565b1561034f565b826316c90d2760e21b5f5260045260245ffd5b5063449491f560e11b5f5260045260245ffd5b50631643770160e21b5f5260045260245ffd5b5f80fd5b34610626575f3660031901126106265760206001600160a01b035f5416604051908152f35b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a602052602060405f205460f81c6040519015158152f35b631643770160e21b5f5260045260245ffd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a60205260206001600160a01b03600160405f20015416604051908152f35b346106265760403660031901126106265760043561071861390d565b61072182615996565b9161072a61457a565b805f52600a60205260ff600160405f20015460a81c161561069957805f52600a60205260ff600160405f20015460a01c16610a2d576001600160a01b0382168015610a1a57815f5260036020526001600160a01b0360405f205416938482141580610a09575b6109ef576001600160801b03169283156109dc576001600160801b036107b584615996565b168085116109c25750825f52600a60205283600260405f20015460801c016001600160801b0381116105815761081490845f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b825f52600a60205261082b600260405f2001614e77565b6001600160801b0361084f8160208401511692826040818351169201511690613bcc565b161115610990575b825f52600a60205261087b846001600160a01b03600160405f2001541692836159bc565b81837f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051888152a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051848152a1833314158061097a575b6108eb575b602083604051908152f35b604051916392b9102b60e01b8352600483015233602483015260448201528160648201526020816084815f875af190811561052e576392b9102b60e01b916001600160e01b0319915f9161095b575b5016036109485781806108e0565b50635f3a039d60e01b5f5260045260245ffd5b610974915060203d602011610527576105198183613b4a565b8561093a565b50835f52600960205260ff60405f2054166108db565b5f838152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b19169055610857565b8484632176546160e01b5f5260045260245260445260645ffd5b82633dd1eadf60e21b5f5260045260245ffd5b50906297d0a360e61b5f526004523360245260445260645ffd5b50610a148584614ea9565b15610790565b506316c90d2760e21b5f5260045260245ffd5b63449491f560e11b5f5260045260245ffd5b3461062657604036600319011261062657610a586138f7565b6001600160a01b03610a6861390d565b91165f5260066020526001600160a01b0360405f2091165f52602052602060ff60405f2054166040519015158152f35b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a60205260ff600160405f20015460b81c166040516003821015610aef576020918152f35b634e487b7160e01b5f52602160045260245ffd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c161561069957610b3d602091615996565b6001600160801b0360405191168152f35b3461062657366003190161016081126106265761014013610626576101443567ffffffffffffffff811161062657610b8a9036906004016139bf565b610b9261457a565b610b9b36613c25565b90610ba581613d45565b92610bb36040519485613b4a565b818452602084019160061b81019036821161062657915b818310610be5576020610bdd8686614f90565b604051908152f35b6040833603126106265760206040918251610bff81613af4565b610c0886613b96565b8152610c15838701613a47565b83820152815201920191610bca565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a6020526020600260405f20015460801c604051908152f35b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a60205260206001600160801b03600360405f20015416604051908152f35b3461062657602036600319011261062657600435610cdd816141e4565b505f6001600160a01b0360085416916044604051809481937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa801561052e575f90610d4e575b610d4a906040519182916020835260208301906138d2565b0390f35b503d805f833e610d5e8183613b4a565b8101906020818303126106265780519067ffffffffffffffff821161062657019080601f8301121561062657815191610d9683613b6c565b91610da46040519384613b4a565b8383526020848301011161062657610d4a92610dc691602080850191016138b1565b610d32565b3461062657604036600319011261062657600435610de761390d565b610def61457a565b815f52600a60205260ff600160405f20015460a81c161561061357815f5260036020526001600160a01b0360405f20541690610e2b8284614ea9565b156111d3576001600160801b03610e4184615996565b169081158015610eca575b506001600160a01b03811615610eb757610e6e846001600160a01b0392614d3d565b169182610e885783637e27328960e01b5f5260045260245ffd5b8084918403610e9c57602083604051908152f35b9091506364283d7b60e01b5f5260045260245260445260645ffd5b633250574960e11b5f525f60045260245ffd5b610ed261457a565b845f52600a60205260ff600160405f20015460a81c16156111c057845f52600a60205260ff600160405f20015460a01c166111ad57831561119a57845f5260036020526001600160a01b0360405f205416908185141580611189575b61116f5761115c576001600160801b03610f4786615996565b168084116111425750845f52600a60205282600260405f20015460801c016001600160801b03811161058157610fa690865f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b845f52600a602052610fbd600260405f2001614e77565b6001600160801b03610fe18160208401511692826040818351169201511690613bcc565b161115611110575b845f52600a6020526001600160a01b03600160405f2001541661100d8486836159bc565b84867f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051888152a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051878152a180331415806110fa575b15610e4c576040516392b9102b60e01b81528560048201523360248201528460448201528360648201526020816084815f865af190811561052e576392b9102b60e01b916001600160e01b0319915f916110db575b501614610e4c57635f3a039d60e01b5f5260045260245ffd5b6110f4915060203d602011610527576105198183613b4a565b886110c2565b50805f52600960205260ff60405f20541661106d565b5f858152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b19169055610fe9565b8386632176546160e01b5f5260045260245260445260645ffd5b84633dd1eadf60e21b5f5260045260245ffd5b84866297d0a360e61b5f526004523360245260445260645ffd5b506111948287614ea9565b15610f2e565b846316c90d2760e21b5f5260045260245ffd5b8463449491f560e11b5f5260045260245ffd5b84631643770160e21b5f5260045260245ffd5b82634dda2c3960e11b5f526004523360245260445ffd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a602052602064ffffffffff60405f205460a01c16604051908152f35b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a60205260206001600160a01b0360405f205416604051908152f35b34610626576020366003190112610626576004355f52600a602052602060ff600160405f20015460a81c166040519015158152f35b34610626576080366003190112610626576112d56138f7565b6112dd61390d565b6064359167ffffffffffffffff831161062657366023840112156106265782600401359161130a83613b6c565b926113186040519485613b4a565b8084523660248287010111610626576020815f92602461134498018388013785010152604435916140d4565b005b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c161561069957805f52600a60205260ff600160405f20015460b81c166003811015610aef5760010361143c575f52600c60205260405f2080546113b181613d45565b916113bf6040519384613b4a565b81835260208301905f5260205f205f915b8383106113ed5760405160208082528190610d4a90820188613a59565b6001602081926040516113ff81613ac4565b64ffffffffff86546001600160801b038116835267ffffffffffffffff8160801c168584015260c01c1660408201528152019201920191906113d0565b5f52600a60205261146360ff600160405f20015460b81c16637382cd8b60e01b5f52613b88565b600160245260445ffd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a602052602060ff600160405f20015460b01c166040519015158152f35b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699576114f590614ca9565b6040516005821015610aef576020918152f35b3461062657366003190161016081126106265761014013610626576101443564ffffffffff8116810361062657610bdd60209161154361457a565b61154c36613c25565b6154c3565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a60205260206001600160801b03600260405f20015416604051908152f35b34610626576040366003190112610626576115bb6138f7565b60243590811515809203610626576001600160a01b031690811561162a57335f52600660205260405f20825f5260205260405f2060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b507f5b08ba18000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b34610626575f366003190112610626576040515f6002548060011c90600181168015611754575b6020831081146117405782855290811561171c57506001146116be575b610d4a836116aa81850382613b4a565b6040519182916020835260208301906138d2565b91905060025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace915f905b808210611702575090915081016020016116aa61169a565b9192600181602092548385880101520191019092916116ea565b60ff191660208086019190915291151560051b840190910191506116aa905061169a565b634e487b7160e01b5f52602260045260245ffd5b91607f169161167d565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a602052602064ffffffffff60405f205460c81c16604051908152f35b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699576117e590614ca9565b600581101580610aef5760028214908115611821575b811561180f575b6020826040519015158152f35b9050610aef5760046020911482611802565b5050600381145f6117fb565b346106265760203660031901126106265760043567ffffffffffffffff81116106265761185e903690600401613954565b9061186761457a565b5f915b80831061187357005b61187e8382846140af565b359261188861457a565b835f52600a60205260ff600160405f20015460a81c1615611bd257835f52600a60205260ff600160405f20015460a01c165f146118d2578363449491f560e11b5f5260045260245ffd5b909192805f52600a60205260405f205460f81c611bc057611907815f52600a6020526001600160a01b0360405f205416331490565b15611baa5761191581614205565b90805f52600a60205261192d600260405f2001614e77565b916001600160801b038351166001600160801b0382161015611b9757815f52600a60205260ff60405f205460f01c1615611b8457806001600160801b03602081611981948188511603169501511690613bcc565b5f828152600a6020526040902080547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b179055916001600160801b038316908115611b5f575b825f52600a602052600360405f20016001600160801b0382166001600160801b0319825416179055825f52600a6020526001600160a01b0360405f205416835f5260036020526001600160a01b0360405f20541694845f52600a60205285827f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa50611a936001600160a01b03600160405f2001541694611a6b8885886159bc565b604080518b81526001600160801b03808b166020830152909216908201529081906060820190565b0390a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051868152a1845f52600960205260ff60405f205416611ae4575b5050505050600101919061186a565b60405193630d4af11f60e31b855260048501526024840152604483015260648201526020816084815f865af190811561052e57630d4af11f60e31b916001600160e01b0319915f91611b41575b5016036104ed5780808080611ad5565b611b59915060203d8111610527576105198183613b4a565b87611b31565b825f52600a602052600160405f2001600160a01b60ff60a01b198254161790556119cb565b50635c7470b760e01b5f5260045260245ffd5b5063fa36c71760e01b5f5260045260245ffd5b634dda2c3960e11b5f526004523360245260445ffd5b63e707ae4f60e01b5f5260045260245ffd5b83631643770160e21b5f5260045260245ffd5b34610626573660031901610140811261062657610100136106265760403661010319011261062657611c1561457a565b64ffffffffff4216604051611c2981613af4565b8181525f602082018181529164ffffffffff611c436140bf565b16611cfb575b610124359264ffffffffff841684036106265764ffffffffff84602096610bdd965001169052611c77614039565b90611c8061404f565b611c88614065565b6001600160a01b03611c9861407b565b6001600160801b03611ca8614091565b9383611cb26140a0565b96816040519a611cc18c613b10565b168a52168b89015216604087015216606085015215156080840152151560a083015260c0820152611cf136613bec565b60e08201526154c3565b905064ffffffffff611d0b6140bf565b84011690611c49565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c161561069957805f52600a60205260ff600160405f20015460b81c166003811015610aef57600203611df7575f52600d60205260405f208054611d7f81613d45565b91611d8d6040519384613b4a565b81835260208301905f5260205f205f915b838310611dbb5760405160208082528190610d4a908201886139f0565b600160208192604051611dcd81613af4565b64ffffffffff86546001600160801b038116835260801c1683820152815201920192019190611d9e565b5f52600a602052611e1e60ff600160405f20015460b81c16637382cd8b60e01b5f52613b88565b600260245260445ffd5b3461062657602036600319011261062657600435611e4461457a565b805f52600a60205260ff600160405f20015460a81c161561069957611e6881614ca9565b6005811015610aef5760048103611e8c575063449491f560e11b5f5260045260245ffd5b60038103611ea7575063e707ae4f60e01b5f5260045260245ffd5b600214611f6357611ecc815f52600a6020526001600160a01b0360405f205416331490565b15611baa57805f52600a60205260ff60405f205460f01c1615611f51576020817ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7925f52600a825260405f2060ff60f01b19815416905560405190807f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f5f80a28152a1005b635c7470b760e01b5f5260045260245ffd5b63fa36c71760e01b5f5260045260245ffd5b34610626576020366003190112610626576004356001600160a01b038116809103610626576001600160a01b035f541633810361203c575060085490806001600160a01b03198316176008556001600160a01b036040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a26007545f1981019081116105815760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a1005b6331b339a960e21b5f526004523360245260445ffd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c161561069957805f52600a60205260ff600160405f20015460b81c166003811015610aef576120c1575f52600b602052602064ffffffffff60405f205416604051908152f35b5f52600a6020526120e860ff600160405f20015460b81c16637382cd8b60e01b5f52613b88565b5f60245260445ffd5b34610626575f3660031901126106265760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610626576020366003190112610626576121446138f7565b5f546001600160a01b03811633810361203c57506001600160a01b036001600160a01b0319921691829116175f55337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf805f80a3005b34610626576020366003190112610626576001600160a01b036121ba6138f7565b1680156121d7575f526004602052602060405f2054604051908152f35b7f89c62b64000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b346106265760203660031901126106265760206122216004356141e4565b6001600160a01b0360405191168152f35b3461062657366003190161012081126106265761010013610626576101043567ffffffffffffffff81116106265761226e9036906004016139bf565b61227661457a565b6040519182917f66f401dd000000000000000000000000000000000000000000000000000000008352806024840160206004860152526044830191905f5b81811061247957845f8180870381737715be116061e014bb721b46dc78dd57c91fdf9b5af490811561052e575f916123b7575b5080515f198101908111610581578164ffffffffff602061230c610bdd948296614011565b510151166040519061231d82613af4565b64ffffffffff4216825284820152612333614039565b9061233c61404f565b612344614065565b6001600160a01b0361235461407b565b6001600160801b03612364614091565b938361236e6140a0565b96816040519a61237d8c613b10565b168a52168b89015216604087015216606085015215156080840152151560a083015260c08201526123ad36613bec565b60e0820152614f90565b90503d805f833e6123c88183613b4a565b8101906020818303126106265780519067ffffffffffffffff8211610626570181601f82011215610626578051906123ff82613d45565b9261240d6040519485613b4a565b82845260208085019360061b8301019181831161062657602001925b82841061243a5750505050816122e7565b604084830312610626576020604091825161245481613af4565b61245d87613feb565b815261246a838801613fff565b83820152815201930192612429565b919350916040806001926001600160801b0361249488613b96565b16815264ffffffffff6124a960208901613a47565b1660208201520194019101918493926122b4565b346106265760403660031901126106265760043567ffffffffffffffff8111610626576124ee903690600401613954565b60243567ffffffffffffffff81116106265761250e903690600401613954565b61251993919361457a565b808303612835575f5b83811061252b57005b6125368185856140af565b356125428286866140af565b355f5260036020526001600160a01b0360405f205416906125648385896140af565b356001600160801b03811690818103610626575061258061457a565b815f52600a60205260ff600160405f20015460a81c161561061357815f52600a60205260ff600160405f20015460a01c16610600578215610a1a57815f5260036020526001600160a01b0360405f205416928381141580612824575b61280b5781156109dc576001600160801b036125f784615996565b168083116127f15750825f52600a60205281600260405f20015460801c016001600160801b0381116105815761265690845f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b825f52600a60205261266d600260405f2001614e77565b6001600160801b036126918160208401511692826040818351169201511690613bcc565b1611156127bf575b825f52600a6020526001600160a01b03600160405f200154166126bd8383836159bc565b81847f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051878152a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051858152a183331415806127a9575b61272e575b50505050600101612522565b604051926392b9102b60e01b84526004840152336024840152604483015260648201526020816084815f865af190811561052e576392b9102b60e01b916001600160e01b0319915f9161278b575b5016036104ed57808080612722565b6127a3915060203d8111610527576105198183613b4a565b8961277c565b50835f52600960205260ff60405f20541661271d565b5f838152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b19169055612699565b8284632176546160e01b5f5260045260245260445260645ffd5b826297d0a360e61b5f526004523360245260445260645ffd5b5061282f8484614ea9565b156125dc565b827fc0a1a35a000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c161561069957610b3d602091614f0f565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f6128d782614ca9565b6005811015610aef576002036128f5575b6020906040519015158152f35b505f52600a602052602060ff60405f205460f01c166128e8565b34610626575f3660031901126106265760206001600160a01b0360085416604051908152f35b3461062657366003190161012081126106265761010013610626576101043567ffffffffffffffff811161062657612971903690600401613923565b61297961457a565b6040519182917fca31a854000000000000000000000000000000000000000000000000000000008352806024840160206004860152526044830191905f5b818110612b9d57845f8180870381737715be116061e014bb721b46dc78dd57c91fdf9b5af490811561052e575f91612abb575b5080515f198101908111610581578164ffffffffff6040612a10610bdd94602096614011565b5101511660405190612a2182613af4565b64ffffffffff4216825284820152612a37614039565b90612a4061404f565b612a48614065565b6001600160a01b03612a5861407b565b6001600160801b03612a68614091565b9383612a726140a0565b96816040519a612a818c613b10565b168a52168b89015216604087015216606085015215156080840152151560a083015260c0820152612ab136613bec565b60e082015261461f565b90503d805f833e612acc8183613b4a565b8101906020818303126106265780519067ffffffffffffffff8211610626570181601f8201121561062657805190612b0382613d45565b92612b116040519485613b4a565b8284526020606081860194028301019181831161062657602001925b828410612b3e5750505050816129ea565b6060848303126106265760405190612b5582613ac4565b612b5e85613feb565b825260208501519067ffffffffffffffff821682036106265782602092836060950152612b8d60408801613fff565b6040820152815201930192612b2d565b919350916060806001926001600160801b03612bb888613b96565b16815267ffffffffffffffff612bd060208901613d5d565b16602082015264ffffffffff612be860408901613a47565b1660408201520194019101918493926129b7565b3461062657602036600319011261062657600435612c1861457a565b805f52600a60205260ff600160405f20015460a81c161561069957805f52600a60205260ff600160405f20015460a01c1615612dab57805f526003602052612c6d6001600160a01b0360405f20541682614ea9565b15611baa57805f5260036020526001600160a01b0360405f205416151580612da4575b80612d87575b612d75577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051838152a1805f5260036020526001600160a01b0360405f2054168015908115612d3e575b825f52600360205260405f206001600160a01b03198154169055825f827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a450612d2c57005b637e27328960e01b5f5260045260245ffd5b612d5d835f52600560205260405f206001600160a01b03198154169055565b805f52600460205260405f205f198154019055612ce4565b6349d74b1160e11b5f5260045260245ffd5b50805f52600a60205260ff600160405f20015460b01c1615612c96565b505f612c90565b7fa6ba32da000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b3461062657611344612de736613985565b9060405192612df7602085613b4a565b5f84526140d4565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699575f52600a602052602060ff600160405f20015460a01c166040519015158152f35b3461062657602036600319011261062657600435612e6b61457a565b805f52600a60205260ff600160405f20015460a81c161561069957805f52600a60205260ff600160405f20015460a01c165f14612eb45763449491f560e11b5f5260045260245ffd5b805f52600a60205260405f205460f81c611bc057612ee6815f52600a6020526001600160a01b0360405f205416331490565b15611baa57612ef481614205565b90805f52600a602052612f0c600260405f2001614e77565b916001600160801b038351166001600160801b0382161015611b9757815f52600a60205260ff60405f205460f01c1615611b8457806001600160801b03602081612f60948188511603169501511690613bcc565b5f828152600a6020526040902080547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b179055916001600160801b038316908115613101575b825f52600a602052600360405f20016001600160801b0382166001600160801b0319825416179055825f52600a6020526001600160a01b0360405f205416835f5260036020526001600160a01b0360405f20541694845f52600a60205285827f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5061304a6001600160a01b03600160405f2001541694611a6b8885886159bc565b0390a47ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051868152a1845f52600960205260ff60405f20541661308d57005b60405193630d4af11f60e31b855260048501526024840152604483015260648201526020816084815f865af190811561052e57630d4af11f60e31b916001600160e01b0319915f916130e2575016036104ed57005b6130fb915060203d602011610527576105198183613b4a565b846104e4565b825f52600a602052600160405f2001600160a01b60ff60a01b19825416179055612faa565b346106265760203660031901126106265761313f6138f7565b6001600160a01b035f54169033820361327e57806001600160a01b03913b1561325257166040516301ffc9a760e01b81527ff8ee98d3000000000000000000000000000000000000000000000000000000006004820152602081602481855afa90811561052e575f91613223575b50156131f857805f52600960205260405f20600160ff198254161790556040519081527fb4378d4e289cb3f40f4f75a99c9cafa76e3df1c4dc31309babc23dc91bd7280160203392a2005b7f976c0d64000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b613245915060203d60201161324b575b61323d8183613b4a565b810190613fd3565b826131ad565b503d613233565b7f65453b0d000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b506331b339a960e21b5f526004523360245260445ffd5b34610626576020366003190112610626576001600160a01b036132b66138f7565b165f526009602052602060ff60405f2054166040519015158152f35b34610626576113446132e336613985565b91613da1565b34610626575f366003190112610626576020600754604051908152f35b346106265760203660031901126106265760043567ffffffffffffffff811161062657613337903690600401613954565b9036819003601e1901905f5b83811015611344578060051b8201358381121561062657820180359067ffffffffffffffff821161062657602001813603811361062657815f92918392604051928392833781018381520390305af461339a613d72565b90156133a95750600101613343565b6133e7906040519182917fd93544850000000000000000000000000000000000000000000000000000000083526020600484015260248301906138d2565b0390fd5b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c16156106995761342390614ca9565b6005811015610aef578060209115908115613444575b506040519015158152f35b600191501482613439565b3461062657366003190161016081126106265761014013610626576101443567ffffffffffffffff81116106265761348b903690600401613923565b61349361457a565b61349c36613c25565b906134a681613d45565b926134b46040519485613b4a565b818452606060208501920281019036821161062657915b8183106134de576020610bdd868661461f565b6060833603126106265760206060916040516134f981613ac4565b61350286613b96565b815261350f838701613d5d565b8382015261351f60408701613a47565b60408201528152019201916134cb565b3461062657602036600319011261062657600435805f52600a60205260ff600160405f20015460a81c1615610699576020905f90805f52600a835260ff60405f205460f01c16806135c4575b613592575b506001600160801b0360405191168152f35b6135be9150805f52600a83526135b86001600160801b03600260405f2001541691614205565b90613bcc565b82613580565b50805f52600a835260ff600160405f20015460a01c161561357b565b34610626576040366003190112610626576135f96138f7565b602435613605816141e4565b331515806136d2575b8061369f575b6136735781906001600160a01b0380851691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a45f5260056020526001600160a01b0360405f2091166001600160a01b03198254161790555f80f35b7fa9fbf51f000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b506001600160a01b0381165f52600660205260405f206001600160a01b0333165f5260205260ff60405f20541615613614565b50336001600160a01b038216141561360e565b34610626576020366003190112610626576020612221600435613baa565b34610626575f366003190112610626576040515f6001548060011c906001811680156137b4575b6020831081146117405782855290811561171c575060011461375657610d4a836116aa81850382613b4a565b91905060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6915f905b80821061379a575090915081016020016116aa61169a565b919260018160209254838588010152019101909291613782565b91607f169161372a565b34610626575f36600319011261062657602060405167016345785d8a00008152f35b3461062657602036600319011261062657600435906001600160e01b0319821680920361062657817f49064906000000000000000000000000000000000000000000000000000000006020931490811561383c575b5015158152f35b7f80ac58cd00000000000000000000000000000000000000000000000000000000811491508115613887575b8115613876575b5083613835565b6301ffc9a760e01b9150148361386f565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150613868565b5f5b8381106138c25750505f910152565b81810151838201526020016138b3565b906020916138eb815180928185528580860191016138b1565b601f01601f1916010190565b600435906001600160a01b038216820361062657565b602435906001600160a01b038216820361062657565b9181601f840112156106265782359167ffffffffffffffff8311610626576020808501946060850201011161062657565b9181601f840112156106265782359167ffffffffffffffff8311610626576020808501948460051b01011161062657565b6060906003190112610626576004356001600160a01b038116810361062657906024356001600160a01b0381168103610626579060443590565b9181601f840112156106265782359167ffffffffffffffff8311610626576020808501948460061b01011161062657565b90602080835192838152019201905f5b818110613a0d5750505090565b9091926020604082613a3c600194885164ffffffffff602080926001600160801b038151168552015116910152565b019401929101613a00565b359064ffffffffff8216820361062657565b90602080835192838152019201905f5b818110613a765750505090565b9091926020606082613ab9600194885164ffffffffff604080926001600160801b03815116855267ffffffffffffffff6020820151166020860152015116910152565b019401929101613a69565b6060810190811067ffffffffffffffff821117613ae057604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff821117613ae057604052565b610100810190811067ffffffffffffffff821117613ae057604052565b610160810190811067ffffffffffffffff821117613ae057604052565b90601f8019910116810190811067ffffffffffffffff821117613ae057604052565b67ffffffffffffffff8111613ae057601f01601f191660200190565b6003811015610aef57600452565b35906001600160801b038216820361062657565b613bb3816141e4565b505f5260056020526001600160a01b0360405f20541690565b906001600160801b03809116911603906001600160801b03821161058157565b60409060c31901126106265760405190613c0582613af4565b8160c4356001600160a01b0381168103610626578152602060e435910152565b9061014060031983011261062657604051613c3f81613b10565b80926004356001600160a01b03811681036106265782526024356001600160a01b03811681036106265760208301526044356001600160801b03811681036106265760408301526064356001600160a01b0381168103610626576060830152608435801515810361062657608083015260a43580151581036106265760a0830152604060c31982011261062657604051613cd881613af4565b60c43564ffffffffff8116810361062657815260e43564ffffffffff8116810361062657602082015260c08301526040610104809203126106265760405191613d2083613af4565b81356001600160a01b03811681036106265760e0926020918552013560208401520152565b67ffffffffffffffff8111613ae05760051b60200190565b359067ffffffffffffffff8216820361062657565b3d15613d9c573d90613d8382613b6c565b91613d916040519384613b4a565b82523d5f602084013e565b606090565b91906001600160a01b03168015610eb757815f5260036020526001600160a01b0360405f205416151580613fcb575b80613fae575b613f9b577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051848152a1815f5260036020526001600160a01b0360405f20541692823315159283613ee6575b6001600160a01b03935085613eaf575b805f52600460205260405f2060018154019055815f52600360205260405f20816001600160a01b0319825416179055857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a416808303613e9757505050565b6364283d7b60e01b5f5260045260245260445260645ffd5b613ece825f52600560205260405f206001600160a01b03198154169055565b855f52600460205260405f205f198154019055613e36565b9192905080613f44575b15613efd57828291613e26565b8284613f1557637e27328960e01b5f5260045260245ffd5b7f177e802f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b503384148015613f72575b80613ef05750825f526005602052336001600160a01b0360405f20541614613ef0565b50835f52600660205260405f206001600160a01b0333165f5260205260ff60405f205416613f4f565b506349d74b1160e11b5f5260045260245ffd5b50815f52600a60205260ff600160405f20015460b01c1615613dd6565b506001613dd0565b90816020910312610626575180151581036106265790565b51906001600160801b038216820361062657565b519064ffffffffff8216820361062657565b80518210156140255760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6004356001600160a01b03811681036106265790565b6024356001600160a01b03811681036106265790565b6044356001600160801b03811681036106265790565b6064356001600160a01b03811681036106265790565b60843580151581036106265790565b60a43580151581036106265790565b91908110156140255760051b0190565b6101043564ffffffffff811681036106265790565b906140e0838284613da1565b803b6140ed575b50505050565b6020916141336001600160a01b03809316956040519586948594630a85bd0160e11b865233600487015216602485015260448401526080606484015260848301906138d2565b03815f865af15f91816141a3575b5061416f575061414f613d72565b8051908161416a5782633250574960e11b5f5260045260245ffd5b602001fd5b6001600160e01b0319630a85bd0160e11b91160361419157505f8080806140e7565b633250574960e11b5f5260045260245ffd5b6141bd91925060203d602011610527576105198183613b4a565b905f614141565b9081602091031261062657516001600160e01b0319811681036106265790565b805f5260036020526001600160a01b0360405f205416908115612d2c575090565b64ffffffffff421690805f52600a60205264ffffffffff60405f205460a01c169180831015614573575f828152600a6020526040902080546002909101546001600160801b03169160c89190911c64ffffffffff169081111561456c575f835f52600a60205260ff600160405f20015460b81c166003811015610aef57600181036143bc575050505090815f52600c60205260405f20915f52600a602052600260405f20015460801c906040519283917f63ec2f5a0000000000000000000000000000000000000000000000000000000083526064830160606004850152825480915260848401925f5260205f20905f5b818110614376575050509060209383926024840152604483015203817326f9d826bded47fc472526ae8095b75ac336963c5af490811561052e575f9161433c575b505b90565b90506020813d60201161436e575b8161435760209383613b4a565b810103126106265761436890613feb565b5f614337565b3d915061434a565b82546001600160801b0381168652608081901c67ffffffffffffffff16602087015260c01c64ffffffffff166040860152879550606090940193600192830192016142f6565b92949391928061445e575050805f52600b60205264ffffffffff60405f205416905f52600a602052600260405f20015460801c92604051947f24d5ab3e0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401526064830152608482015260208160a4817326f9d826bded47fc472526ae8095b75ac336963c5af490811561052e575f9161433c575090565b91935093506002915014614470575090565b90505f52600d60205260405f2060405180917f5515a8160000000000000000000000000000000000000000000000000000000082526024820160206004840152815480915260448301915f5260205f20905f5b81811061453a57505050908060209203817326f9d826bded47fc472526ae8095b75ac336963c5af490811561052e575f91614500575b505f614337565b90506020813d602011614532575b8161451b60209383613b4a565b810103126106265761452c90613feb565b5f6144f9565b3d915061450e565b82546001600160801b038116855260801c64ffffffffff166020850152859450604090930192600192830192016144c3565b5091505090565b5050505f90565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036145ac57565b7fa1c0d6e5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90816040910312610626576146026020604051926145f184613af4565b6145fa81613feb565b845201613feb565b602082015290565b8054821015614025575f5260205f2001905f90565b906146a492916001600160a01b038151169160c082019182516001600160801b036040830151169060e083019560208751015192604051998a937ffb6164dd0000000000000000000000000000000000000000000000000000000085526101048501936004860152602485019064ffffffffff60208092828151168552015116910152565b60648301526101006084830152845180915261012482019060208601905f5b818110614c555750505081906040937f000000000000000000000000000000000000000000000000000000000000000060a484015260c483015267016345785d8a000060e48301520381737715be116061e014bb721b46dc78dd57c91fdf9b5af495861561052e575f96614c24575b506007549582515f5b818110614b125750508151948451805164ffffffffff16906020015164ffffffffff16956080850197885115158b60608801998a516001600160a01b031660a08a019687511515928a516001600160801b0316956040519661479c88613ac4565b8752602087015f9052604087015f9052604051976147b989613b2d565b6001600160a01b0316885260208801928352604088019182526060880190815260808801905f825260a0890194855260c08901925f845260e08a0194600186526101008b019788526101208b019860018a526101408c019a8b525f52600a60205260405f209a516001600160a01b03166001600160a01b03168b546001600160a01b031916178b5551908a54905160c81b64ffffffffff60c81b169160a01b64ffffffffff60a01b169069ffffffffffffffffffff60a01b19161717895551151561489b90899060ff60f01b1960ff60f01b835492151560f01b169116179055565b5187546001600160f81b031690151560f81b7fff00000000000000000000000000000000000000000000000000000000000000161787559151600187018054935160ff60a01b90151560a01b166001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff19909416939093171782555115159381549251151560b01b60ff60b01b169351916003831015610aef5762ffffff60a81b1990931660a89590951b60ff60a81b169490941790921760b89290921b60ff60b81b16919091179055518051602082015160801b6001600160801b0319166001600160801b039182161760028401559060039082906040015116920191166001600160801b031982541617905560208501956001600160a01b038751168015610eb7576149cf8c6001600160a01b0392614d3d565b16614ae657614aab8b94614abf936001600160a01b038080807f37ba529dbe2c0eff025dc0325f5f31b6298126095fecc31e6c785a9a58b520209c8f6001600160801b0360208f8f600101600755614a3286855116848351169030903390615a13565b01511680614acb575b505051169c51169c51169c5115159651151591519251511695614a84604051998a998a523360208b015260408a01906001600160801b0360208092828151168552015116910152565b608088015260a087015260c086019064ffffffffff60208092828151168552015116910152565b610140610100850152610140840190613a59565b906101208301520390a4565b83614adf925116848a515116903390615a13565b8f5f614a3b565b7f73c6ac6e000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b885f52600c60205260405f2090614b298187614011565b5191805468010000000000000000811015613ae057614b4d9160018201815561460a565b614c1157826001600160801b03806001955116166001600160801b03198354161782556020810151907fffffff00000000000000000000000000ffffffffffffffffffffffffffffffff7cffffffffff000000000000000000000000000000000000000000000000604077ffffffffffffffff0000000000000000000000000000000086549560801b1693847fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff8716178755015160c01b169216171790550161473b565b634e487b7160e01b5f525f60045260245ffd5b614c4791965060403d604011614c4e575b614c3f8183613b4a565b8101906145d4565b945f614732565b503d614c35565b91949350916020606082614c9a600194895164ffffffffff604080926001600160801b03815116855267ffffffffffffffff6020820151166020860152015116910152565b0195019101918a9394926146c3565b805f52600a60205260ff600160405f20015460a01c165f14614ccb5750600490565b805f52600a60205260405f205460f81c614d3757805f52600a60205264ffffffffff60405f205460a01c164210614d3257614d0581614205565b905f52600a6020526001600160801b0380600260405f200154169116105f14614d2d57600190565b600290565b505f90565b50600390565b90805f5260036020526001600160a01b0360405f205416151580614e65575b80614e48575b612d75577ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce76020604051838152a1805f5260036020526001600160a01b038060405f2054169283614e11575b1680614df9575b815f52600360205260405f20816001600160a01b0319825416179055827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a490565b805f52600460205260405f2060018154019055614db5565b614e30835f52600560205260405f206001600160a01b03198154169055565b835f52600460205260405f205f198154019055614dae565b50805f52600a60205260ff600160405f20015460b01c1615614d62565b506001600160a01b0382161515614d5c565b90604051614e8481613ac4565b60406001600160801b03600183958054838116865260801c6020860152015416910152565b906001600160a01b031690813314918215614ee3575b508115614eca575090565b90506001600160a01b03614ede3392613baa565b161490565b9091505f52600660205260405f206001600160a01b0333165f5260205260ff60405f205416905f614ebf565b805f52600a602052614f26600260405f2001614e77565b90805f52600a60205260ff600160405f20015460a01c165f14614f545750602001516001600160801b031690565b90815f52600a60205260405f205460f81c614f73575061433990614205565b61433991506001600160801b036040818351169201511690613bcc565b9061501592916001600160a01b038151169160c082019182516001600160801b036040830151169060e083019560208751015192604051998a937f07aaee4b0000000000000000000000000000000000000000000000000000000085526101048501936004860152602485019064ffffffffff60208092828151168552015116910152565b60648301526101006084830152845180915261012482019060208601905f5b8181106154835750505081906040937f000000000000000000000000000000000000000000000000000000000000000060a484015260c483015267016345785d8a000060e48301520381737715be116061e014bb721b46dc78dd57c91fdf9b5af495861561052e575f96615462575b506007549582515f5b8181106153b75750508151948451805164ffffffffff16906020015164ffffffffff16956080850197885115158b60608801998a516001600160a01b031660a08a019687511515928a516001600160801b0316956040519661510d88613ac4565b8752602087015f9052604087015f90526040519761512a89613b2d565b6001600160a01b0316885260208801928352604088019182526060880190815260808801905f825260a0890194855260c08901925f845260e08a0194600186526101008b019788526101208b019860028a526101408c019a8b525f52600a60205260405f209a516001600160a01b03166001600160a01b03168b546001600160a01b031916178b5551908a54905160c81b64ffffffffff60c81b169160a01b64ffffffffff60a01b169069ffffffffffffffffffff60a01b19161717895551151561520c90899060ff60f01b1960ff60f01b835492151560f01b169116179055565b5187546001600160f81b031690151560f81b7fff00000000000000000000000000000000000000000000000000000000000000161787559151600187018054935160ff60a01b90151560a01b166001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff19909416939093171782555115159381549251151560b01b60ff60b01b169351916003831015610aef5762ffffff60a81b1990931660a89590951b60ff60a81b169490941790921760b89290921b60ff60b81b16919091179055518051602082015160801b6001600160801b0319166001600160801b039182161760028401559060039082906040015116920191166001600160801b031982541617905560208501956001600160a01b038751168015610eb7576153408c6001600160a01b0392614d3d565b16614ae6576153a38b94614abf936001600160a01b038080807f698bb53308d5520596fa20e0bd6e16c29eb8b8115f6e987397278c6c0757be089c8f6001600160801b0360208f8f600101600755614a3286855116848351169030903390615a13565b6101406101008501526101408401906139f0565b885f52600d60205260405f20906153ce8187614011565b5191805468010000000000000000811015613ae0576153f29160018201815561460a565b614c11576020836001600160801b03806001965116166001600160801b031984541617835501517fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff74ffffffffff0000000000000000000000000000000083549260801b169116179055016150ac565b61547c91965060403d604011614c4e57614c3f8183613b4a565b945f6150a3565b919493509160206040826154b4600194895164ffffffffff602080926001600160801b038151168552015116910152565b0195019101918a939492615034565b91906001600160a01b0383511660c08401516001600160801b03604086015116615539602060e0880151015192604051947f21e1a4bb0000000000000000000000000000000000000000000000000000000086526004860152602485019064ffffffffff60208092828151168552015116910152565b64ffffffffff84166064840152608483015260a482015267016345785d8a000060c482015260408160e481737715be116061e014bb721b46dc78dd57c91fdf9b5af490811561052e575f91615977575b506007549364ffffffffff8316615951575b80516001600160a01b03169260c082015192835164ffffffffff16936020015164ffffffffff1694608084019588875115159160608701516001600160a01b031660a0880198895115159287516001600160801b031695604051966155ff88613ac4565b8752602087015f9052604087015f90526040519761561c89613b2d565b885260208801928352604088019182526060880190815260808801905f825260a0890194855260c08901925f845260e08a0194600186526101008b019788526101208b01985f8a526101408c019a8b525f52600a60205260405f209a516001600160a01b03166001600160a01b03168b546001600160a01b031916178b5551908a54905160c81b64ffffffffff60c81b169160a01b64ffffffffff60a01b169069ffffffffffffffffffff60a01b1916171789555115156156f490899060ff60f01b1960ff60f01b835492151560f01b169116179055565b5187546001600160f81b031690151560f81b7fff00000000000000000000000000000000000000000000000000000000000000161787559151600187018054935160ff60a01b90151560a01b166001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff19909416939093171782555115159381549251151560b01b60ff60b01b169351916003831015610aef5762ffffff60a81b1990931660a89590951b60ff60a81b169490941790921760b89290921b60ff60b81b16919091179055518051602082015160801b6001600160801b0319166001600160801b039182161760028401559060039082906040015116920191166001600160801b03198254161790556001600160a01b036020840151168015610eb757615826886001600160a01b0392614d3d565b16614ae657866101409164ffffffffff7fcf9ef6a106311d590d4fb2ae5a0963a0b5e399f8e1e8280d8e80b262feea1b0f94600184016007556158856001600160a01b036060890151166001600160801b038551169030903390615a13565b6001600160801b0360208401511680615922575b506159126001600160a01b03885116976001600160a01b03602082015116996001600160a01b036060830151169b5115159051151590614a846001600160a01b0360e060c0860151950151511697604051998a523360208b015260408a01906001600160801b0360208092828151168552015116910152565b16610100830152610120820152a4565b61594b906001600160a01b0360608a0151166001600160a01b0360e08b01515116903390615a13565b5f615899565b845f52600b60205260405f2064ffffffffff841664ffffffffff1982541617905561559b565b615990915060403d604011614c4e57614c3f8183613b4a565b5f615589565b614339906159a381614f0f565b905f52600a602052600260405f20015460801c90613bcc565b615a11926001600160a01b03604051937fa9059cbb000000000000000000000000000000000000000000000000000000006020860152166024840152604483015260448252615a0c606483613b4a565b615a6d565b565b9091926001600160a01b03615a119481604051957f23b872dd000000000000000000000000000000000000000000000000000000006020880152166024860152166044840152606483015260648252615a0c608483613b4a565b5f806001600160a01b03615a9693169360208151910182865af1615a8f613d72565b9083615af2565b8051908115159182615ad7575b5050615aac5750565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b615aea9250602080918301019101613fd3565b155f80615aa3565b90615b2f5750805115615b0757805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580615b75575b615b40575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15615b3856fea164736f6c634300081a000a"; - bytes public constant BYTECODE_MERKLE_FACTORY = - hex"608034609357601f615a8138819003918201601f19168301916001600160401b03831184841017609757808492602094604052833981010312609357516001600160a01b038116908190036093575f80546001600160a01b0319168217815560405191907fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a36159d590816100ac8239f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c8063070a6b8414610d0e5780631134f19414610cf157806345aa9357146109735780634d7c0f11146108a05780636f71d8f41461083057806375829def146107aa5780638af96dfe14610723578063b3ee17cc146102f9578063d498fcf514610265578063f255527814610135578063f851a440146101105763f946eef21461009d575f80fd5b3461010c57602036600319011261010c576004356001600160a01b035f54163381036100f65750806001556040519081527f7d41b7bcff330c958826f81c5de08357f286914f0758727ca23717d24f158fcc60203392a2005b6331b339a960e21b5f526004523360245260445ffd5b5f80fd5b3461010c575f36600319011261010c5760206001600160a01b035f5416604051908152f35b3461010c57604036600319011261010c576004356001600160a01b03811680910361010c57602435906001600160a01b03821680920361010c576001600160a01b035f54163381036100f65750801561023d576040517f164e68de0000000000000000000000000000000000000000000000000000000081528160048201526020816024815f875af1908115610232575f91610200575b5060405191825260208201527ff65e64e219c3199240f0fe17a71d01821ed2dd08283833094e12a9ad6883786560403392a3005b90506020813d60201161022a575b8161021b60209383610f14565b8101031261010c5751836101cc565b3d915061020e565b6040513d5f823e3d90fd5b7f38da7036000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461010c57604036600319011261010c5761027e610f5c565b602435906001600160a01b035f54163381036100f657506001600160a01b031690815f52600260205280600160405f20805460ff8116156102eb575b5001556040519081527f314737fce28d10af73c184056111a030c8124d005478d4a11f5978545779ed9a60203392a3005b60ff191682178155856102ba565b3461010c5761010036600319011261010c5760043567ffffffffffffffff811161010c5761032b903690600401610fc8565b610333611089565b9061033c61109f565b906103456110ae565b9061034e610f36565b60a4359167ffffffffffffffff831161010c573660238401121561010c57826004013567ffffffffffffffff8111610683576040519361039460208360051b0186610f14565b8185526024602086019260061b8201019036821161010c57602401915b8183106106d65750505082515f905f905b808210610697575050336103d5906111e3565b825160208401516040850151908760608701519a604051809c602082016020905260408201610403916110de565b03601f1981018d52610415908d610f14565b6080880151908d60a08a015160405181819251908160208401916020019161043c926110bd565b81010380825261044f9060200182610f14565b61045890611103565b6040519e8f806020810197602089526040820161047491611193565b03601f198101825261048591610f14565b604051978897602089019a3360601b8c526bffffffffffffffffffffffff199060601b1660348a015260d81b6001600160d81b03191660488901526bffffffffffffffffffffffff199060601b16604d880152805190816061890191602001916104ee926110bd565b860193606185015260818401526001600160a01b03169d6bffffffffffffffffffffffff199060601b1660a183015215159a8b60f81b60b583015215159b8c60f81b60b683015264ffffffffff8a169960d81b6001600160d81b03191660b783015251918260bc8301610560926110bd565b0160610103605b01601f19810182526105799082610f14565b519020604051611e8a80820182811067ffffffffffffffff821117610683578460c06105de8e8e8e8897613b3f893960e087526105ba8d60e0890190611125565b926020880152604087015260608601528b608086015284810360a08601528c611193565b92015203905ff58015610232576020987f4507eb2a4efc5eacd7bf717901bdc881a42a88f0e7c45a050d6d1375521883649661063a966001600160a01b0361065b94169a8b9a604051998a996101408b526101408b0190611125565b948e8a015260408901526060880152608087015285820360a0870152611193565b9160c084015260c43560e084015260e4356101008401526101208301520390a2604051908152f35b634e487b7160e01b5f52604160045260245ffd5b909185518310156106c25760019064ffffffffff6020808660051b8a010151015116019201906103c2565b634e487b7160e01b5f52603260045260245ffd5b60408336031261010c57604051906106ed82610ef8565b83359067ffffffffffffffff8216820361010c578260209260409452610714838701610f4a565b838201528152019201916103b1565b3461010c57602036600319011261010c5761073c610f5c565b6001600160a01b035f541690338203610793576001600160a01b0316805f5260026020525f6001604082208281550155337f8cebf46c84bf401fa7816b701dfac1f1fdf41e6e601b9a501e7639d2aff5582f5f80a3005b506331b339a960e21b5f526004523360245260445ffd5b3461010c57602036600319011261010c576107c3610f5c565b5f546001600160a01b0381163381036100f657506001600160a01b037fffffffffffffffffffffffff0000000000000000000000000000000000000000921691829116175f55337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf805f80a3005b3461010c57602036600319011261010c576001600160a01b03610851610f5c565b5f602060405161086081610ef8565b8281520152165f5260026020526040805f20815161087d81610ef8565b6020600160ff845416151593848452015491019081528251918252516020820152f35b3461010c57602036600319011261010c5760043567ffffffffffffffff811161010c573660238201121561010c5780600401359067ffffffffffffffff821161010c573660248360061b8301011161010c575f90815b838310156109545760248360061b830101359067ffffffffffffffff821680920361010c5767ffffffffffffffff160167ffffffffffffffff8111610940576001909201916108f6565b634e487b7160e01b5f52601160045260245ffd5b602090670de0b6b3a764000067ffffffffffffffff6040519216148152f35b3461010c5761012036600319011261010c5760043567ffffffffffffffff811161010c576109a5903690600401610fc8565b6109ad611089565b6109b561109f565b906109be6110ae565b90606036608319011261010c576040516060810181811067ffffffffffffffff821117610683576040526109f0610f36565b815260a43564ffffffffff8116810361010c57602082015260c43564ffffffffff8116810361010c576040820152845160208601516040870151906060880151966040519081602081019960208b5260408201610a4c916110de565b03601f1981018352610a5e9083610f14565b60808a01519060a08b0151604051818192519081602084019160200191610a84926110bd565b810103808252610a979060200182610f14565b610aa090611103565b6040519a60208c0194610ad2868b64ffffffffff60408092828151168552826020820151166020860152015116910152565b60608d52610ae160808e610f14565b604051978897602089019a3360601b8c526bffffffffffffffffffffffff199060601b1660348a015260d81b6001600160d81b03191660488901526bffffffffffffffffffffffff199060601b16604d88015251908160618801610b44926110bd565b850192606184015260818301526001600160a01b038816976bffffffffffffffffffffffff199060601b1660a18301521515978860f81b60b58301521515988960f81b60b683015251918260b78301610b9c926110bd565b0160610103605601601f1981018252610bb59082610f14565b51902094610bc2336111e3565b9560405161180b80820182811067ffffffffffffffff821117610683578291612334833961010081528960e0610bfc610100840188611125565b928960208201528a60408201528b6060820152610c3b608082018a64ffffffffff60408092828151168552826020820151166020860152015116910152565b015203905ff592831561023257602096610cce610c96946001600160a01b037fe7c4d633a3f64a821f1283e2a399b368e633c17776b3cb932e4105d76ca299e397169889986040519788976101408952610140890190611125565b958c88015260408701526060860152608085019064ffffffffff60408092828151168552826020820151166020860152015116910152565b60e43560e0840152610104356101008401526101208301520390a2604051908152f35b3461010c575f36600319011261010c576020600154604051908152f35b3461010c57606036600319011261010c5760043567ffffffffffffffff811161010c57610d3f903690600401610fc8565b80516001600160d81b0319610e3e60406061602086015182870151606088015190845191610d8a83610d7c602082019360208552898301906110de565b03601f198101855284610f14565b610e2360808b015193610dcc60a08d0151610dc760208b5183610db682955180928580860191016110bd565b81010301601f198101835282610f14565b611103565b9388519a8b97602089019d8e3360601b90526bffffffffffffffffffffffff199060601b1660348a015260d81b1660488801526bffffffffffffffffffffffff199060601b16604d870152518092878701906110bd565b83019184830152608182015203016020810184520182610f14565b51902090610e4b336111e3565b9160405161111880820182811067ffffffffffffffff82111761068357829161121c833960408152856020610e836040840188611125565b92015203905ff5918215610232577f12188a644c16704b9e77e2ecd3bb77e911693c22ffb0fcf44d9e4b36638b5d01610ed86001600160a01b0360209516938493604051928392608084526080840190611125565b9060243588840152604435604084015260608301520390a2604051908152f35b6040810190811067ffffffffffffffff82111761068357604052565b90601f8019910116810190811067ffffffffffffffff82111761068357604052565b6084359064ffffffffff8216820361010c57565b359064ffffffffff8216820361010c57565b600435906001600160a01b038216820361010c57565b81601f8201121561010c5780359067ffffffffffffffff82116106835760405192610fa7601f8401601f191660200185610f14565b8284526020838301011161010c57815f926020809301838601378301015290565b919060c08382031261010c576040519060c0820182811067ffffffffffffffff82111761068357604052819380356001600160a01b038116810361010c57835261101460208201610f4a565b602084015260408101356001600160a01b038116810361010c576040840152606081013567ffffffffffffffff811161010c5782611053918301610f72565b60608401526080810135608084015260a08101359167ffffffffffffffff831161010c5760a0926110849201610f72565b910152565b602435906001600160a01b038216820361010c57565b60443590811515820361010c57565b60643590811515820361010c57565b5f5b8381106110ce5750505f910152565b81810151838201526020016110bf565b906020916110f7815180928185528580860191016110bd565b601f01601f1916010190565b602081519101519060208110611117575090565b5f199060200360031b1b1690565b611190916001600160a01b03825116815264ffffffffff60208301511660208201526001600160a01b03604083015116604082015260a0611175606084015160c0606085015260c08401906110de565b926080810151608084015201519060a08184039101526110de565b90565b90602080835192838152019201905f5b8181106111b05750505090565b8251805167ffffffffffffffff16855260209081015164ffffffffff1681860152604090940193909201916001016111a3565b6001600160a01b0316805f52600260205260ff60405f2054165f14611214575f526002602052600160405f20015490565b506001549056fe61014080604052346103d457611118803803809161001d82856103d8565b83398101906040818303126103d45780516001600160401b0381116103d45781019060c0828403126103d4576040519160c083016001600160401b038111848210176103a95760405280516001600160a01b03811681036103d4578352602081015164ffffffffff811681036103d457602084019081526040820151936001600160a01b03851685036103d4576040810194855260608301516001600160401b0381116103d457866100d091850161041c565b92606082019384526080810151966080830197885260a082015160018060401b0381116103d457610101920161041c565b60a082018181526020959095015195515f80546001600160a01b0319166001600160a01b039290921691821781557fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a351602081116103bd5750516001600160a01b03166080525164ffffffffff1660a0523360c0525180519093906001600160401b0381116103a957600154600181811c9116801561039f575b602082101461038b57601f8111610328575b50602094601f82116001146102c5579481929394955f926102ba575b50508160011b915f199060031b1c1916176001555b5160e052516040516102146020828161020381830196878151938492016103fb565b81010301601f1981018352826103d8565b51905190602081106102a9575b506101005261012052604051610ca7908161047182396080518181816103f50152818161062a0152610811015260a051818181610181015281816107370152818161089f0152610b07015260c05181818161077e015261093d015260e05181818161028b01526105af015261010051816109fa01526101205181818161014101526104af0152f35b5f199060200360031b1b165f610221565b015190505f806101cc565b601f1982169560015f52805f20915f5b888110610310575083600195969798106102f8575b505050811b016001556101e1565b01515f1960f88460031b161c191690555f80806102ea565b919260206001819286850151815501940192016102d5565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f830160051c81019160208410610381575b601f0160051c01905b81811061037657506101b0565b5f8155600101610369565b9091508190610360565b634e487b7160e01b5f52602260045260245ffd5b90607f169061019e565b634e487b7160e01b5f52604160045260245ffd5b6371935f2960e11b5f52600452602060245260445ffd5b5f80fd5b601f909101601f19168101906001600160401b038211908210176103a957604052565b5f5b83811061040c5750505f910152565b81810151838201526020016103fd565b81601f820112156103d45780516001600160401b0381116103a9576040519261044f601f8301601f1916602001856103d8565b818452602082840101116103d45761046d91602080850191016103fb565b9056fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146109e457508063164e68de1461090e5780631686c909146107a25780632dd310001461075f5780633f31ae3f146104195780634800d97f146103d657806349fc73dd146102d25780634e390d3e146102ae57806351e75e8b1461027457806375829def146101bf57806390e64d13146101a5578063bb4b573414610164578063bba72cd31461012a578063ce516507146100ea5763f851a440146100c1575f80fd5b346100e6575f3660031901126100e65760206001600160a01b035f5416604051908152f35b5f80fd5b346100e65760203660031901126100e657602061012060043560ff6001918060081c5f526002602052161b60405f205416151590565b6040519015158152f35b346100e6575f3660031901126100e65760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346100e6575f3660031901126100e657602060405164ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100e6575f3660031901126100e6576020610120610aff565b346100e65760203660031901126100e6576101d8610a74565b5f546001600160a01b03811633810361024557506001600160a01b037fffffffffffffffffffffffff0000000000000000000000000000000000000000921691829116175f55337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf805f80a3005b7fc6cce6a4000000000000000000000000000000000000000000000000000000005f526004523360245260445ffd5b346100e6575f3660031901126100e65760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346100e6575f3660031901126100e657602064ffffffffff60035416604051908152f35b346100e6575f3660031901126100e6576040515f6001548060011c906001811680156103cc575b6020831081146103b8578285529081156103945750600114610336575b6103328361032681850382610a8a565b60405191829182610a2d565b0390f35b91905060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6915f905b80821061037a57509091508101602001610326610316565b919260018160209254838588010152019101909291610362565b60ff191660208086019190915291151560051b840190910191506103269050610316565b634e487b7160e01b5f52602260045260245ffd5b91607f16916102f9565b346100e6575f3660031901126100e65760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b60803660031901126100e657600435602435906001600160a01b038216918281036100e657604435926fffffffffffffffffffffffffffffffff84168094036100e6576064359367ffffffffffffffff85116100e657366023860112156100e657846004013567ffffffffffffffff81116100e6578060051b95602487820101903682116100e6576104a9610aff565b610708577f00000000000000000000000000000000000000000000000000000000000000008034106106d957506104f78760ff6001918060081c5f526002602052161b60405f205416151590565b6106ad57604051602081019088825286604082015285606082015260608152610521608082610a8a565b519020604051602081019182526020815261053d604082610a8a565b5190209261055160206040519a018a610a8a565b8852602401602088015b82821061069d57505050925f935b86518510156105ab5760208560051b88010151908181105f1461059a575f52602052600160405f205b940193610569565b905f52602052600160405f20610592565b85907f000000000000000000000000000000000000000000000000000000000000000003610675578261064e7f1dcd2362ae467d43bf31cbcac0526c0958b23eb063e011ab49a5179c839ed9a99460409460035464ffffffffff81161561065b575b508460081c5f526002602052855f20600160ff87161b81541790557f0000000000000000000000000000000000000000000000000000000000000000610b3c565b82519182526020820152a2005b64ffffffffff19164264ffffffffff16176003558861060d565b7fb4f06787000000000000000000000000000000000000000000000000000000005f5260045ffd5b813581526020918201910161055b565b867febe6f30d000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fa164c6b4000000000000000000000000000000000000000000000000000000005f523460045260245260445ffd5b7fdf4bae05000000000000000000000000000000000000000000000000000000005f524260045264ffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660245260445ffd5b346100e6575f3660031901126100e65760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100e65760403660031901126100e6576107bb610a74565b602435906fffffffffffffffffffffffffffffffff82168092036100e6576001600160a01b035f5416338103610245575064ffffffffff60035416801515806108d9575b806108ca575b610870575061083582827f0000000000000000000000000000000000000000000000000000000000000000610b3c565b7f2e9d425ba8b27655048400b366d7b6a1f7180ebdb088e06bb7389704860ffe1f60206001600160a01b03805f5416936040519586521693a3005b7fe2e40a0c000000000000000000000000000000000000000000000000000000005f524260045264ffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660245260445260645ffd5b506108d3610aff565b15610805565b5062093a80810164ffffffffff81116108fa5764ffffffffff1642116107ff565b634e487b7160e01b5f52601160045260245ffd5b346100e65760203660031901126100e6576004356001600160a01b0381168091036100e6576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168033036109b5575047905f80808085855af1610977610ac0565b501561098857602082604051908152f35b7e534073000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e3ddeed000000000000000000000000000000000000000000000000000000005f526004523360245260445ffd5b346100e6575f3660031901126100e657610332907f0000000000000000000000000000000000000000000000000000000000000000602082015260208152610326604082610a8a565b9190916020815282518060208301525f5b818110610a5e575060409293505f838284010152601f8019910116010190565b8060208092870101516040828601015201610a3e565b600435906001600160a01b03821682036100e657565b90601f8019910116810190811067ffffffffffffffff821117610aac57604052565b634e487b7160e01b5f52604160045260245ffd5b3d15610afa573d9067ffffffffffffffff8211610aac5760405191610aef601f8201601f191660200184610a8a565b82523d5f602084013e565b606090565b64ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168015159081610b34575090565b905042101590565b5f610ba9926001600160a01b038293604051968260208901947fa9059cbb000000000000000000000000000000000000000000000000000000008652166024890152604488015260448752610b92606488610a8a565b1694519082865af1610ba2610ac0565b9083610c0e565b8051908115159182610bea575b5050610bbf5750565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b81925090602091810103126100e657602001518015908115036100e6575f80610bb6565b90610c4b5750805115610c2357805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580610c91575b610c5c575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15610c5456fea164736f6c634300081a000a6101a0806040523461049a5761180b803803809161001d82856105d8565b8339810190808203610100811261049a5781516001600160401b03811161049a5782019160c08385031261049a576040519160c083016001600160401b038111848210176105ad5760405283516001600160a01b038116810361049a578352610088602085016105fb565b6020840190815260408501519091906001600160a01b038116810361049a576040850190815260608601516001600160401b03811161049a57876100cd918801610649565b95606086019687526080810151976080870198895260a082015160018060401b03811161049a576100fe9201610649565b60a0860190815260208501516001600160a01b038116979092909188840361049a5761012c6040880161068e565b92606061013a818a0161068e565b96607f19011261049a5760405196606088016001600160401b038111898210176105ad5760405261016d60808a016105fb565b885261017b60a08a016105fb565b99602089019a8b5260e061019160c08c016105fb565b60408b019081529a015194515f80546001600160a01b0319166001600160a01b039290921691821781557fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a3835151602081116105c15750516001600160a01b03166080525164ffffffffff1660a0523360c052518051909a906001600160401b0381116105ad57600154600181811c911680156105a3575b602082101461058f57601f811161052c575b506020601f82116001146104ba57819064ffffffffff9a9b9c9d5f926104af575b50508160011b915f199060031b1c1916176001555b5160e052516040516102a7602082816102968183019687815193849201610628565b81010301601f1981018352826105d8565b519051906020811061049e575b50610100526101205261014052610160526101805251166effffffffff0000000000000000000069ffffffffff0000000000600454945160281b16925160501b169260018060781b03191617171760045560018060a01b0360805116604051905f806020840163095ea7b360e01b815285602486015281196044860152604485526103406064866105d8565b84519082855af161034f61069b565b81610463575b5080610459575b15610414575b60405161106f908161079c823960805181818161049e015281816107530152610c31015260a0518181816101ad01528181610a8801528181610d310152610fa1015260c051818181610acf0152610dcf015260e051818181610334015261065601526101005181610e8c01526101205181818161016d01526105560152610140518181816107840152610b4601526101605181818161024401526108a70152610180518181816107ae0152610b0a0152f35b61044c610451936040519063095ea7b360e01b602083015260248201525f6044820152604481526104466064826105d8565b826106ca565b6106ca565b5f8080610362565b50803b151561035c565b8051801592508215610478575b50505f610355565b819250906020918101031261049a576020610493910161068e565b5f80610470565b5f80fd5b5f199060200360031b1b165f6102b4565b015190505f8061025f565b601f1982169c60015f52815f209d5f5b81811061050f57509164ffffffffff9b9c9d9e918460019594106104f7575b505050811b01600155610274565b01515f1960f88460031b161c191690555f80806104e9565b919e8f60016020928684930151815501940192019e91929e6104ca565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f830160051c81019160208410610585575b601f0160051c01905b81811061057a575061023e565b5f815560010161056d565b9091508190610564565b634e487b7160e01b5f52602260045260245ffd5b90607f169061022c565b634e487b7160e01b5f52604160045260245ffd5b6371935f2960e11b5f52600452602060245260445ffd5b601f909101601f19168101906001600160401b038211908210176105ad57604052565b519064ffffffffff8216820361049a57565b6001600160401b0381116105ad57601f01601f191660200190565b5f5b8381106106395750505f910152565b818101518382015260200161062a565b81601f8201121561049a57805161065f8161060d565b9261066d60405194856105d8565b8184526020828401011161049a5761068b9160208085019101610628565b90565b5190811515820361049a57565b3d156106c5573d906106ac8261060d565b916106ba60405193846105d8565b82523d5f602084013e565b606090565b5f806106f29260018060a01b03169360208151910182865af16106eb61069b565b908361073d565b805190811515918261071a575b50506107085750565b635274afe760e01b5f5260045260245ffd5b819250906020918101031261049a576020610735910161068e565b155f806106ff565b90610761575080511561075257805190602001fd5b630a12f52160e11b5f5260045ffd5b81511580610792575b610772575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b1561076a56fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde0314610e7657508063164e68de14610da05780631686c90914610b6b57806316c3549d14610b2f5780631bfd681414610af35780632dd3100014610ab05780633f31ae3f146104c25780634800d97f1461047f57806349fc73dd1461037b5780634e390d3e1461035757806351e75e8b1461031d57806375829def14610268578063845aef4b1461022557806390e64d131461020b578063b0604a26146101d1578063bb4b573414610190578063bba72cd314610156578063ce516507146101165763f851a440146100ed575f80fd5b34610112575f3660031901126101125760206001600160a01b035f5416604051908152f35b5f80fd5b3461011257602036600319011261011257602061014c60043560ff6001918060081c5f526002602052161b60405f205416151590565b6040519015158152f35b34610112575f3660031901126101125760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610112575f36600319011261011257602060405164ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610112575f36600319011261011257606060045464ffffffffff604051918181168352818160281c16602084015260501c166040820152f35b34610112575f36600319011261011257602061014c610f99565b34610112575f3660031901126101125760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461011257602036600319011261011257610281610f06565b5f546001600160a01b0381163381036102ee57506001600160a01b037fffffffffffffffffffffffff0000000000000000000000000000000000000000921691829116175f55337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf805f80a3005b7fc6cce6a4000000000000000000000000000000000000000000000000000000005f526004523360245260445ffd5b34610112575f3660031901126101125760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610112575f36600319011261011257602064ffffffffff60035416604051908152f35b34610112575f366003190112610112576040515f6001548060011c90600181168015610475575b6020831081146104615782855290811561043d57506001146103df575b6103db836103cf81850382610f38565b60405191829182610ebf565b0390f35b91905060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6915f905b808210610423575090915081016020016103cf6103bf565b91926001816020925483858801015201910190929161040b565b60ff191660208086019190915291151560051b840190910191506103cf90506103bf565b634e487b7160e01b5f52602260045260245ffd5b91607f16916103a2565b34610112575f3660031901126101125760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b608036600319011261011257600435602435906001600160a01b038216809203610112576044356fffffffffffffffffffffffffffffffff8116809103610112576064359067ffffffffffffffff8211610112573660238301121561011257816004013567ffffffffffffffff8111610112578060051b926024848201019036821161011257610550610f99565b610a59577f0000000000000000000000000000000000000000000000000000000000000000803410610a2a575061059e8660ff6001918060081c5f526002602052161b60405f205416151590565b6109fe576040516020810190878252886040820152856060820152606081526105c8608082610f38565b51902060405160208101918252602081526105e4604082610f38565b519020926105f86020604051970187610f38565b8552602401602085015b8282106109ee57505050935f945b83518610156106525760208660051b85010151908181105f14610641575f52602052600160405f205b950194610610565b905f52602052600160405f20610639565b84907f0000000000000000000000000000000000000000000000000000000000000000036109c65760035464ffffffffff8116156109ac575b508060081c5f52600260205260405f20600160ff83161b8154179055604051926106b484610f1c565b60045464ffffffffff8116806109a5575064ffffffffff421685525b5f9064ffffffffff8160281c168061098e575b5064ffffffffff9081808851169160501c16011660208601526001600160a01b035f5416946040519061071582610f1c565b5f82525f602083015260405196610100880188811067ffffffffffffffff82111761097a5760405287526020870186815260408801858152606089017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815260808a01917f00000000000000000000000000000000000000000000000000000000000000001515835260a08b01937f00000000000000000000000000000000000000000000000000000000000000001515855260c08c0195865260e08c019687526040519b7fab605ced000000000000000000000000000000000000000000000000000000008d52516001600160a01b031660048d0152516001600160a01b031660248c0152516fffffffffffffffffffffffffffffffff1660448b0152516001600160a01b031660648a0152511515608489015251151560a488015251805164ffffffffff1660c48801526020015164ffffffffff1660e48701525180516001600160a01b03166101048701526020015161012486015264ffffffffff1661014485015283807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165a925f61016492602095f193841561096f575f9461091b575b507f28b58397e03322f670d6b223cc863f8c148e368b8b615412e6798a641a22842d9160409182519182526020820152a3005b9093506020813d602011610967575b8161093760209383610f38565b810103126101125751927f28b58397e03322f670d6b223cc863f8c148e368b8b615412e6798a641a22842d6108e8565b3d915061092a565b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b865164ffffffffff908116909101811692506106e3565b85526106d0565b64ffffffffff19164264ffffffffff16176003558361068b565b7fb4f06787000000000000000000000000000000000000000000000000000000005f5260045ffd5b8135815260209182019101610602565b857febe6f30d000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fa164c6b4000000000000000000000000000000000000000000000000000000005f523460045260245260445ffd5b7fdf4bae05000000000000000000000000000000000000000000000000000000005f524260045264ffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660245260445ffd5b34610112575f3660031901126101125760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610112575f3660031901126101125760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b34610112575f3660031901126101125760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b3461011257604036600319011261011257610b84610f06565b6024356fffffffffffffffffffffffffffffffff8116809103610112576001600160a01b035f54163381036102ee575064ffffffffff6003541680151580610d6b575b80610d5c575b610d025750604051610c675f806001600160a01b0360208501967fa9059cbb000000000000000000000000000000000000000000000000000000008852169586602486015285604486015260448552610c27606486610f38565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001694519082865af1610c60610f5a565b9083610fd6565b8051908115159182610cde575b5050610cb357507f2e9d425ba8b27655048400b366d7b6a1f7180ebdb088e06bb7389704860ffe1f60206001600160a01b035f541692604051908152a3005b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b81925090602091810103126101125760200151801590811503610112578480610c74565b7fe2e40a0c000000000000000000000000000000000000000000000000000000005f524260045264ffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660245260445260645ffd5b50610d65610f99565b15610bcd565b5062093a80810164ffffffffff8111610d8c5764ffffffffff164211610bc7565b634e487b7160e01b5f52601160045260245ffd5b34610112576020366003190112610112576004356001600160a01b038116809103610112576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803303610e47575047905f80808085855af1610e09610f5a565b5015610e1a57602082604051908152f35b7e534073000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e3ddeed000000000000000000000000000000000000000000000000000000005f526004523360245260445ffd5b34610112575f366003190112610112576103db907f00000000000000000000000000000000000000000000000000000000000000006020820152602081526103cf604082610f38565b9190916020815282518060208301525f5b818110610ef0575060409293505f838284010152601f8019910116010190565b8060208092870101516040828601015201610ed0565b600435906001600160a01b038216820361011257565b6040810190811067ffffffffffffffff82111761097a57604052565b90601f8019910116810190811067ffffffffffffffff82111761097a57604052565b3d15610f94573d9067ffffffffffffffff821161097a5760405191610f89601f8201601f191660200184610f38565b82523d5f602084013e565b606090565b64ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168015159081610fce575090565b905042101590565b906110135750805115610feb57805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580611059575b611024575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561101c56fea164736f6c634300081a000a6101e080604052346104ba57611e8a803803809161001d828561071d565b833981019060e0818303126104ba5780516001600160401b0381116104ba5781019060c0828403126104ba576040519160c083016001600160401b038111848210176105745760405280516001600160a01b03811681036104ba57835261008660208201610740565b6020840190815260408201516001600160a01b03811681036104ba576040850190815260608301516001600160401b0381116104ba57866100c891850161078e565b6060860190815260808085015190870190815260a085015191949091906001600160401b0382116104ba576100ff9189910161078e565b60a087019081526020860151949091906001600160a01b03861686036104ba5761012b604088016107d3565b94610138606089016107d3565b9861014560808a01610740565b60a08a01519099906001600160401b0381116104ba5781018c601f820112156104ba578051906001600160401b038211610574576040519d8e8360051b60200161018f908261071d565b8381526020019260061b8201602001918183116104ba57602001925b8284106106c1575050505060c0015195515f80546001600160a01b0319166001600160a01b039290921691821781557fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a3845151602081116106aa5750516001600160a01b03166080525164ffffffffff1660a0523360c052518051906001600160401b0382116105745760015490600182811c921680156106a0575b602083101461068c5781601f84931161061e575b50602090601f83116001146105b8575f926105ad575b50508160011b915f199060031b1c1916176001555b5160e052516040516102bc602082816102ab818301968781519384920161076d565b81010301601f19810183528261071d565b519051906020811061059c575b5061010052610120526101405261016052610180526101c0528051905f915f915b8183106104be57836101a05260018060a01b036080511660018060a01b03610160511690604051905f806020840163095ea7b360e01b8152856024860152811960448601526044855261033e60648661071d565b84519082855af161034d6107f4565b81610483575b5080610479575b15610434575b60405161159590816108f582396080518181816105780152818161095d0152610f83015260a05181818161027d01528181610de301528181611083015261130b015260c051818181610e2a0152611121015260e05181818161040e015261072e015261010051816111de01526101205181818161023d015261062701526101405181818161098d0152610ea101526101605181818161031e0152610ad501526101805181818161018901526107bc01526101a0518181816102c1015261078a01526101c0518181816109b70152610e650152f35b61046c610471936040519063095ea7b360e01b602083015260248201525f60448201526044815261046660648261071d565b82610823565b610823565b808080610360565b50803b151561035a565b8051801592508215610498575b505084610353565b81925090602091810103126104ba5760206104b391016107d3565b8480610490565b5f80fd5b91929091906001600160401b036104d585846107e0565b5151166001600160401b039182160190811161058857926104f681836107e0565b519060045491680100000000000000008310156105745760018301806004558310156105605760019260045f5260205f200190838060401b038151166cffffffffff00000000000000006020845493015160401b1691858060681b031916171790550191906102ea565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f199060200360031b1b165f6102c9565b015190505f80610274565b60015f9081528281209350601f198516905b81811061060657509084600195949392106105ee575b505050811b01600155610289565b01515f1960f88460031b161c191690555f80806105e0565b929360206001819287860151815501950193016105ca565b60015f529091507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f840160051c81019160208510610682575b90601f859493920160051c01905b818110610674575061025e565b5f8155849350600101610667565b9091508190610659565b634e487b7160e01b5f52602260045260245ffd5b91607f169161024a565b6371935f2960e11b5f52600452602060245260445ffd5b6040848303126104ba5760408051919082016001600160401b03811183821017610574576040528451906001600160401b03821682036104ba57826020926040945261070e838801610740565b838201528152019301926101ab565b601f909101601f19168101906001600160401b0382119082101761057457604052565b519064ffffffffff821682036104ba57565b6001600160401b03811161057457601f01601f191660200190565b5f5b83811061077e5750505f910152565b818101518382015260200161076f565b81601f820112156104ba5780516107a481610752565b926107b2604051948561071d565b818452602082840101116104ba576107d0916020808501910161076d565b90565b519081151582036104ba57565b80518210156105605760209160051b010190565b3d1561081e573d9061080582610752565b91610813604051938461071d565b82523d5f602084013e565b606090565b5f8061084b9260018060a01b03169360208151910182865af16108446107f4565b9083610896565b8051908115159182610873575b50506108615750565b635274afe760e01b5f5260045260245ffd5b81925090602091810103126104ba57602061088e91016107d3565b155f80610858565b906108ba57508051156108ab57805190602001fd5b630a12f52160e11b5f5260045ffd5b815115806108eb575b6108cb575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156108c356fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146111c857508063164e68de146110f25780631686c90914610ec657806316c3549d14610e8a5780631bfd681414610e4e5780632dd3100014610e0b5780633f31ae3f1461059c5780634800d97f1461055957806349fc73dd146104555780634e390d3e1461043157806351e75e8b146103f757806375829def14610342578063845aef4b146102ff57806390e64d13146102e5578063936c63d9146102a1578063bb4b573414610260578063bba72cd314610226578063bf4ed03f146101ad578063ce36b3351461016c578063ce5165071461012c5763f851a44014610103575f80fd5b34610128575f3660031901126101285760206001600160a01b035f5416604051908152f35b5f80fd5b3461012857602036600319011261012857602061016260043560ff6001918060081c5f526002602052161b60405f205416151590565b6040519015158152f35b34610128575f36600319011261012857602060405164ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610128575f366003190112610128576101c5611340565b6040518091602082016020835281518091526020604084019201905f5b8181106101f0575050500390f35b8251805167ffffffffffffffff16855260209081015164ffffffffff1681860152869550604090940193909201916001016101e2565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405164ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610128575f36600319011261012857602060405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610128575f366003190112610128576020610162611303565b34610128575f3660031901126101285760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101285760203660031901126101285761035b611258565b5f546001600160a01b0381163381036103c857506001600160a01b037fffffffffffffffffffffffff0000000000000000000000000000000000000000921691829116175f55337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf805f80a3005b7fc6cce6a4000000000000000000000000000000000000000000000000000000005f526004523360245260445ffd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602064ffffffffff60035416604051908152f35b34610128575f366003190112610128576040515f6001548060011c9060018116801561054f575b60208310811461053b5782855290811561051757506001146104b9575b6104b5836104a98185038261128a565b60405191829182611211565b0390f35b91905060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6915f905b8082106104fd575090915081016020016104a9610499565b9192600181602092548385880101520191019092916104e5565b60ff191660208086019190915291151560051b840190910191506104a99050610499565b634e487b7160e01b5f52602260045260245ffd5b91607f169161047c565b34610128575f3660031901126101285760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b608036600319011261012857600435602435906001600160a01b03821680920361012857604435906001600160801b03821691828103610128576064359367ffffffffffffffff851161012857366023860112156101285784600401359467ffffffffffffffff86116101285760248660051b82010136811161012857610621611303565b610db4577f0000000000000000000000000000000000000000000000000000000000000000803410610d85575061066f8560ff6001918060081c5f526002602052161b60405f205416151590565b610d595760405160208101908682528460408201528760608201526060815261069960808261128a565b51902060405160208101918252602081526106b560408261128a565b519020916106c2886112eb565b976106d0604051998a61128a565b8852602401602088015b828210610d4957505050925f935b865185101561072a576106fb85886113f5565b519081811015610719575f52602052600160405f205b9401936106e8565b905f52602052600160405f20610711565b85907f000000000000000000000000000000000000000000000000000000000000000003610d215760035464ffffffffff811615610d07575b508160081c5f52600260205260405f20600160ff84161b815417905567ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016670de0b6b3a76400008103610cdc57507f000000000000000000000000000000000000000000000000000000000000000064ffffffffff8116610cd6575064ffffffffff4216935b6107fa611340565b90815191610807836112eb565b92610815604051948561128a565b808452601f19610824826112eb565b015f5b818110610cb357505061085661085167ffffffffffffffff610848856113d4565b5151168761144e565b611409565b64ffffffffff806020610868866113d4565b510151168a0116906001600160801b03604051916108858361126e565b16918282526020820152610898866113d4565b526108a2856113d4565b50916001905b828210610c1f5750506001600160801b038216858111610c0b578511610be0575b50505064ffffffffff60206108e25f19845101846113f5565b510151166001600160a01b035f54169064ffffffffff604051976109058961126e565b16875260208701526040516109198161126e565b5f81525f602082015260405191610100830183811067ffffffffffffffff821117610bcc5760409493929452815260208101928684526040820197858952606083017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152608084017f00000000000000000000000000000000000000000000000000000000000000001515815260a08501917f00000000000000000000000000000000000000000000000000000000000000001515835260c0860193845260e086019485526040519b8c987fd6a03d31000000000000000000000000000000000000000000000000000000008a526101648a0197516001600160a01b031660048b0152516001600160a01b031660248a0152516001600160801b03166044890152516001600160a01b03166064880152511515608487015251151560a486015251805164ffffffffff1660c48601526020015164ffffffffff1660e48501525180516001600160a01b031661010485015260200151610124840152610144830161016090528151809152610184830191602001905f5b818110610b9757505050908060209203815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1938415610b8c575f94610b38575b507f28b58397e03322f670d6b223cc863f8c148e368b8b615412e6798a641a22842d9160409182519182526020820152a3005b9093506020813d602011610b84575b81610b546020938361128a565b810103126101285751927f28b58397e03322f670d6b223cc863f8c148e368b8b615412e6798a641a22842d610b05565b3d9150610b47565b6040513d5f823e3d90fd5b825180516001600160801b0316855260209081015164ffffffffff168186015289955060409094019390920191600101610ab9565b634e487b7160e01b5f52604160045260245ffd5b6001600160801b0391610bf783925f1901866113f5565b5193031681835116011690528580806108c9565b634e487b7160e01b5f52600160045260245ffd5b90926001600160801b03600191610c4e61085167ffffffffffffffff610c4589886113f5565b5151168b61144e565b9064ffffffffff806020610c655f198b018d6113f5565b51015116816020610c768b8a6113f5565b51015116011660405190610c898261126e565b84841682526020820152610c9d888b6113f5565b52610ca8878a6113f5565b5001169301906108a8565b602090604051610cc28161126e565b5f81525f8382015282828901015201610827565b936107f2565b7f36d385ef000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b64ffffffffff19164264ffffffffff161760035584610763565b7fb4f06787000000000000000000000000000000000000000000000000000000005f5260045ffd5b81358152602091820191016106da565b847febe6f30d000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fa164c6b4000000000000000000000000000000000000000000000000000000005f523460045260245260445ffd5b7fdf4bae05000000000000000000000000000000000000000000000000000000005f524260045264ffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660245260445ffd5b34610128575f3660031901126101285760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610128575f3660031901126101285760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b34610128575f3660031901126101285760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b3461012857604036600319011261012857610edf611258565b6024356001600160801b038116809103610128576001600160a01b035f54163381036103c8575064ffffffffff60035416801515806110bd575b806110ae575b6110545750604051610fb95f806001600160a01b0360208501967fa9059cbb000000000000000000000000000000000000000000000000000000008852169586602486015285604486015260448552610f7960648661128a565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001694519082865af1610fb26112ac565b90836114fc565b8051908115159182611030575b505061100557507f2e9d425ba8b27655048400b366d7b6a1f7180ebdb088e06bb7389704860ffe1f60206001600160a01b035f541692604051908152a3005b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b81925090602091810103126101285760200151801590811503610128578480610fc6565b7fe2e40a0c000000000000000000000000000000000000000000000000000000005f524260045264ffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660245260445260645ffd5b506110b7611303565b15610f1f565b5062093a80810164ffffffffff81116110de5764ffffffffff164211610f19565b634e487b7160e01b5f52601160045260245ffd5b34610128576020366003190112610128576004356001600160a01b038116809103610128576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803303611199575047905f80808085855af161115b6112ac565b501561116c57602082604051908152f35b7e534073000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b7f4e3ddeed000000000000000000000000000000000000000000000000000000005f526004523360245260445ffd5b34610128575f366003190112610128576104b5907f00000000000000000000000000000000000000000000000000000000000000006020820152602081526104a960408261128a565b9190916020815282518060208301525f5b818110611242575060409293505f838284010152601f8019910116010190565b8060208092870101516040828601015201611222565b600435906001600160a01b038216820361012857565b6040810190811067ffffffffffffffff821117610bcc57604052565b90601f8019910116810190811067ffffffffffffffff821117610bcc57604052565b3d156112e6573d9067ffffffffffffffff8211610bcc57604051916112db601f8201601f19166020018461128a565b82523d5f602084013e565b606090565b67ffffffffffffffff8111610bcc5760051b60200190565b64ffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168015159081611338575090565b905042101590565b6004549061134d826112eb565b9161135b604051938461128a565b80835260045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b602085015b8383106113975750505050565b6001602081926040516113a98161126e565b64ffffffffff865467ffffffffffffffff8116835260401c168382015281520192019201919061138a565b8051156113e15760200190565b634e487b7160e01b5f52603260045260245ffd5b80518210156113e15760209160051b010190565b6001600160801b038111611423576001600160801b031690565b7f4916adce000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091905f19838209838202918280831092039180830392146114eb57670de0b6b3a76400008210156114bb577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106699394670de0b6b3a7640000910990828211900360ee1b910360121c170290565b84907f5173648d000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b5050670de0b6b3a764000090049150565b90611539575080511561151157805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b8151158061157f575b61154a575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561154256fea164736f6c634300081a000aa164736f6c634300081a000a"; + hex"60c0604052346103ce576164916060813803918261001c816103d2565b9384928339810103126103ce5780516001600160a01b038116908190036103ce5760208201516001600160a01b03811692908390036103ce576040015161006360406103d2565b92601284527114d8589b1a595c88131bd8dadd5c0813919560721b602085015261008d60406103d2565b600a81526905341422d4c4f434b55560b41b6020820152306080525f80546001600160a01b031916851781559093907fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf808180a383516001600160401b0381116102df57600154600181811c911680156103c4575b60208210146102c157601f8111610361575b50602094601f82116001146102fe579481929394955f926102f3575b50508160011b915f199060031b1c1916176001555b82516001600160401b0381116102df57600254600181811c911680156102d5575b60208210146102c157601f811161025e575b506020601f82116001146101fb57819293945f926101f0575b50508160011b915f199060031b1c1916176002555b600880546001600160a01b03191691909117905560a052600160075560405161609990816103f8823960805181614818015260a0518181816121fc01528181614a0a01526153c40152f35b015190505f80610190565b601f1982169060025f52805f20915f5b8181106102465750958360019596971061022e575b505050811b016002556101a5565b01515f1960f88460031b161c191690555f8080610220565b9192602060018192868b01518155019401920161020b565b60025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f830160051c810191602084106102b7575b601f0160051c01905b8181106102ac5750610177565b5f815560010161029f565b9091508190610296565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610165565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061012f565b601f1982169560015f52805f20915f5b88811061034957508360019596979810610331575b505050811b01600155610144565b01515f1960f88460031b161c191690555f8080610323565b9192602060018192868501518155019401920161030e565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f830160051c810191602084106103ba575b601f0160051c01905b8181106103af5750610113565b5f81556001016103a2565b9091508190610399565b90607f1690610101565b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176102df5760405256fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714613a0057508063027b6744146139de57806306fdde0314613923578063081812fc14613905578063095ea7b3146138005780631400ecec1461374f5780631b1a433f1461366f5780631c1cdd4c1461360b5780631e897afb146135265780631e99d5691461350957806323b872dd146134f2578063303acc85146134b5578063406887cb1461334657806340e58ee514613082578063425d30dd1461303257806342842e0e1461300957806342966c6814612e4257806342e94a7b14612b7b5780634426757014612b555780634857501f14612ae45780634869e12d14612aaa5780634cc55e11146127165780636352211e1461245c5780636611ceab1461248b5780636d0cee751461245c57806370a08231146123f2578063727b3b0a1461228d57806375829def1461221f57806377163c1d146121e5578063780a82c8146121765780637b73dd9d146120e25780637cad6cd1146120055780637de6b1db14611ecb5780637f5799f914611db75780638659c27014611a125780638f69b993146119925780639067b6771461194357806395d89b411461183b578063a22cb46514611787578063a80fc07114611736578063ad35efd4146116eb578063ad7628cd14611575578063b256456914611525578063b637b865146113fe578063b88d4fde14611374578063b8a3be661461133f578063b971302a146112f1578063bc2be1be146112a2578063c156a11d14610e96578063c87b56dd14610d8b578063d4dbd20b14610d3a578063d511609f14610cef578063d6a03d3114610c19578063d975dfed14610bce578063df2a848c14610af3578063e6c417eb14610a88578063e985e9c514610a2f578063ea5ead19146106ff578063eac8f5b8146106ae578063f590c17614610652578063f851a4401461062d5763fdd46d60146102c6575f80fd5b34610629576060366003190112610629576004356102e2613b2d565b906044356001600160801b038116809103610629576102ff61480e565b815f52600a60205260ff600160405f20015460a81c161561061657815f52600a60205260ff600160405f20015460a01c16610603576001600160a01b03831680156105f057825f5260036020526001600160a01b0360405f2054169384821415806105df575b6105c55782156105b2576001600160801b0361038085615e84565b168084116105985750835f52600a60205282600260405f20015460801c016001600160801b038111610584576103df90855f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b835f52600a6020526103f6600260405f20016151f8565b6001600160801b0361041a8160208401511692826040818351169201511690613e09565b161115610552575b835f52600a602052610446836001600160a01b03600160405f200154169283615eaa565b81847f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051878152a45f8051602061606d8339815191526020604051858152a1833314158061053c575b61049957005b604051926392b9102b60e01b84526004840152336024840152604483015260648201526020816084815f865af1908115610531576392b9102b60e01b916001600160e01b0319915f91610502575b5016036104f057005b635f3a039d60e01b5f5260045260245ffd5b610524915060203d60201161052a575b61051c8183613d87565b810190614406565b5f6104e7565b503d610512565b6040513d5f823e3d90fd5b50835f52600960205260ff60405f205416610493565b5f848152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b19169055610422565b634e487b7160e01b5f52601160045260245ffd5b8385632176546160e01b5f5260045260245260445260645ffd5b83633dd1eadf60e21b5f5260045260245ffd5b50826297d0a360e61b5f526004523360245260445260645ffd5b506105ea858561522a565b15610365565b826316c90d2760e21b5f5260045260245ffd5b5063449491f560e11b5f5260045260245ffd5b50631643770160e21b5f5260045260245ffd5b5f80fd5b34610629575f3660031901126106295760206001600160a01b035f5416604051908152f35b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a602052602060405f205460f81c6040519015158152f35b631643770160e21b5f5260045260245ffd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a60205260206001600160a01b03600160405f20015416604051908152f35b346106295760403660031901126106295760043561071b613b2d565b61072482615e84565b9161072d61480e565b805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460a01c16610a1d576001600160a01b0382168015610a0a57815f5260036020526001600160a01b0360405f2054169384821415806109f9575b6109df576001600160801b03169283156109cc576001600160801b036107b884615e84565b168085116109b25750825f52600a60205283600260405f20015460801c016001600160801b0381116105845761081790845f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b825f52600a60205261082e600260405f20016151f8565b6001600160801b036108528160208401511692826040818351169201511690613e09565b161115610980575b825f52600a60205261087e846001600160a01b03600160405f200154169283615eaa565b81837f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051888152a45f8051602061606d8339815191526020604051848152a1833314158061096a575b6108db575b602083604051908152f35b604051916392b9102b60e01b8352600483015233602483015260448201528160648201526020816084815f875af1908115610531576392b9102b60e01b916001600160e01b0319915f9161094b575b5016036109385781806108d0565b50635f3a039d60e01b5f5260045260245ffd5b610964915060203d60201161052a5761051c8183613d87565b8561092a565b50835f52600960205260ff60405f2054166108cb565b5f838152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b1916905561085a565b8484632176546160e01b5f5260045260245260445260645ffd5b82633dd1eadf60e21b5f5260045260245ffd5b50906297d0a360e61b5f526004523360245260445260645ffd5b50610a04858461522a565b15610793565b506316c90d2760e21b5f5260045260245ffd5b63449491f560e11b5f5260045260245ffd5b3461062957604036600319011261062957610a48613b17565b6001600160a01b03610a58613b2d565b91165f5260066020526001600160a01b0360405f2091165f52602052602060ff60405f2054166040519015158152f35b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a60205260ff600160405f20015460b81c166040516003821015610adf576020918152f35b634e487b7160e01b5f52602160045260245ffd5b3461062957602036600319011261062957600435610b0f6143ee565b50805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460b81c166003811015610adf57610b9e575f52600e6020526040805f20815190610b6682613d14565b546001600160801b038116825260801c6020820152610b9c825180926001600160801b0360208092828151168552015116910152565bf35b5f52600a602052610bc560ff600160405f20015460b81c16637382cd8b60e01b5f52613dc5565b5f60245260445ffd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c57610c08602091615e84565b6001600160801b0360405191168152f35b3461062957366003190161016081126106295761014013610629576101443567ffffffffffffffff811161062957610c55903690600401613bdf565b610c5d61480e565b610c6636613e62565b90610c7081613f82565b92610c7e6040519485613d87565b818452602084019160061b81019036821161062957915b818310610cb0576020610ca88686615311565b604051908152f35b6040833603126106295760206040918251610cca81613d14565b610cd386613dd3565b8152610ce0838701613c10565b83820152815201920191610c95565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a6020526020600260405f20015460801c604051908152f35b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a60205260206001600160801b03600360405f20015416604051908152f35b3461062957602036600319011261062957600435610da881614426565b505f6001600160a01b0360085416916044604051809481937fe9dc637500000000000000000000000000000000000000000000000000000000835230600484015260248301525afa8015610531575f90610e19575b610e1590604051918291602083526020830190613af2565b0390f35b503d805f833e610e298183613d87565b8101906020818303126106295780519067ffffffffffffffff821161062957019080601f8301121561062957815191610e6183613da9565b91610e6f6040519384613d87565b8383526020848301011161062957610e1592610e919160208085019101613ad1565b610dfd565b3461062957604036600319011261062957600435610eb2613b2d565b610eba61480e565b815f52600a60205260ff600160405f20015460a81c161561061657815f5260036020526001600160a01b0360405f20541690610ef6828461522a565b1561128b576001600160801b03610f0c84615e84565b169081158015610f95575b506001600160a01b03811615610f8257610f39846001600160a01b03926150d1565b169182610f535783637e27328960e01b5f5260045260245ffd5b8084918403610f6757602083604051908152f35b9091506364283d7b60e01b5f5260045260245260445260645ffd5b633250574960e11b5f525f60045260245ffd5b610f9d61480e565b845f52600a60205260ff600160405f20015460a81c161561127857845f52600a60205260ff600160405f20015460a01c1661126557831561125257845f5260036020526001600160a01b0360405f205416908185141580611241575b61122757611214576001600160801b0361101286615e84565b168084116111fa5750845f52600a60205282600260405f20015460801c016001600160801b0381116105845761107190865f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b845f52600a602052611088600260405f20016151f8565b6001600160801b036110ac8160208401511692826040818351169201511690613e09565b1611156111c8575b845f52600a6020526001600160a01b03600160405f200154166110d8848683615eaa565b84867f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051888152a45f8051602061606d8339815191526020604051878152a180331415806111b2575b15610f17576040516392b9102b60e01b81528560048201523360248201528460448201528360648201526020816084815f865af1908115610531576392b9102b60e01b916001600160e01b0319915f91611193575b501614610f1757635f3a039d60e01b5f5260045260245ffd5b6111ac915060203d60201161052a5761051c8183613d87565b8861117a565b50805f52600960205260ff60405f205416611125565b5f858152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b191690556110b4565b8386632176546160e01b5f5260045260245260445260645ffd5b84633dd1eadf60e21b5f5260045260245ffd5b84866297d0a360e61b5f526004523360245260445260645ffd5b5061124c828761522a565b15610ff9565b846316c90d2760e21b5f5260045260245ffd5b8463449491f560e11b5f5260045260245ffd5b84631643770160e21b5f5260045260245ffd5b82634dda2c3960e11b5f526004523360245260445ffd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a602052602064ffffffffff60405f205460a01c16604051908152f35b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a60205260206001600160a01b0360405f205416604051908152f35b34610629576020366003190112610629576004355f52600a602052602060ff600160405f20015460a81c166040519015158152f35b346106295760803660031901126106295761138d613b17565b611395613b2d565b6064359167ffffffffffffffff83116106295736602384011215610629578260040135916113c283613da9565b926113d06040519485613d87565b8084523660248287010111610629576020815f9260246113fc98018388013785010152604435916142fe565b005b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460b81c166003811015610adf576001036114f4575f52600c60205260405f20805461146981613f82565b916114776040519384613d87565b81835260208301905f5260205f205f915b8383106114a55760405160208082528190610e1590820188613c79565b6001602081926040516114b781613ce4565b64ffffffffff86546001600160801b038116835267ffffffffffffffff8160801c168584015260c01c166040820152815201920192019190611488565b5f52600a60205261151b60ff600160405f20015460b81c16637382cd8b60e01b5f52613dc5565b600160245260445ffd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a602052602060ff600160405f20015460b01c166040519015158152f35b34610629573660031901610180811261062957610100136106295760403661010319011261062957604036610143190112610629576115b261480e565b6040514264ffffffffff166115c682613d14565b808252602082015f81525f9164ffffffffff6115e06142e9565b166116d2575b6101643564ffffffffff81168103610629570164ffffffffff16905261160a614263565b91611613614279565b61161b61428f565b6001600160a01b0361162b6142a5565b6001600160801b0361163b6142bb565b93836116456142ca565b96816040519b6116548d613d30565b168b521660208a015216604088015216606086015215156080850152151560a084015260c083015261168536613e29565b60e08301526040519061169782613d14565b610104356001600160801b038116810361062957825261012435916001600160801b038316830361062957602093610ca893858301526158af565b915064ffffffffff6116e26142e9565b830116916115e6565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c576117239061503d565b6040516005821015610adf576020918152f35b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a60205260206001600160801b03600260405f20015416604051908152f35b34610629576040366003190112610629576117a0613b17565b60243590811515809203610629576001600160a01b031690811561180f57335f52600660205260405f20825f5260205260405f2060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b507f5b08ba18000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b34610629575f366003190112610629576040515f6002548060011c90600181168015611939575b6020831081146119255782855290811561190157506001146118a3575b610e158361188f81850382613d87565b604051918291602083526020830190613af2565b91905060025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace915f905b8082106118e75750909150810160200161188f61187f565b9192600181602092548385880101520191019092916118cf565b60ff191660208086019190915291151560051b8401909101915061188f905061187f565b634e487b7160e01b5f52602260045260245ffd5b91607f1691611862565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a602052602064ffffffffff60405f205460c81c16604051908152f35b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c576119ca9061503d565b600581101580610adf5760028214908115611a06575b81156119f4575b6020826040519015158152f35b9050610adf57600460209114826119e7565b5050600381145f6119e0565b346106295760203660031901126106295760043567ffffffffffffffff811161062957611a43903690600401613b74565b90611a4c61480e565b5f915b808310611a5857005b611a638382846142d9565b3592611a6d61480e565b835f52600a60205260ff600160405f20015460a81c1615611da457835f52600a60205260ff600160405f20015460a01c165f14611ab7578363449491f560e11b5f5260045260245ffd5b909192805f52600a60205260405f205460f81c611d9257611aec815f52600a6020526001600160a01b0360405f205416331490565b15611d7c57611afa81614447565b90805f52600a602052611b12600260405f20016151f8565b916001600160801b038351166001600160801b0382161015611d6957815f52600a60205260ff60405f205460f01c1615611d5657806001600160801b03602081611b66948188511603169501511690613e09565b5f828152600a6020526040902080547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b179055916001600160801b038316908115611d31575b825f52600a602052600360405f20016001600160801b0382166001600160801b0319825416179055825f52600a6020526001600160a01b0360405f205416835f5260036020526001600160a01b0360405f20541694845f52600a60205285827f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa50611c786001600160a01b03600160405f2001541694611c50888588615eaa565b604080518b81526001600160801b03808b166020830152909216908201529081906060820190565b0390a45f8051602061606d8339815191526020604051868152a1845f52600960205260ff60405f205416611cb6575b50505050506001019190611a4f565b60405193630d4af11f60e31b855260048501526024840152604483015260648201526020816084815f865af190811561053157630d4af11f60e31b916001600160e01b0319915f91611d13575b5016036104f05780808080611ca7565b611d2b915060203d811161052a5761051c8183613d87565b87611d03565b825f52600a602052600160405f2001600160a01b60ff60a01b19825416179055611bb0565b50635c7470b760e01b5f5260045260245ffd5b5063fa36c71760e01b5f5260045260245ffd5b634dda2c3960e11b5f526004523360245260445ffd5b63e707ae4f60e01b5f5260045260245ffd5b83631643770160e21b5f5260045260245ffd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460b81c166003811015610adf57600203611e9a575f52600d60205260405f208054611e2281613f82565b91611e306040519384613d87565b81835260208301905f5260205f205f915b838310611e5e5760405160208082528190610e1590820188613c22565b600160208192604051611e7081613d14565b64ffffffffff86546001600160801b038116835260801c1683820152815201920192019190611e41565b5f52600a602052611ec160ff600160405f20015460b81c16637382cd8b60e01b5f52613dc5565b600260245260445ffd5b3461062957602036600319011261062957600435611ee761480e565b805f52600a60205260ff600160405f20015460a81c161561069c57611f0b8161503d565b6005811015610adf5760048103611f2f575063449491f560e11b5f5260045260245ffd5b60038103611f4a575063e707ae4f60e01b5f5260045260245ffd5b600214611ff357611f6f815f52600a6020526001600160a01b0360405f205416331490565b15611d7c57805f52600a60205260ff60405f205460f01c1615611fe1576020815f8051602061606d833981519152925f52600a825260405f2060ff60f01b19815416905560405190807f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f5f80a28152a1005b635c7470b760e01b5f5260045260245ffd5b63fa36c71760e01b5f5260045260245ffd5b34610629576020366003190112610629576004356001600160a01b038116809103610629576001600160a01b035f54163381036120cc575060085490806001600160a01b03198316176008556001600160a01b036040519216825260208201527fa2548bd4b805e907c1558a47b5858324fe8bb4a2e1ddfca647eecbf65610eebc60403392a26007545f1981019081116105845760407f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c91815190600182526020820152a1005b6331b339a960e21b5f526004523360245260445ffd5b346106295736600319016101a08112610629576101401361062957604036610143190112610629576101843564ffffffffff811681036106295761212461480e565b61212d36613e62565b906040519061213b82613d14565b610144356001600160801b038116810361062957825261016435916001600160801b038316830361062957602093610ca893858301526158af565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460b81c166003811015610adf57610b9e575f52600b602052602064ffffffffff60405f205416604051908152f35b34610629575f3660031901126106295760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461062957602036600319011261062957612238613b17565b5f546001600160a01b0381163381036120cc57506001600160a01b036001600160a01b0319921691829116175f55337fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf805f80a3005b346106295760203660031901126106295760043567ffffffffffffffff8111610629576122be903690600401613b74565b906122c761480e565b5f915b8083106122d357005b6122de8382846142d9565b35926122e861480e565b835f52600a60205260ff600160405f20015460a81c1615611da45761230c8461503d565b6005811015610adf5760048103612330578463449491f560e11b5f5260045260245ffd5b6003810361234b578463e707ae4f60e01b5f5260045260245ffd5b92939192909190600214611ff357612377815f52600a6020526001600160a01b0360405f205416331490565b15611d7c57805f52600a60205260ff60405f205460f01c1615611fe157905f8051602061606d8339815191526020836001945f52600a825260405f2060ff60f01b19815416905560405190807f0eb069207093cd3e51cd1370d2d369770057fbe29947e577e5fb428c6c6fc78f5f80a28152a10191906122ca565b34610629576020366003190112610629576001600160a01b03612413613b17565b168015612430575f526004602052602060405f2054604051908152f35b7f89c62b64000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b3461062957602036600319011261062957602061247a600435614426565b6001600160a01b0360405191168152f35b3461062957366003190161012081126106295761010013610629576101043567ffffffffffffffff8111610629576124c7903690600401613bdf565b6124cf61480e565b6040519182917f66f401dd000000000000000000000000000000000000000000000000000000008352806024840160206004860152526044830191905f5b8181106126d257845f8180870381737715be116061e014bb721b46dc78dd57c91fdf9b5af4908115610531575f91612610575b5080515f198101908111610584578164ffffffffff6020612565610ca894829661423b565b510151166040519061257682613d14565b64ffffffffff421682528482015261258c614263565b90612595614279565b61259d61428f565b6001600160a01b036125ad6142a5565b6001600160801b036125bd6142bb565b93836125c76142ca565b96816040519a6125d68c613d30565b168a52168b89015216604087015216606085015215156080840152151560a083015260c082015261260636613e29565b60e0820152615311565b90503d805f833e6126218183613d87565b8101906020818303126106295780519067ffffffffffffffff8211610629570181601f820112156106295780519061265882613f82565b926126666040519485613d87565b82845260208085019360061b8301019181831161062957602001925b828410612693575050505081612540565b60408483031261062957602060409182516126ad81613d14565b6126b687614215565b81526126c3838801614229565b83820152815201930192612682565b919350916040806001926001600160801b036126ed88613dd3565b16815264ffffffffff61270260208901613c10565b16602082015201940191019184939261250d565b346106295760403660031901126106295760043567ffffffffffffffff811161062957612747903690600401613b74565b60243567ffffffffffffffff811161062957612767903690600401613b74565b61277293919361480e565b808303612a7b575f5b83811061278457005b61278f8185856142d9565b3561279b8286866142d9565b355f5260036020526001600160a01b0360405f205416906127bd8385896142d9565b356001600160801b0381169081810361062957506127d961480e565b815f52600a60205260ff600160405f20015460a81c161561061657815f52600a60205260ff600160405f20015460a01c16610603578215610a0a57815f5260036020526001600160a01b0360405f205416928381141580612a6a575b612a515781156109cc576001600160801b0361285084615e84565b16808311612a375750825f52600a60205281600260405f20015460801c016001600160801b038111610584576128af90845f52600a602052600260405f2001906001600160801b036001600160801b031983549260801b169116179055565b825f52600a6020526128c6600260405f20016151f8565b6001600160801b036128ea8160208401511692826040818351169201511690613e09565b161115612a05575b825f52600a6020526001600160a01b03600160405f20015416612916838383615eaa565b81847f40b88e5c41c5a97ffb7b6ef88a0a2d505aa0c634cf8a0275cb236ea7dd87ed4d6020604051878152a45f8051602061606d8339815191526020604051858152a183331415806129ef575b612974575b5050505060010161277b565b604051926392b9102b60e01b84526004840152336024840152604483015260648201526020816084815f865af1908115610531576392b9102b60e01b916001600160e01b0319915f916129d1575b5016036104f057808080612968565b6129e9915060203d811161052a5761051c8183613d87565b896129c2565b50835f52600960205260ff60405f205416612963565b5f838152600a6020526040902060018101805460ff60a01b1916600160a01b179055805460ff60f01b191690556128f2565b8284632176546160e01b5f5260045260245260445260645ffd5b826297d0a360e61b5f526004523360245260445260645ffd5b50612a75848461522a565b15612835565b827fc0a1a35a000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c57610c08602091615290565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f612b1d8261503d565b6005811015610adf57600203612b3b575b6020906040519015158152f35b505f52600a602052602060ff60405f205460f01c16612b2e565b34610629575f3660031901126106295760206001600160a01b0360085416604051908152f35b3461062957366003190161012081126106295761010013610629576101043567ffffffffffffffff811161062957612bb7903690600401613b43565b612bbf61480e565b6040519182917fca31a854000000000000000000000000000000000000000000000000000000008352806024840160206004860152526044830191905f5b818110612de357845f8180870381737715be116061e014bb721b46dc78dd57c91fdf9b5af4908115610531575f91612d01575b5080515f198101908111610584578164ffffffffff6040612c56610ca89460209661423b565b5101511660405190612c6782613d14565b64ffffffffff4216825284820152612c7d614263565b90612c86614279565b612c8e61428f565b6001600160a01b03612c9e6142a5565b6001600160801b03612cae6142bb565b9383612cb86142ca565b96816040519a612cc78c613d30565b168a52168b89015216604087015216606085015215156080840152151560a083015260c0820152612cf736613e29565b60e0820152614957565b90503d805f833e612d128183613d87565b8101906020818303126106295780519067ffffffffffffffff8211610629570181601f8201121561062957805190612d4982613f82565b92612d576040519485613d87565b8284526020606081860194028301019181831161062957602001925b828410612d84575050505081612c30565b6060848303126106295760405190612d9b82613ce4565b612da485614215565b825260208501519067ffffffffffffffff821682036106295782602092836060950152612dd360408801614229565b6040820152815201930192612d73565b919350916060806001926001600160801b03612dfe88613dd3565b16815267ffffffffffffffff612e1660208901613f9a565b16602082015264ffffffffff612e2e60408901613c10565b166040820152019401910191849392612bfd565b3461062957602036600319011261062957600435612e5e61480e565b805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460a01c1615612fde57805f526003602052612eb36001600160a01b0360405f2054168261522a565b15611d7c57805f5260036020526001600160a01b0360405f205416151580612fd7575b80612fba575b612fa8575f8051602061606d8339815191526020604051838152a1805f5260036020526001600160a01b0360405f2054168015908115612f71575b825f52600360205260405f206001600160a01b03198154169055825f827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a450612f5f57005b637e27328960e01b5f5260045260245ffd5b612f90835f52600560205260405f206001600160a01b03198154169055565b805f52600460205260405f205f198154019055612f17565b6349d74b1160e11b5f5260045260245ffd5b50805f52600a60205260ff600160405f20015460b01c1615612edc565b505f612ed6565b7fa6ba32da000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b34610629576113fc61301a36613ba5565b906040519261302a602085613d87565b5f84526142fe565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c575f52600a602052602060ff600160405f20015460a01c166040519015158152f35b346106295760203660031901126106295760043561309e61480e565b805f52600a60205260ff600160405f20015460a81c161561069c57805f52600a60205260ff600160405f20015460a01c165f146130e75763449491f560e11b5f5260045260245ffd5b805f52600a60205260405f205460f81c611d9257613119815f52600a6020526001600160a01b0360405f205416331490565b15611d7c5761312781614447565b90805f52600a60205261313f600260405f20016151f8565b916001600160801b038351166001600160801b0382161015611d6957815f52600a60205260ff60405f205460f01c1615611d5657806001600160801b03602081613193948188511603169501511690613e09565b5f828152600a6020526040902080547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b179055916001600160801b038316908115613321575b825f52600a602052600360405f20016001600160801b0382166001600160801b0319825416179055825f52600a6020526001600160a01b0360405f205416835f5260036020526001600160a01b0360405f20541694845f52600a60205285827f5edb27d6c1a327513b90a792050debf074b7194444885e3144d4decc5caaaa5061327d6001600160a01b03600160405f2001541694611c50888588615eaa565b0390a45f8051602061606d8339815191526020604051868152a1845f52600960205260ff60405f2054166132ad57005b60405193630d4af11f60e31b855260048501526024840152604483015260648201526020816084815f865af190811561053157630d4af11f60e31b916001600160e01b0319915f91613302575016036104f057005b61331b915060203d60201161052a5761051c8183613d87565b846104e7565b825f52600a602052600160405f2001600160a01b60ff60a01b198254161790556131dd565b346106295760203660031901126106295761335f613b17565b6001600160a01b035f54169033820361349e57806001600160a01b03913b1561347257166040516301ffc9a760e01b81527ff8ee98d3000000000000000000000000000000000000000000000000000000006004820152602081602481855afa908115610531575f91613443575b501561341857805f52600960205260405f20600160ff198254161790556040519081527fb4378d4e289cb3f40f4f75a99c9cafa76e3df1c4dc31309babc23dc91bd7280160203392a2005b7f976c0d64000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b613465915060203d60201161346b575b61345d8183613d87565b8101906141fd565b826133cd565b503d613453565b7f65453b0d000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b506331b339a960e21b5f526004523360245260445ffd5b34610629576020366003190112610629576001600160a01b036134d6613b17565b165f526009602052602060ff60405f2054166040519015158152f35b34610629576113fc61350336613ba5565b91613fde565b34610629575f366003190112610629576020600754604051908152f35b346106295760203660031901126106295760043567ffffffffffffffff811161062957613557903690600401613b74565b9036819003601e1901905f5b838110156113fc578060051b8201358381121561062957820180359067ffffffffffffffff821161062957602001813603811361062957815f92918392604051928392833781018381520390305af46135ba613faf565b90156135c95750600101613563565b613607906040519182917fd9354485000000000000000000000000000000000000000000000000000000008352602060048401526024830190613af2565b0390fd5b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c576136439061503d565b6005811015610adf578060209115908115613664575b506040519015158152f35b600191501482613659565b3461062957366003190161016081126106295761014013610629576101443567ffffffffffffffff8111610629576136ab903690600401613b43565b6136b361480e565b6136bc36613e62565b906136c681613f82565b926136d46040519485613d87565b818452606060208501920281019036821161062957915b8183106136fe576020610ca88686614957565b60608336031261062957602060609160405161371981613ce4565b61372286613dd3565b815261372f838701613f9a565b8382015261373f60408701613c10565b60408201528152019201916136eb565b3461062957602036600319011261062957600435805f52600a60205260ff600160405f20015460a81c161561069c576020905f90805f52600a835260ff60405f205460f01c16806137e4575b6137b2575b506001600160801b0360405191168152f35b6137de9150805f52600a83526137d86001600160801b03600260405f2001541691614447565b90613e09565b826137a0565b50805f52600a835260ff600160405f20015460a01c161561379b565b3461062957604036600319011261062957613819613b17565b60243561382581614426565b331515806138f2575b806138bf575b6138935781906001600160a01b0380851691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a45f5260056020526001600160a01b0360405f2091166001600160a01b03198254161790555f80f35b7fa9fbf51f000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b506001600160a01b0381165f52600660205260405f206001600160a01b0333165f5260205260ff60405f20541615613834565b50336001600160a01b038216141561382e565b3461062957602036600319011261062957602061247a600435613de7565b34610629575f366003190112610629576040515f6001548060011c906001811680156139d4575b60208310811461192557828552908115611901575060011461397657610e158361188f81850382613d87565b91905060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6915f905b8082106139ba5750909150810160200161188f61187f565b9192600181602092548385880101520191019092916139a2565b91607f169161394a565b34610629575f36600319011261062957602060405167016345785d8a00008152f35b3461062957602036600319011261062957600435906001600160e01b0319821680920361062957817f490649060000000000000000000000000000000000000000000000000000000060209314908115613a5c575b5015158152f35b7f80ac58cd00000000000000000000000000000000000000000000000000000000811491508115613aa7575b8115613a96575b5083613a55565b6301ffc9a760e01b91501483613a8f565b7f5b5e139f0000000000000000000000000000000000000000000000000000000081149150613a88565b5f5b838110613ae25750505f910152565b8181015183820152602001613ad3565b90602091613b0b81518092818552858086019101613ad1565b601f01601f1916010190565b600435906001600160a01b038216820361062957565b602435906001600160a01b038216820361062957565b9181601f840112156106295782359167ffffffffffffffff8311610629576020808501946060850201011161062957565b9181601f840112156106295782359167ffffffffffffffff8311610629576020808501948460051b01011161062957565b6060906003190112610629576004356001600160a01b038116810361062957906024356001600160a01b0381168103610629579060443590565b9181601f840112156106295782359167ffffffffffffffff8311610629576020808501948460061b01011161062957565b359064ffffffffff8216820361062957565b90602080835192838152019201905f5b818110613c3f5750505090565b9091926020604082613c6e600194885164ffffffffff602080926001600160801b038151168552015116910152565b019401929101613c32565b90602080835192838152019201905f5b818110613c965750505090565b9091926020606082613cd9600194885164ffffffffff604080926001600160801b03815116855267ffffffffffffffff6020820151166020860152015116910152565b019401929101613c89565b6060810190811067ffffffffffffffff821117613d0057604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff821117613d0057604052565b610100810190811067ffffffffffffffff821117613d0057604052565b610120810190811067ffffffffffffffff821117613d0057604052565b610160810190811067ffffffffffffffff821117613d0057604052565b90601f8019910116810190811067ffffffffffffffff821117613d0057604052565b67ffffffffffffffff8111613d0057601f01601f191660200190565b6003811015610adf57600452565b35906001600160801b038216820361062957565b613df081614426565b505f5260056020526001600160a01b0360405f20541690565b906001600160801b03809116911603906001600160801b03821161058457565b60409060c31901126106295760405190613e4282613d14565b8160c4356001600160a01b0381168103610629578152602060e435910152565b9061014060031983011261062957604051613e7c81613d30565b80926004356001600160a01b03811681036106295782526024356001600160a01b03811681036106295760208301526044356001600160801b03811681036106295760408301526064356001600160a01b0381168103610629576060830152608435801515810361062957608083015260a43580151581036106295760a0830152604060c31982011261062957604051613f1581613d14565b60c43564ffffffffff8116810361062957815260e43564ffffffffff8116810361062957602082015260c08301526040610104809203126106295760405191613f5d83613d14565b81356001600160a01b03811681036106295760e0926020918552013560208401520152565b67ffffffffffffffff8111613d005760051b60200190565b359067ffffffffffffffff8216820361062957565b3d15613fd9573d90613fc082613da9565b91613fce6040519384613d87565b82523d5f602084013e565b606090565b91906001600160a01b03168015610f8257815f5260036020526001600160a01b0360405f2054161515806141f5575b806141d8575b6141c5575f8051602061606d8339815191526020604051848152a1815f5260036020526001600160a01b0360405f20541692823315159283614110575b6001600160a01b039350856140d9575b805f52600460205260405f2060018154019055815f52600360205260405f20816001600160a01b0319825416179055857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4168083036140c157505050565b6364283d7b60e01b5f5260045260245260445260645ffd5b6140f8825f52600560205260405f206001600160a01b03198154169055565b855f52600460205260405f205f198154019055614060565b919290508061416e575b1561412757828291614050565b828461413f57637e27328960e01b5f5260045260245ffd5b7f177e802f000000000000000000000000000000000000000000000000000000005f523360045260245260445ffd5b50338414801561419c575b8061411a5750825f526005602052336001600160a01b0360405f2054161461411a565b50835f52600660205260405f206001600160a01b0333165f5260205260ff60405f205416614179565b506349d74b1160e11b5f5260045260245ffd5b50815f52600a60205260ff600160405f20015460b01c1615614013565b50600161400d565b90816020910312610629575180151581036106295790565b51906001600160801b038216820361062957565b519064ffffffffff8216820361062957565b805182101561424f5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6004356001600160a01b03811681036106295790565b6024356001600160a01b03811681036106295790565b6044356001600160801b03811681036106295790565b6064356001600160a01b03811681036106295790565b60843580151581036106295790565b60a43580151581036106295790565b919081101561424f5760051b0190565b6101443564ffffffffff811681036106295790565b9061430a838284613fde565b803b614317575b50505050565b60209161435d6001600160a01b03809316956040519586948594630a85bd0160e11b86523360048701521660248501526044840152608060648401526084830190613af2565b03815f865af15f91816143cd575b506143995750614379613faf565b805190816143945782633250574960e11b5f5260045260245ffd5b602001fd5b6001600160e01b0319630a85bd0160e11b9116036143bb57505f808080614311565b633250574960e11b5f5260045260245ffd5b6143e791925060203d60201161052a5761051c8183613d87565b905f61436b565b604051906143fb82613d14565b5f6020838281520152565b9081602091031261062957516001600160e01b0319811681036106295790565b805f5260036020526001600160a01b0360405f205416908115612f5f575090565b5f818152600a6020526040908190205490519064ffffffffff60c882901c81169160a01c1661447583613d14565b8083526020830191825264ffffffffff42168091101561480657835f52600a60205264ffffffffff6001600160801b03600260405f200154169251161115614800575f835f52600a60205260ff600160405f20015460b81c166003811015610adf57600181036146195750505090805f52600c60205264ffffffffff60405f20925116905f52600a602052600260405f20015460801c906040519283917f63ec2f5a0000000000000000000000000000000000000000000000000000000083526064830160606004850152825480915260848401925f5260205f20905f5b8181106145d3575050509060209383926024840152604483015203817326f9d826bded47fc472526ae8095b75ac336963c5af4908115610531575f91614599575b505b90565b90506020813d6020116145cb575b816145b460209383613d87565b81010312610629576145c590614215565b5f614594565b3d91506145a7565b82546001600160801b0381168652608081901c67ffffffffffffffff16602087015260c01c64ffffffffff16604086015287955060609094019360019283019201614553565b919391806146f3575050805f52600b60205264ffffffffff60405f205416815f52600e60205260405f20915f52600a6020526146a3600260405f20015460801c93604051957f9465928b0000000000000000000000000000000000000000000000000000000087526004870152602486019064ffffffffff60208092828151168552015116910152565b6064840152546001600160801b038116608484015260801c60a483015260c482015260208160e4817326f9d826bded47fc472526ae8095b75ac336963c5af4908115610531575f91614599575090565b909350600291925014614704575090565b90505f52600d60205260405f2060405180917f5515a8160000000000000000000000000000000000000000000000000000000082526024820160206004840152815480915260448301915f5260205f20905f5b8181106147ce57505050908060209203817326f9d826bded47fc472526ae8095b75ac336963c5af4908115610531575f91614794575b505f614594565b90506020813d6020116147c6575b816147af60209383613d87565b81010312610629576147c090614215565b5f61478d565b3d91506147a2565b82546001600160801b038116855260801c64ffffffffff16602085015285945060409093019260019283019201614757565b91505090565b505050505f90565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361484057565b7fa1c0d6e5000000000000000000000000000000000000000000000000000000005f5260045ffd5b908160409103126106295761489660206040519261488584613d14565b61488e81614215565b845201614215565b602082015290565b805482101561424f575f5260205f2001905f90565b6001600160a01b0361010061014092828151168552826020820151166020860152826040820151166040860152614907606082015160608701906001600160801b0360208092828151168552015116910152565b8260808201511660a086015260a0810151151560c086015260c0810151151560e086015261494f60e08201518387019064ffffffffff60208092828151168552015116910152565b015116910152565b91906001600160a01b03835116906149da60c0850180516001600160801b036040880151169060e0880195602087510151926040519586937ffb6164dd0000000000000000000000000000000000000000000000000000000085526101048501936004860152602485019064ffffffffff60208092828151168552015116910152565b60648301526101006084830152855180915261012482019060208701905f5b818110614fe95750505081906040937f000000000000000000000000000000000000000000000000000000000000000060a484015260c483015267016345785d8a000060e48301520381737715be116061e014bb721b46dc78dd57c91fdf9b5af4918215610531575f92614fb8575b506007549583515f5b818110614ea6575050604051614a8681613d4d565b5f8152602081015f9052604081015f9052604051614aa381613d14565b5f8152602081015f90526060820152608081015f905260a081015f905260c081015f9052604051614ad381613d14565b5f8152602081015f905260e0820152610100015f905280516001600160a01b031693825195865164ffffffffff16966020015164ffffffffff16906080840196875115158b606087019485516001600160a01b031660a089019c8d511515928c516001600160801b03169560405196614b4b88613ce4565b8752602087015f9052604087015f905260405197614b6889613d6a565b885260208801928352604088019182526060880190815260808801905f825260a0890194855260c08901925f845260e08a0194600186526101008b019788526101208b019860018a526101408c019a8b525f52600a60205260405f209a516001600160a01b03166001600160a01b03168b546001600160a01b031916178b5551908a54905160c81b64ffffffffff60c81b169160a01b64ffffffffff60a01b169069ffffffffffffffffffff60a01b191617178955511515614c4190899060ff60f01b1960ff60f01b835492151560f01b169116179055565b5187546001600160f81b031690151560f81b7fff00000000000000000000000000000000000000000000000000000000000000161787559151600187018054935160ff60a01b90151560a01b166001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff19909416939093171782555115159381549251151560b01b60ff60b01b169351916003831015610adf5762ffffff60a81b1990931660a89590951b60ff60a81b169490941790921760b89290921b60ff60b81b16919091179055518051602082015160801b6001600160801b0319166001600160801b039182161760028401559060039082906040015116920191166001600160801b031982541617905560208401946001600160a01b038651168015610f8257614d758c6001600160a01b03926150d1565b16614e7a578a987f57d31f8bb3cedf51e9d4ce840aca90a0f5fef3e4269c3dc4b52333edc973429198614e46986001600160a01b038080808f9b6001614e5a9d01600755614dd5828c51166001600160801b038851169030903390615f01565b6001600160801b0360208701511680614e5f575b5051169b511697511692511515935115159451955151169560405199614e0e8b613d4d565b338b5260208b015260408a01526060890152608088015260a087015260c086015260e0850152610100840152604051938480946148b3565b610180610160840152610180830190613c79565b0390a2565b614e7490838d5116848d515116903390615f01565b5f614de9565b7f73c6ac6e000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b885f52600c60205260405f2090614ebd818861423b565b5191805468010000000000000000811015613d0057614ee19160018201815561489e565b614fa557826001600160801b03806001955116166001600160801b03198354161782556020810151907fffffff00000000000000000000000000ffffffffffffffffffffffffffffffff7cffffffffff000000000000000000000000000000000000000000000000604077ffffffffffffffff0000000000000000000000000000000086549560801b1693847fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff8716178755015160c01b1692161717905501614a71565b634e487b7160e01b5f525f60045260245ffd5b614fdb91925060403d604011614fe2575b614fd38183613d87565b810190614868565b905f614a68565b503d614fc9565b9194935091602060608261502e600194895164ffffffffff604080926001600160801b03815116855267ffffffffffffffff6020820151166020860152015116910152565b019501910191869394926149f9565b805f52600a60205260ff600160405f20015460a01c165f1461505f5750600490565b805f52600a60205260405f205460f81c6150cb57805f52600a60205264ffffffffff60405f205460a01c1642106150c65761509981614447565b905f52600a6020526001600160801b0380600260405f200154169116105f146150c157600190565b600290565b505f90565b50600390565b90805f5260036020526001600160a01b0360405f2054161515806151e6575b806151c9575b612fa8575f8051602061606d8339815191526020604051838152a1805f5260036020526001600160a01b038060405f2054169283615192575b168061517a575b815f52600360205260405f20816001600160a01b0319825416179055827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a490565b805f52600460205260405f2060018154019055615136565b6151b1835f52600560205260405f206001600160a01b03198154169055565b835f52600460205260405f205f19815401905561512f565b50805f52600a60205260ff600160405f20015460b01c16156150f6565b506001600160a01b03821615156150f0565b9060405161520581613ce4565b60406001600160801b03600183958054838116865260801c6020860152015416910152565b906001600160a01b031690813314918215615264575b50811561524b575090565b90506001600160a01b0361525f3392613de7565b161490565b9091505f52600660205260405f206001600160a01b0333165f5260205260ff60405f205416905f615240565b805f52600a6020526152a7600260405f20016151f8565b90805f52600a60205260ff600160405f20015460a01c165f146152d55750602001516001600160801b031690565b90815f52600a60205260405f205460f81c6152f4575061459690614447565b61459691506001600160801b036040818351169201511690613e09565b91906001600160a01b038351169061539460c0850180516001600160801b036040880151169060e0880195602087510151926040519586937f07aaee4b0000000000000000000000000000000000000000000000000000000085526101048501936004860152602485019064ffffffffff60208092828151168552015116910152565b60648301526101006084830152855180915261012482019060208701905f5b81811061586f5750505081906040937f000000000000000000000000000000000000000000000000000000000000000060a484015260c483015267016345785d8a000060e48301520381737715be116061e014bb721b46dc78dd57c91fdf9b5af4918215610531575f9261584e575b506007549583515f5b8181106157a357505060405161544081613d4d565b5f8152602081015f9052604081015f905260405161545d81613d14565b5f8152602081015f90526060820152608081015f905260a081015f905260c081015f905260405161548d81613d14565b5f8152602081015f905260e0820152610100015f905280516001600160a01b031693825195865164ffffffffff16966020015164ffffffffff16906080840196875115158b606087019485516001600160a01b031660a089019c8d511515928c516001600160801b0316956040519661550588613ce4565b8752602087015f9052604087015f90526040519761552289613d6a565b885260208801928352604088019182526060880190815260808801905f825260a0890194855260c08901925f845260e08a0194600186526101008b019788526101208b019860028a526101408c019a8b525f52600a60205260405f209a516001600160a01b03166001600160a01b03168b546001600160a01b031916178b5551908a54905160c81b64ffffffffff60c81b169160a01b64ffffffffff60a01b169069ffffffffffffffffffff60a01b1916171789555115156155fb90899060ff60f01b1960ff60f01b835492151560f01b169116179055565b5187546001600160f81b031690151560f81b7fff00000000000000000000000000000000000000000000000000000000000000161787559151600187018054935160ff60a01b90151560a01b166001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff19909416939093171782555115159381549251151560b01b60ff60b01b169351916003831015610adf5762ffffff60a81b1990931660a89590951b60ff60a81b169490941790921760b89290921b60ff60b81b16919091179055518051602082015160801b6001600160801b0319166001600160801b039182161760028401559060039082906040015116920191166001600160801b031982541617905560208401946001600160a01b038651168015610f825761572f8c6001600160a01b03926150d1565b16614e7a578a987f3791edd755f0a379ba7622d643751f1fa19ee54a734a43502c4892a34ce8fe719861578f986001600160a01b038080808f9b6001614e5a9d01600755614dd5828c51166001600160801b038851169030903390615f01565b610180610160840152610180830190613c22565b885f52600d60205260405f20906157ba818861423b565b5191805468010000000000000000811015613d00576157de9160018201815561489e565b614fa5576020836001600160801b03806001965116166001600160801b031984541617835501517fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff74ffffffffff0000000000000000000000000000000083549260801b1691161790550161542b565b61586891925060403d604011614fe257614fd38183613d87565b905f615422565b919493509160206040826158a0600194895164ffffffffff602080926001600160801b038151168552015116910152565b019501910191869394926153b3565b929190926001600160a01b0381511660c082018051926001600160801b036040820151169364ffffffffff60e083019661593260208951015193604051977fe7de03ce0000000000000000000000000000000000000000000000000000000089526004890152602488019064ffffffffff60208092828151168552015116910152565b1694856064860152608485015261596160a48501896001600160801b0360208092828151168552015116910152565b60e484015267016345785d8a000061010484015260408361012481737715be116061e014bb721b46dc78dd57c91fdf9b5af4928315610531575f93615e63575b50600754966001600160801b0381511680615e38575b5084615dce575b6040516159ca81613d4d565b5f8152602081015f9052604081015f90526040516159e781613d14565b5f8152602081015f90526060820152608081015f905260a081015f905260c081015f9052604051615a1781613d14565b5f8152602081015f905260e0820152610100015f905281516001600160a01b031694835196875164ffffffffff16976020015164ffffffffff16906080850197885115158c606088019485516001600160a01b031660a08a019d8e511515928d516001600160801b03169560405196615a8f88613ce4565b8752602087015f9052604087015f905260405197615aac89613d6a565b885260208801928352604088019182526060880190815260808801905f825260a0890194855260c08901925f845260e08a0194600186526101008b019788526101208b01985f8a526101408c019a8b525f52600a60205260405f209a516001600160a01b03166001600160a01b03168b546001600160a01b031916178b5551908a54905160c81b64ffffffffff60c81b169160a01b64ffffffffff60a01b169069ffffffffffffffffffff60a01b191617178955511515615b8490899060ff60f01b1960ff60f01b835492151560f01b169116179055565b5187546001600160f81b031690151560f81b7fff00000000000000000000000000000000000000000000000000000000000000161787559151600187018054935160ff60a01b90151560a01b166001600160a01b0390921674ffffffffffffffffffffffffffffffffffffffffff19909416939093171782555115159381549251151560b01b60ff60b01b169351916003831015610adf5762ffffff60a81b1990931660a89590951b60ff60a81b169490941790921760b89290921b60ff60b81b16919091179055518051602082015160801b6001600160801b0319166001600160801b039182161760028401559060039082906040015116920191166001600160801b031982541617905560208501956001600160a01b038751168015610f8257615cb88d6001600160a01b03926150d1565b16614e7a578b997ffab1da036cbdbf2bb53bc19bb2c81ca5819d3b35a0583fa45b5a8401097ce839996101c0996001600160a01b0380808f615db09c6001839201600755615d18828c51166001600160801b038851169030903390615f01565b6001600160801b0360208701511680615db3575b5051169c51169751169251151593511515945195515116956040519a615d518c613d4d565b338c5260208c015260408b015260608a0152608089015260a088015260c087015260e0860152610100850152615d8a60405180956148b3565b6101608401526101808301906001600160801b0360208092828151168552015116910152565ba2565b615dc890838d5116848d515116903390615f01565b5f615d2c565b875f52600b60205260405f208564ffffffffff198254161790556001600160801b0360208201511680615e02575b506159be565b615e3290895f52600e60205260405f20906001600160801b036001600160801b031983549260801b169116179055565b5f615dfc565b885f52600e6020526001600160801b0360405f2091166001600160801b03198254161790555f6159b7565b615e7d91935060403d604011614fe257614fd38183613d87565b915f6159a1565b61459690615e9181615290565b905f52600a602052600260405f20015460801c90613e09565b615eff926001600160a01b03604051937fa9059cbb000000000000000000000000000000000000000000000000000000006020860152166024840152604483015260448252615efa606483613d87565b615f5b565b565b9091926001600160a01b03615eff9481604051957f23b872dd000000000000000000000000000000000000000000000000000000006020880152166024860152166044840152606483015260648252615efa608483613d87565b5f806001600160a01b03615f8493169360208151910182865af1615f7d613faf565b9083615fe0565b8051908115159182615fc5575b5050615f9a5750565b7f5274afe7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b615fd892506020809183010191016141fd565b155f80615f91565b9061601d5750805115615ff557805190602001fd5b7f1425ea42000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580616063575b61602e575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561602656fef8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7a164736f6c634300081a000a"; bytes public constant BYTECODE_NFT_DESCRIPTOR = hex"6080806040523460155761600c908161001a8239f35b5f80fdfe6102406040526004361015610012575f80fd5b5f3560e01c63e9dc637514610025575f80fd5b346141bc5760403660031901126141bc576001600160a01b036004351680600435036141bc576103e06040525f61024081905260606102608190526102808290526102a08290526102c0819052610300819052610320819052610340819052610360819052610380526103a08190526103c0526102e08190526100b6906100ad600435614824565b61030052614b9d565b610320526102e0516040517feac8f5b80000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156145b8575f91614681575b506001600160a01b0361012791168061024052614c99565b610260526102e0516040517fa80fc0710000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156145b8576fffffffffffffffffffffffffffffffff915f91614662575b5016610280526102e0516040517fad35efd40000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa80156145b8575f90614625575b6101f59150614e3b565b610360526102e0516040517f4869e12d0000000000000000000000000000000000000000000000000000000081526024803560048301529091602091839182906001600160a01b03165afa9081156145b8575f916145f6575b50610280516fffffffffffffffffffffffffffffffff1680156145e2576fffffffffffffffffffffffffffffffff612710819302160416610160610240015260405160208101904682526bffffffffffffffffffffffff1960043560601b1660408201526024356054820152605481526102c9607482614710565b51902061040a60028061016861ffff8560101c160693600161031c63ffffffff601e61031482601461030c82604660ff6050818d60081c16069b16069d16615568565b970116615568565b980116615568565b60246040519788947f68736c2800000000000000000000000000000000000000000000000000000000602087015261035d815180926020868a0191016146ca565b85017f2c00000000000000000000000000000000000000000000000000000000000000838201526103988251809360206025850191016146ca565b01017f252c000000000000000000000000000000000000000000000000000000000000838201526103d38251809360206003850191016146ca565b01017f2529000000000000000000000000000000000000000000000000000000000000838201520301601d19810184520182614710565b6104446fffffffffffffffffffffffffffffffff604061024001511660ff61043d6001600160a01b036102405116614f3b565b16906150a1565b9061045a6001600160a01b036102405116614b9d565b906020610240015190602460206001600160a01b0360a0610240015116604051928380927fbc2be1be000000000000000000000000000000000000000000000000000000008252823560048301525afa80156145b8576024915f916145c3575b5060206001600160a01b0360a0610240015116604051938480927f9067b677000000000000000000000000000000000000000000000000000000008252823560048301525afa80156145b85764ffffffffff8091610522945f91614589575b50169116615397565b610320516103a051939091906105ac600161054a6064610543818a06615a13565b9804615568565b602060405198826105648b945180928580880191016146ca565b8301610578825180938580850191016146ca565b01017f2500000000000000000000000000000000000000000000000000000000000000815203601e19810188520186614710565b61016061024001519561012061024001519760c061024001519560405161016052610140610160510161016051811067ffffffffffffffff821117614575576040526101605152602061016051015260406101605101526060610160510152608061016051015260a061016051015260c061016051015260e06101605101526101006101605101526101206101605101526040516101c0810181811067ffffffffffffffff82111761457557604052606081525f60208201525f60408201526060808201525f6080820152606060a08201525f60c08201525f60e082015260606101008201525f6101208201525f61014082015260606101608201525f6101808201525f6101a082015260e06101605101516108ec6109cb60046007602760586106e3610100610160510151610160515190615b14565b60b76106ee5f615e04565b985f6102205260206102205261071660405161070d6102205182614710565b5f815284615832565b1561456b57601b60909a5b61072a8c615568565b906040519b8c9889937f3c672069643d220000000000000000000000000000000000000000000000000061022051860152835161077081846102205188019801886146ca565b8b017f222066696c6c3d2223666666223e000000000000000000000000000000000000838201527f3c726563742077696474683d220000000000000000000000000000000000000060358201526107d382518093604284019061022051016146ca565b0101917f22206865696768743d22313030222066696c6c2d6f7061636974793d222e3033858401527f222072783d223135222072793d22313522207374726f6b653d22236666662220603b8401527f7374726f6b652d6f7061636974793d222e3122207374726f6b652d7769647468605b8401527f3d2234222f3e0000000000000000000000000000000000000000000000000000607b8401527f3c7465787420783d2232302220793d2233342220666f6e742d66616d696c793d60818401527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060a18401527f666f6e742d73697a653d2232327078223e00000000000000000000000000000060c184015251809360d28401906146ca565b0101661e17ba32bc3a1f60c91b838201527f3c7465787420783d2232302220793d2237322220666f6e742d66616d696c793d60be8201527f2227436f7572696572204e6577272c417269616c2c6d6f6e6f7370616365222060de8201527f666f6e742d73697a653d2232367078223e00000000000000000000000000000060fe8201526109868251809361010f84019061022051016146ca565b0101661e17ba32bc3a1f60c91b838201526109ad82518093605f84019061022051016146ca565b0101631e17b39f60e11b838201520301601b19810184520182614710565b6101008301526101208201526101206101605101516108ec610a3960046007602760586040516109fe6102205182614710565b5f815260b7610a0d6001615e04565b98601b6028610a1b8c615f0f565b610a2484615f87565b8082111561456457505b019a61072a8c615568565b61016083015261018082015260206101605101516108ec610a7a6004600760276058604051610a6b6102205182614710565b5f815260b7610a0d6002615e04565b8252602082015260286080610160510151604051610a9b6102205182614710565b5f81526108ec610ae56004600760276058610ab66003615e04565b9660b7610ac289615f0f565b610acb8b615f87565b8082111561455c5750995b601b8c8c019a61072a8c615568565b60a085015260c0840152602083015101016101208201510161018082015101603081016080830152602f19906103e8030160011c8061014083015261012082015101601081016101a083015261018082015101610220518101604083015260106102205191602084015101010160e0820152610b7461010082015161016083015183519060a085015192615034565b60608201526101006101208190526040516101a0819052610b959190614710565b60c76101a051527f3c726563742077696474683d223130302522206865696768743d223130302522610220516101a05101527f2066696c7465723d2275726c28234e6f69736529222f3e3c7265637420783d2260406101a05101527f37302220793d223730222077696474683d2238363022206865696768743d223860606101a05101527f3630222066696c6c3d2223666666222066696c6c2d6f7061636974793d222e3060806101a05101527f33222072783d223435222072793d22343522207374726f6b653d22236666662260a06101a05101527f207374726f6b652d6f7061636974793d222e3122207374726f6b652d7769647460c06101a05101527f683d2234222f3e0000000000000000000000000000000000000000000000000060e06101a05101526101605151610120610160510151906060830151610140525f610200526060610200526040516101e052610cf7610200516101e051614710565b60336101e051527f3c636972636c652069643d22476c6f772220723d22353030222066696c6c3d22610220516101e05101527f75726c282352616469616c476c6f7729222f3e0000000000000000000000000060406101e051015261014060405190610d638183614710565b61011c82527f3c66696c7465722069643d224e6f697365223e3c6665466c6f6f6420783d2230610220518301527f2220793d2230222077696474683d223130302522206865696768743d2231303060408301527f252220666c6f6f642d636f6c6f723d2268736c283233302c3231252c31312529610200518301527f2220666c6f6f642d6f7061636974793d22312220726573756c743d22666c6f6f60808301527f6446696c6c222f3e3c666554757262756c656e6365206261736546726571756560a08301527f6e63793d222e3422206e756d4f6374617665733d22332220726573756c743d2260c08301527f4e6f6973652220747970653d226672616374616c4e6f697365222f3e3c66654260e08301527f6c656e6420696e3d224e6f6973652220696e323d22666c6f6f6446696c6c2220610120518301527f6d6f64653d22736f66742d6c69676874222f3e3c2f66696c7465723e000000006101208301525f6101c0526103a06101c0526119426118bd6073606b60405196610eec6101c05189614710565b61037b88527f3c706174682069643d224c6f676f222066696c6c3d2223666666222066696c6c610220518901527f2d6f7061636974793d222e312220643d226d3133332e3535392c3132342e303360408901527f34632d2e3031332c322e3431322d312e3035392c342e3834382d322e3932332c610200518901527f362e3430322d322e3535382c312e3831392d352e3136382c332e3433392d372e60808901527f3838382c342e3939362d31342e34342c382e3236322d33312e3034372c31322e60a08901527f3536352d34372e3637342c31322e3536392d382e3835382e3033362d31372e3860c08901527f33382d312e3237322d32362e3332382d332e3636332d392e3830362d322e373660e08901527f362d31392e3038372d372e3131332d32372e3536322d31322e3737382d31332e610120518901527f3834322d382e3032352c392e3436382d32382e3630362c31362e3135332d33356101208901527f2e323635683063322e3033352d312e3833382c342e3235322d332e3534362c36868901527f2e3436332d352e323234683063362e3432392d352e3635352c31362e3231382d6101608901527f322e3833352c32302e3335382c342e31372c342e3134332c352e3035372c382e6101808901527f3831362c392e3634392c31332e39322c31332e373334682e30333763352e37336101a08901527f362c362e3436312c31352e3335372d322e3235332c392e33382d382e34382c306101c08901527f2c302d332e3531352d332e3531352d332e3531352d332e3531352d31312e34396101e08901527f2d31312e3437382d35322e3635362d35322e3636342d36342e3833372d36342e6102008901527f3833376c2e3034392d2e303337632d312e3732352d312e3630362d322e3731396102208901527f2d332e3834372d322e3735312d362e3230346830632d2e3034362d322e3337356102408901527f2c312e3036322d342e3538322c322e3732362d362e32323968306c2e3138352d6102608901527f2e3134386830632e3039392d2e3036322c2e3232322d2e3134382c2e33372d2e6102808901527f323539683063322e30362d312e3336322c332e3935312d322e3632312c362e306102a08901527f34342d332e3834324335372e3736332d332e3437332c39372e37362d322e33346102c08901527f312c3132382e3633372c31382e3333326331362e3637312c392e3934362d32366102e08901527f2e3334342c35342e3831332d33382e3635312c34302e3139392d362e3239392d6103008901527f362e3039362d31382e3036332d31372e3734332d31392e3636382d31382e38316103208901527f312d362e3031362d342e3034372d31332e3036312c342e3737362d372e3735326103408901527f2c392e3735316c36382e3235342c36382e33373163312e3732342c312e3630316103608901527f2c322e3731342c332e38342c322e3733382c362e3139325a222f3e00000000006103808901525f6101805260a06101805260405160a0526113516101805160a051614710565b607560a051527f3c706174682069643d22466c6f6174696e6754657874222066696c6c3d226e6f6102205160a05101527f6e652220643d224d313235203435683735307338302030203830203830763735604060a05101527f307330203830202d3830203830682d373530732d38302030202d3830202d38306102005160a05101527f762d3735307330202d3830203830202d3830222f3e0000000000000000000000608060a051015261193d6014602261140a615ad9565b9360a2604051957f3c72616469616c4772616469656e742069643d2252616469616c476c6f77223e610220518801527f3c73746f70206f66667365743d223025222073746f702d636f6c6f723d220000604088015261153f6025603589605e87519561022051890196611480818486018a6146ca565b83017f222073746f702d6f7061636974793d222e36222f3e0000000000000000000000838201528f7f3c73746f70206f66667365743d2231303025222073746f702d636f6c6f723d22908201526114e382518093609384019061022051016146ca565b01017f222073746f702d6f7061636974793d2230222f3e000000000000000000000000838201527f3c2f72616469616c4772616469656e743e00000000000000000000000000000060498201520301600581018a520188614710565b61165685602361154d615ad9565b6040519b8c917f3c6c696e6561724772616469656e742069643d2253616e64546f70222078313d610220518401527f223025222079313d223025223e0000000000000000000000000000000000000060408401527f3c73746f70206f66667365743d223025222073746f702d636f6c6f723d220000604d84015288516115d6818486018a6146ca565b83016211179f60e91b838201527f3c73746f70206f66667365743d2231303025222073746f702d636f6c6f723d22606e82015261161f82518093608e84019061022051016146ca565b01016211179f60e91b83820152701e17b634b732b0b923b930b234b2b73a1f60791b60268201520301600b1981018b520189614710565b6117e060726023611665615ad9565b6040519c8d917f3c6c696e6561724772616469656e742069643d2253616e64426f74746f6d2220610220518401527f78313d2231303025222079313d2231303025223e00000000000000000000000060408401527f3c73746f70206f66667365743d22313025222073746f702d636f6c6f723d220060548401526116f4815180928486019061022051016146ca565b82016211179f60e91b828201527f3c73746f70206f66667365743d2231303025222073746f702d636f6c6f723d22607682015288519061173882609683018a6146ca565b01016211179f60e91b838201527f3c616e696d617465206174747269627574654e616d653d22783122206475723d60268201527f2236732220726570656174436f756e743d22696e646566696e6974652220766160468201527f6c7565733d223330253b3630253b313230253b3630253b3330253b222f3e00006066820152701e17b634b732b0b923b930b234b2b73a1f60791b60848201520301605281018c52018a614710565b6117e8615ad9565b906040519a8b947f3c6c696e6561724772616469656e742069643d22486f7572676c617373537472610220518701527f6f6b6522206772616469656e745472616e73666f726d3d22726f74617465283960408701527f302922206772616469656e74556e6974733d227573657253706163654f6e5573610200518701527f65223e000000000000000000000000000000000000000000000000000000000060808701527f3c73746f70206f66667365743d22353025222073746f702d636f6c6f723d22006083870152518092858701906146ca565b83016211179f60e91b838201527f3c73746f70206f66667365743d22383025222073746f702d636f6c6f723d220060a58201526119068251809360c484019061022051016146ca565b01016211179f60e91b83820152701e17b634b732b0b923b930b234b2b73a1f60791b60258201520301600b19810187520185614710565b615034565b60e052611956611950614dc5565b85615832565b938415614541575b5060c061010081905260405191906119769083614710565b609082527f3c7061746820643d224d2035302c3336302061203330302c333030203020312c610220518301527f31203630302c302061203330302c333030203020312c31202d3630302c30222060408301527f66696c6c3d2223666666222066696c6c2d6f7061636974793d222e3032222073610200518301527f74726f6b653d2275726c2823486f7572676c6173735374726f6b65292220737460808301527f726f6b652d77696474683d2234222f3e00000000000000000000000000000000610180518301526102c060405160c052611a538160c051614710565b61029860c051527f3c7061746820643d226d3536362c3136312e323031762d35332e39323463302d6102205160c05101527f31392e3338322d32322e3531332d33372e3536332d36332e3339382d35312e31604060c05101527f39382d34302e3735362d31332e3539322d39342e3934362d32312e3037392d316102005160c05101527f35322e3538372d32312e303739732d3131312e3833382c372e3438372d313532608060c05101527f2e3630322c32312e303739632d34302e3839332c31332e3633362d36332e34316101805160c05101527f332c33312e3831362d36332e3431332c35312e3139387635332e39323463302c6101005160c05101527f31372e3138312c31372e3730342c33332e3432372c35302e3232332c34362e3360e060c05101527f3934763238342e383039632d33322e3531392c31322e39362d35302e3232332c6101205160c05101527f32392e3230362d35302e3232332c34362e3339347635332e39323463302c313961012060c05101527f2e3338322c32322e35322c33372e3536332c36332e3431332c35312e3139382c8260c05101527f34302e3736332c31332e3539322c39342e3935342c32312e3037392c3135322e61016060c05101527f3630322c32312e303739733131312e3833312d372e3438372c3135322e35383761018060c05101527f2d32312e3037396334302e3838362d31332e3633362c36332e3339382d33312e6101a060c05101527f3831362c36332e3339382d35312e313938762d35332e39323463302d31372e316101c060c05101527f39362d31372e3730342d33332e3433352d35302e3232332d34362e34303156326101e060c05101527f30372e3630336333322e3531392d31322e3936372c35302e3232332d32392e3261020060c05101527f30362c35302e3232332d34362e3430315a6d2d3334372e3436322c35372e373961022060c05101527f336c3133302e3935392c3133312e3032372d3133302e3935392c3133312e303161024060c05101527f33563231382e3939345a6d3236322e3932342e303232763236322e3031386c2d61026060c05101527f3133302e3933372d3133312e3030362c3133302e3933372d3133312e3031335a61028060c05101527f222066696c6c3d2223313631383232223e3c2f706174683e00000000000000006102a060c0510152855f1461432c57604051611dce6102205182614710565b5f8152955b156141d957604051611de76101e082614710565b6101b181527f3c7061746820643d226d3438312e34362c3438312e35347638312e3031632d32610220518201527f2e33352e37372d342e38322c312e35312d372e33392c322e32332d33302e332c60408201527f382e35342d37342e36352c31332e39322d3132342e30362c31332e39322d3533610200518201527f2e362c302d3130312e32342d362e33332d3133312e34372d31362e3136762d3860808201527f316c34362e332d34362e3331683137302e33336c34362e32392c34362e33315a610180518201527f222066696c6c3d2275726c282353616e64426f74746f6d29222f3e3c70617468610100518201527f20643d226d3433352e31372c3433352e323363302c312e31372d2e34362c322e60e08201527f33322d312e33332c332e34342d372e31312c392e30382d34312e39332c31352e610120518201527f39382d38332e38312c31352e3938732d37362e372d362e392d38332e38322d316101208201527f352e3938632d2e38372d312e31322d312e33332d322e32372d312e33332d332e838201527f3434762d2e30346c382e33342d382e33352e30312d2e30316331332e37322d366101608201527f2e35312c34322e39352d31312e30322c37362e382d31312e30327336322e39376101808201527f2c342e34392c37362e37322c31316c382e34322c382e34325a222066696c6c3d6101a08201527f2275726c282353616e64546f7029222f3e0000000000000000000000000000006101c0820152905b604051926120206107e085614710565b6107a7845261022080517f3c672066696c6c3d226e6f6e6522207374726f6b653d2275726c2823486f7572908601527f676c6173735374726f6b652922207374726f6b652d6c696e656361703d22726f60408087019190915261020080517f756e6422207374726f6b652d6d697465726c696d69743d22313022207374726f908801527f6b652d77696474683d2234223e3c7061746820643d226d3536352e3634312c31608088015261018080517f30372e323863302c392e3533372d352e35362c31382e3632392d31352e36373690890152610100517f2c32362e393733682d2e303233632d392e3230342c372e3539362d32322e3139908901527f342c31342e3536322d33382e3139372c32302e3539322d33392e3530342c313460e089015261012080517f2e3933362d39372e3332352c32342e3335352d3136312e3733332c32342e3335908a01527f352d39302e34382c302d3136372e3934382d31382e3538322d3139392e393533908901527f2d34342e393438682d2e303233632d31302e3131352d382e3334342d31352e36948801949094527f37362d31372e3433372d31352e3637362d32362e3937332c302d33392e3733356101608801527f2c39362e3535342d37312e3932312c3231352e3635322d37312e393231733231938701939093527f352e3632392c33322e3138352c3231352e3632392c37312e3932315a222f3e3c6101a08701527f7061746820643d226d3133342e33362c3136312e32303363302c33392e3733356101c0808801919091527f2c39362e3535342c37312e3932312c3231352e3635322c37312e3932317332316101e08801527f352e3632392d33322e3138362c3231352e3632392d37312e393231222f3e3c6c938701939093527f696e652078313d223133342e3336222079313d223136312e323033222078323d828701527f223133342e3336222079323d223130372e3238222f3e3c6c696e652078313d226102408701527f3536352e3634222079313d223136312e323033222078323d223536352e3634226102608701527f2079323d223130372e3238222f3e3c6c696e652078313d223138342e353834226102808701527f2079313d223230362e383233222078323d223138342e353835222079323d22356102a08701527f33372e353739222f3e3c6c696e652078313d223231382e313831222079313d22938601939093527f3231382e313138222078323d223231382e313831222079323d223536322e35336102e08601527f37222f3e3c6c696e652078313d223438312e383138222079313d223231382e316103008601527f3432222078323d223438312e383139222079323d223536322e343238222f3e3c6103208601527f6c696e652078313d223531352e343135222079313d223230372e3335322220786103408601527f323d223531352e343136222079323d223533372e353739222f3e3c70617468206103608601527f643d226d3138342e35382c3533372e353863302c352e34352c342e32372c313061038086015290517f2e36352c31322e30332c31352e3432682e303263352e35312c332e33392c3132908501527f2e37392c362e35352c32312e35352c392e34322c33302e32312c392e392c37386103c08501527f2e30322c31362e32382c3133312e38332c31362e32382c34392e34312c302c396103e08501527f332e37362d352e33382c3132342e30362d31332e39322c322e372d2e37362c356104008501527f2e32392d312e35342c372e37352d322e33352c382e37372d322e38372c31362e6104208501527f30352d362e30342c32312e35362d392e3433683063372e37362d342e37372c316104408501527f322e30342d392e39372c31322e30342d31352e3432222f3e3c7061746820643d6104608501527f226d3138342e3538322c3439322e363536632d33312e3335342c31322e3438356104808501527f2d35302e3232332c32382e35382d35302e3232332c34362e3134322c302c392e6104a08501527f3533362c352e3536342c31382e3632372c31352e3637372c32362e393639682e6104c08501527f30323263382e3530332c372e3030352c32302e3231332c31332e3436332c33346104e08501527f2e3532342c31392e3135392c392e3939392c332e3939312c32312e3236392c376105008501527f2e3630392c33332e3539372c31302e3738382c33362e34352c392e3430372c386105208501527f322e3138312c31352e3030322c3133312e3833352c31352e3030327339352e336105408501527f36332d352e3539352c3133312e3830372d31352e3030326331302e3834372d326105608501527f2e37392c32302e3836372d352e3932362c32392e3932342d392e3334392c312e6105808501527f3234342d2e3436372c322e3437332d2e3934322c332e3637332d312e3432342c6105a08501527f31342e3332362d352e3639362c32362e3033352d31322e3136312c33342e35326105c08501527f342d31392e313733682e3032326331302e3131342d382e3334322c31352e36376105e08501527f372d31372e3433332c31352e3637372d32362e3936392c302d31372e3536322d6106008501527f31382e3836392d33332e3636352d35302e3232332d34362e3135222f3e3c70616106208501527f746820643d226d3133342e33362c3539322e373263302c33392e3733352c39366106408501527f2e3535342c37312e3932312c3231352e3635322c37312e393231733231352e366106608501527f32392d33322e3138362c3231352e3632392d37312e393231222f3e3c6c696e656106808501527f2078313d223133342e3336222079313d223539322e3732222078323d223133346106a08501527f2e3336222079323d223533382e373937222f3e3c6c696e652078313d223536356106c08501527f2e3634222079313d223539322e3732222078323d223536352e3634222079323d6106e08501527f223533382e373937222f3e3c706f6c796c696e6520706f696e74733d223438316107008501527f2e383232203438312e393031203438312e373938203438312e383737203438316107208501527f2e373735203438312e383534203335302e303135203335302e303236203231386107408501527f2e313835203231382e313239222f3e3c706f6c796c696e6520706f696e74733d6107608501527f223231382e313835203438312e393031203231382e323331203438312e3835346107808501527f203335302e303135203335302e303236203438312e383232203231382e3135326107a08501527f222f3e3c2f673e000000000000000000000000000000000000000000000000006107c0850152905181517f3c672069643d22486f7572676c617373223e00000000000000000000000000009082015284519151909788959092916129ef9183916032890191016146ca565b840160c051519060328101826102205160c0510191612a0d926146ca565b016032018082518093610220510191612a25926146ca565b018082518093610220510191612a3a926146ca565b018082518093610220510191612a4f926146ca565b01631e17b39f60e11b815203601b1981018452600401612a6f9084614710565b60405160805261022051608051017f3c646566733e000000000000000000000000000000000000000000000000000090526101e0515160805160260181610220516101e0510191612abf926146ca565b60805101815191826026830191610220510191612adb926146ca565b016026018082518093610220510191612af3926146ca565b0160a051519080826102205160a0510191612b0d926146ca565b0160e051519080826102205160e0510191612b27926146ca565b018082518093610220510191612b3c926146ca565b01610140515190808261022051610140510191612b58926146ca565b017f3c2f646566733e000000000000000000000000000000000000000000000000008152608051900360181981016080515260070160805190612b9a91614710565b6101605160a00151906101605160c00151916101605160400151906101605160600151612bc78583615d58565b916040958651612bd78882614710565b600581526102205181017f2d31303025000000000000000000000000000000000000000000000000000000905287519485916102205183017f3c74657874506174682073746172744f66667365743d220000000000000000009052805190816037850191610220510191612c4a926146ca565b7f2220687265663d2223466c6f6174696e6754657874222066696c6c3d222366666037918401918201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201528151610220519092612d8e918491610120850191016146ca565b0160370160e981016a1e17ba32bc3a2830ba341f60a91b90520360e90160141981018552600b01612dbf9085614710565b612dc891615d58565b928551612dd58782614710565b60028152610220518101947f3025000000000000000000000000000000000000000000000000000000000000865287519586926102205184017f3c74657874506174682073746172744f66667365743d22000000000000000000905251908160378501612e41926146ca565b7f2220687265663d2223466c6f6174696e6754657874222066696c6c3d222366666037918401918201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201528151610220519092612f85918491610120850191016146ca565b0160370160e981016a1e17ba32bc3a2830ba341f60a91b90520360e90160141981018552600b01612fb69085614710565b612fc08282615dbf565b918651612fcd8882614710565b60048152610220518101937f2d35302500000000000000000000000000000000000000000000000000000000855288519485926102205184017f3c74657874506174682073746172744f66667365743d22000000000000000000905251908160378501613039926146ca565b7f2220687265663d2223466c6f6174696e6754657874222066696c6c3d222366666037918401918201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e000000000000000000610109820152815161022051909261317d918491610120850191016146ca565b0160370160e981016a1e17ba32bc3a2830ba341f60a91b90520360e90160141981018452600b016131ae9084614710565b6131b791615dbf565b9085516131c48782614710565b60038152610220518101927f3530250000000000000000000000000000000000000000000000000000000000845287519384926102205184017f3c74657874506174682073746172744f66667365743d22000000000000000000905251908160378501613230926146ca565b7f2220687265663d2223466c6f6174696e6754657874222066696c6c3d222366666037918401918201527f662220666f6e742d66616d696c793d2227436f7572696572204e6577272c417260578201527f69616c2c6d6f6e6f7370616365222066696c6c2d6f7061636974793d222e3822607782015271103337b73a16b9b4bd329e91191b383c111f60711b60978201527f3c616e696d6174652061646469746976653d2273756d2220617474726962757460a98201527f654e616d653d2273746172744f66667365742220626567696e3d22307322206460c98201527f75723d22353073222066726f6d3d2230252220726570656174436f756e743d2260e98201527f696e646566696e6974652220746f3d2231303025222f3e0000000000000000006101098201528151610220519092613374918491610120850191016146ca565b0160370160e981016a1e17ba32bc3a2830ba341f60a91b90520360e90160141981018352600b016133a59083614710565b85519384936102205185017f3c7465787420746578742d72656e646572696e673d226f7074696d697a65537090528785017f656564223e0000000000000000000000000000000000000000000000000000009052805190816045870191610220510191613411926146ca565b840181519182604583019161022051019161342b926146ca565b016045018082518093610220510191613443926146ca565b018082518093610220510191613458926146ca565b01661e17ba32bc3a1f60c91b8152036018198101825260070161347b9082614710565b610140820151916101a08101519060408101519060e001519361349d90615568565b916134a790615568565b906134b190615568565b936134bb90615568565b8551948592610220518401947f3c75736520687265663d2223476c6f77222066696c6c2d6f7061636974793d2286528885017f2e39222f3e0000000000000000000000000000000000000000000000000000009052604585017f3c75736520687265663d2223476c6f772220783d22313030302220793d2231309052606585017f3030222066696c6c2d6f7061636974793d222e39222f3e0000000000000000009052607c85017f3c75736520687265663d22234c6f676f2220783d223137302220793d223137309052609c85017f22207472616e73666f726d3d227363616c65282e3629222f3e3c757365206872905260bc85017f65663d2223486f7572676c6173732220783d223135302220793d223930222074905260dc85017f72616e73666f726d3d22726f746174652831302922207472616e73666f726d2d905260fc85017f6f726967696e3d2235303020353030222f3e0000000000000000000000000000905261010e85017f3c75736520687265663d222350726f67726573732220783d2200000000000000905280519081610127870191610220510191613662926146ca565b840161012781016a11103c9e911b9c9811179f60a91b905261013281017f3c75736520687265663d22235374617475732220783d220000000000000000009052815191826101498301916102205101916136bb926146ca565b0161012701602281016a11103c9e911b9c9811179f60a91b9052602d81017f3c75736520687265663d2223416d6f756e742220783d220000000000000000009052815191826044830191610220510191613714926146ca565b01602201602281016a11103c9e911b9c9811179f60a91b9052602d81017f3c75736520687265663d22234475726174696f6e2220783d2200000000000000905281519182604683019161022051019161376c926146ca565b01602201602481016a11103c9e911b9c9811179f60a91b90520360240160141981018452600b0161379d9084614710565b83519283926102205184017f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323090528584017f30302f737667222077696474683d223130303022206865696768743d2231303090526102005184017f30222076696577426f783d2230203020313030302031303030223e000000000090526101a05151607b850181610220516101a0510191613837926146ca565b84016080515190607b810182610220516080510191613855926146ca565b01607b01808251809361022051019161386d926146ca565b0191829151809361387d926146ca565b017f3c2f7376673e0000000000000000000000000000000000000000000000000000815203601919810182526006016138b69082614710565b610380526102e0518151610220517fb25645690000000000000000000000000000000000000000000000000000000090820190815260248035818401528252916001600160a01b03169061390b604482614710565b515a925f93928493fa61391c614793565b610340819052901580156103c0526141d15761022051818051810103126141bc5761022051015180151581036141bc575b15156102a052610260516102e05182517fb971302a00000000000000000000000000000000000000000000000000000000815260248035600483015261022051919283919082906001600160a01b03165afa9081156141c7575f9161417b575b50600360236139be613ad693614b9d565b938161012061024001518780519788947f5b7b2274726169745f74797065223a224173736574222c2276616c7565223a2261022051870152613a0b815180928589019061022051016146ca565b85017f227d2c7b2274726169745f74797065223a2253656e646572222c2276616c75658382015262111d1160e91b61020051820152613a5682518093606384019061022051016146ca565b01017f227d2c7b2274726169745f74797065223a22537461747573222c2276616c75658382015262111d1160e91b6043820152613a9f82518093604684019061022051016146ca565b01017f227d5d0000000000000000000000000000000000000000000000000000000000838201520301601c19810184520182614710565b6103005161026051610320516102405191939291613afc906001600160a01b0316614b9d565b613b07602435615568565b6102a051909190156140ef5761010051875190613b249082614710565b609b81527fe29aa0efb88f205741524e494e473a205472616e7366657272696e6720746865610220518201527f204e4654206d616b657320746865206e6577206f776e65722074686520726563888201527f697069656e74206f66207468652073747265616d2e205468652066756e647320610200518201527f617265206e6f74206175746f6d61746963616c6c792077697468647261776e2060808201527f666f72207468652070726576696f757320726563697069656e742e000000000061018051820152915b8751968794610220518601967f54686973204e465420726570726573656e74732061207061796d656e7420737488528a87017f7265616d20696e2061205361626c696572204c6f636b757020000000000000009052805190610220518101918060598a0190613c5c91856146ca565b7f20636f6e74726163742e20546865206f776e6572206f662074686973204e46546059918a01918201527f2063616e207769746864726177207468652073747265616d656420617373657460798201527f732c207768696368206172652064656e6f6d696e6174656420696e2000000000609982015284516102205186019691613cea8260b583018a6146ca565b01605901605c81017f2e5c6e5c6e2d2053747265616d2049443a200000000000000000000000000000905281519182606e830191610220510191613d2d926146ca565b01605c0190601282016302e3716960e51b905251918260168301613d50926146ca565b01601201600481016901020b2323932b9b99d160b51b905281519182600e830191610220510191613d80926146ca565b0160040190600a82016302e3716960e51b9052519182600e8301613da3926146ca565b01600a01600481016901020b2323932b9b99d160b51b905281519182600e830191610220510191613dd3926146ca565b01600401600a81017f5c6e5c6e00000000000000000000000000000000000000000000000000000000905281519182600e830191610220510191613e16926146ca565b01600a0103600401601f1981018452613e2f9084614710565b61030051613e3e602435615568565b855180916102205182019367029b0b13634b2b9160c51b8552805190816028850191610220510191613e6f926146ca565b8201602881017f2023000000000000000000000000000000000000000000000000000000000000905281519182602a830191610220510191613eb0926146ca565b0160280103600201601f1981018252613ec99082614710565b61038051613ed6906156c7565b9286519586956102205187017f7b2261747472696275746573223a000000000000000000000000000000000000905280519081602e890191610220510191613f1d926146ca565b860190602e82017f2c226465736372697074696f6e223a22000000000000000000000000000000009052519182603e8301613f57926146ca565b01602e0190601082017f222c2265787465726e616c5f75726c223a2268747470733a2f2f7361626c69659052603082017f722e636f6d222c226e616d65223a2200000000000000000000000000000000009052519182603f8301613fba926146ca565b01601001602f81017f222c22696d616765223a22646174613a696d6167652f7376672b786d6c3b62619052604f81017f736536342c0000000000000000000000000000000000000000000000000000009052815191826054830191610220510191614024926146ca565b01602f01602581017f227d000000000000000000000000000000000000000000000000000000000000905203602501601d19810182526002016140679082614710565b6102c0819052614076906156c7565b90805180926102205182017f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000905280519081603d8401916102205101916140bc926146ca565b810103603d01601f19810183526140d39083614710565b5180916102205182526102205182016140eb916146eb565b0390f35b86516140fc608082614710565b605b81527fe29d95494e464f3a2054686973204e4654206973206e6f6e2d7472616e736665610220518201527f7261626c652e2049742063616e6e6f7420626520736f6c64206f72207472616e888201527f7366657272656420746f20616e6f74686572206163636f756e742e00000000006102005182015291613bed565b9050610220513d61022051116141c0575b6141968183614710565b816102205191810103126141bc57516001600160a01b03811681036141bc5760036139ad565b5f80fd5b503d61418c565b83513d5f823e3d90fd5b50600161394d565b6040516141e861012082614710565b60f881527f3c7061746820643d226d3438312e34362c3530342e3130317635382e34343963610220518201527f2d322e33352e37372d342e38322c312e35312d372e33392c322e32332d33302e60408201527f332c382e35342d37342e36352c31332e39322d3132342e30362c31332e39322d610200518201527f35332e362c302d3130312e32342d362e33332d3133312e34372d31362e31367660808201527f2d35382e343339683236322e39325a222066696c6c3d2275726c282353616e64610180518201527f426f74746f6d29222f3e3c656c6c697073652063783d22333530222063793d22610100518201527f3530342e313031222072783d223133312e343632222072793d2232382e31303860e08201527f222066696c6c3d2275726c282353616e64546f7029222f3e00000000000000006101205182015290612010565b60405161433b6101c082614710565b61019981527f3c706f6c79676f6e20706f696e74733d22333530203335302e30323620343135610220518201527f2e3033203238342e39373820323835203238342e39373820333530203335302e60408201527f303236222066696c6c3d2275726c282353616e64426f74746f6d29222f3e3c70610200518201527f61746820643d226d3431362e3334312c3238312e39373563302c2e3931342d2e60808201527f3335342c312e3830392d312e3033352c322e36382d352e3534322c372e303736610180518201527f2d33322e3636312c31322e34352d36352e32382c31322e34352d33322e363234610100518201527f2c302d35392e3733382d352e3337342d36352e32382d31322e34352d2e36383160e08201527f2d2e3837322d312e3033352d312e3736372d312e3033352d322e36382c302d2e610120518201527f3931342e3335342d312e3830382c312e3033352d322e3637362c352e3534322d6101208201527f372e3037362c33322e3635362d31322e34352c36352e32382d31322e34352c33838201527f322e3631392c302c35392e3733382c352e3337342c36352e32382c31322e34356101608201527f2e3638312e3836372c312e3033352c312e3736322c312e3033352c322e3637366101808201527f5a222066696c6c3d2275726c282353616e64546f7029222f3e000000000000006101a082015295611dd3565b61455591945061454f614e00565b90615832565b925f61195e565b905099610ad6565b9050610a2e565b601b60d09a610721565b634e487b7160e01b5f52604160045260245ffd5b6145ab915060203d6020116145b1575b6145a38183614710565b81019061475a565b5f610519565b503d614599565b6040513d5f823e3d90fd5b6145dc915060203d6020116145b1576145a38183614710565b5f6104ba565b634e487b7160e01b5f52601260045260245ffd5b614618915060203d60201161461e575b6146108183614710565b810190614732565b5f61024e565b503d614606565b506020813d60201161465a575b8161463f60209383614710565b810103126141bc575160058110156141bc576101f5906101eb565b3d9150614632565b61467b915060203d60201161461e576146108183614710565b5f610191565b90506020813d6020116146c2575b8161469c60209383614710565b810103126141bc57516001600160a01b03811681036141bc576001600160a01b0361010f565b3d915061468f565b5f5b8381106146db5750505f910152565b81810151838201526020016146cc565b90602091614704815180928185528580860191016146ca565b601f01601f1916010190565b90601f8019910116810190811067ffffffffffffffff82111761457557604052565b908160209103126141bc57516fffffffffffffffffffffffffffffffff811681036141bc5790565b908160209103126141bc575164ffffffffff811681036141bc5790565b67ffffffffffffffff811161457557601f01601f191660200190565b3d156147bd573d906147a482614777565b916147b26040519384614710565b82523d5f602084013e565b606090565b6020818303126141bc5780519067ffffffffffffffff82116141bc570181601f820112156141bc5780516147f581614777565b926148036040519485614710565b818452602082840101116141bc5761482191602080850191016146ca565b90565b6001600160a01b0316604051906395d89b4160e01b82525f82600481845afa9182156145b8575f92614b79575b5060409161489483516148648582614710565b600a81527f5341422d4c4f434b555000000000000000000000000000000000000000000000602082015282615832565b156148d45750506148a781519182614710565b600e81527f5361626c696572204c6f636b7570000000000000000000000000000000000000602082015290565b61491383516148e38582614710565b600e81527f5341422d4c4f434b55502d4c494e000000000000000000000000000000000000602082015282615832565b8015614b34575b1561495a57505061492d81519182614710565b601581527f5361626c696572204c6f636b7570204c696e6561720000000000000000000000602082015290565b61499983516149698582614710565b600e81527f5341422d4c4f434b55502d44594e000000000000000000000000000000000000602082015282615832565b8015614aef575b156149e05750506149b381519182614710565b601681527f5361626c696572204c6f636b75702044796e616d696300000000000000000000602082015290565b614a1f83516149ef8582614710565b600e81527f5341422d4c4f434b55502d545241000000000000000000000000000000000000602082015282615832565b8015614aaa575b15614a66575050614a3981519182614710565b601781527f5361626c696572204c6f636b7570205472616e63686564000000000000000000602082015290565b614aa69083519384937f16ee429d0000000000000000000000000000000000000000000000000000000085526004850152602484015260448301906146eb565b0390fd5b50614aea8351614aba8582614710565b601181527f5341422d56322d4c4f434b55502d545241000000000000000000000000000000602082015282615832565b614a26565b50614b2f8351614aff8582614710565b601181527f5341422d56322d4c4f434b55502d44594e000000000000000000000000000000602082015282615832565b6149a0565b50614b748351614b448582614710565b601181527f5341422d56322d4c4f434b55502d4c494e000000000000000000000000000000602082015282615832565b61491a565b614b969192503d805f833e614b8e8183614710565b8101906147c2565b905f614851565b6001600160a01b03168060405191614bb6606084614710565b602a8352602083016040368237835115614c855760309053825160011015614c85576078602184015360295b60018111614c235750614bf3575090565b7fe22e27eb000000000000000000000000000000000000000000000000000000005f52600452601460245260445ffd5b90600f81166010811015614c85577f3031323334353637383961626364656600000000000000000000000000000000901a614c5e838661585f565b5360041c908015614c71575f1901614be2565b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f809160405160208101906395d89b4160e01b825260048152614cbd602482614710565b51915afa614cc9614793565b90158015614db9575b614d7d5780602080614ce9935183010191016147c2565b601e8151115f14614d305750604051614d03604082614710565b600b81527f4c6f6e672053796d626f6c000000000000000000000000000000000000000000602082015290565b614d3981615870565b15614d415790565b50604051614d50604082614710565b601281527f556e737570706f727465642053796d626f6c0000000000000000000000000000602082015290565b50604051614d8c604082614710565b600581527f4552433230000000000000000000000000000000000000000000000000000000602082015290565b50604081511115614cd2565b60405190614dd4604083614710565b600782527f536574746c6564000000000000000000000000000000000000000000000000006020830152565b60405190614e0f604083614710565b600882527f4465706c657465640000000000000000000000000000000000000000000000006020830152565b6005811015614f275760048103614e555750614821614e00565b60038103614e995750604051614e6c604082614710565b600881527f43616e63656c6564000000000000000000000000000000000000000000000000602082015290565b60018103614edd5750604051614eb0604082614710565b600981527f53747265616d696e670000000000000000000000000000000000000000000000602082015290565b600203614eec57614821614dc5565b604051614efa604082614710565b600781527f50656e64696e6700000000000000000000000000000000000000000000000000602082015290565b634e487b7160e01b5f52602160045260245ffd5b5f809160405160208101907f313ce56700000000000000000000000000000000000000000000000000000000825260048152614f78602482614710565b51915afa614f84614793565b9080614fb3575b15614fae576020818051810103126141bc576020015160ff811681036141bc5790565b505f90565b506020815114614f8b565b60405190614fcd604083614710565b600482527f2667743b000000000000000000000000000000000000000000000000000000006020830152565b60405190615008604083614710565b600482527f266c743b000000000000000000000000000000000000000000000000000000006020830152565b9061505f9493615090602061509f95615082828096816040519c8d8b83829d519485930191016146ca565b8901615073825180938580850191016146ca565b010191828151948592016146ca565b0191828151948592016146ca565b0103601f198101845283614710565b565b908115615376578061536657505b8060018110156151185750506150c3614ff9565b61482160026020604051846150e182965180928580860191016146ca565b81017f2031000000000000000000000000000000000000000000000000000000000000838201520301601d19810184520182614710565b66038d7ea4c680001115615308576040519060a0820182811067ffffffffffffffff821117614575576040526020916040516151548482614710565b5f8152815260409182516151688482614710565b600181527f4b00000000000000000000000000000000000000000000000000000000000000858201528483015282516151a18482614710565b600181527f4d00000000000000000000000000000000000000000000000000000000000000858201528383015282516151da8482614710565b600181527f420000000000000000000000000000000000000000000000000000000000000085820152606083015282516152148482614710565b600181527f54000000000000000000000000000000000000000000000000000000000000008582015260808301525f905f945b6103e88210156152ee5784519461525e8187614710565b600786527f2623383830353b000000000000000000000000000000000000000000000000008287015251945f5b600781106152db575050600160fd1b602786015250600884526152c2906152bc906152b7602887614710565b615568565b91615a13565b916005851015614c85576148219460051b015192615034565b818101830151878201840152820161528b565b9490915060016103e86064600a8504069304910194615247565b50615311614fbe565b614821600860206040518461532f82965180928580860191016146ca565b81017f203939392e393954000000000000000000000000000000000000000000000000838201520301601719810184520182614710565b600a0a9081156145e257046150af565b5050604051615386604082614710565b60018152600360fc1b602082015290565b620151809103048061540157506153ac614ff9565b61482160066020604051846153ca82965180928580860191016146ca565b81017f2031204461790000000000000000000000000000000000000000000000000000838201520301601919810184520182614710565b61270f81116154d8576001810361549457614821615456604051615426604082614710565b600481527f2044617900000000000000000000000000000000000000000000000000000000602082015292615568565b6020604051938261547086945180928580880191016146ca565b8301615484825180938580850191016146ca565b010103601f198101835282614710565b6148216154566040516154a8604082614710565b600581527f2044617973000000000000000000000000000000000000000000000000000000602082015292615568565b506154e1614fbe565b614821600a6020604051846154ff82965180928580860191016146ca565b81017f2039393939204461797300000000000000000000000000000000000000000000838201520301601519810184520182614710565b9061554082614777565b61554d6040519182614710565b828152809261555e601f1991614777565b0190602036910137565b805f917a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000082101561569f575b806d04ee2d6d415b85acef8100000000600a921015615684575b662386f26fc10000811015615670575b6305f5e10081101561565f575b612710811015615650575b6064811015615642575b1015615637575b600a60216155f260018501615536565b938401015b5f1901917f30313233343536373839616263646566000000000000000000000000000000008282061a835304801561563257600a90916155f7565b505090565b6001909101906155e2565b6064600291049301926155db565b612710600491049301926155d1565b6305f5e100600891049301926155c6565b662386f26fc10000601091049301926155b9565b6d04ee2d6d415b85acef8100000000602091049301926155a9565b50604091507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000810461558f565b9081511561581c57604051916156de606084614710565b604083527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208401527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040840152805160028101809111614c7157600390047f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103614c71576157749060021b615536565b90602082019080815182019560208701908151925f83525b8881106157ce57505060039394959650525106806001146157bc576002146157b2575090565b603d905f19015390565b50603d90815f19820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c168701015160028501531684010151600382015301949761578c565b905060405161582c602082614710565b5f815290565b9081518151908181149384615849575b5050505090565b602092939450820120920120145f808080615842565b908151811015614c85570160200190565b8051905f5b82811061588457505050600190565b7fff000000000000000000000000000000000000000000000000000000000000006158af828461585f565b5116600160fd1b811490600360fc1b811015806159e9575b7f410000000000000000000000000000000000000000000000000000000000000082101590816159be575b7f61000000000000000000000000000000000000000000000000000000000000008310159283615993575b8415615969575b508315615961575b508215615959575b508115615951575b501561594a57600101615875565b5050505f90565b90505f61593c565b91505f615934565b92505f61592c565b7f2d000000000000000000000000000000000000000000000000000000000000001493505f615924565b7f7a00000000000000000000000000000000000000000000000000000000000000811115935061591d565b7f5a0000000000000000000000000000000000000000000000000000000000000083111591506158f2565b507f39000000000000000000000000000000000000000000000000000000000000008111156158c7565b80615a27575060405161582c602082614710565b600a811015615a8d57615a3990615568565b614821602260405180937f2e300000000000000000000000000000000000000000000000000000000000006020830152615a7c81518092602086860191016146ca565b81010301601f198101835282614710565b615a9690615568565b614821602160405180937f2e000000000000000000000000000000000000000000000000000000000000006020830152615a7c81518092602086860191016146ca565b60405190615ae8604083614710565b601082527f68736c283233302c3231252c31312529000000000000000000000000000000006020830152565b8015615d4857615b22615ad9565b9061271003906127108211614c7157602e6061916050615b4461482195615568565b60576040519788947f3c672066696c6c3d226e6f6e65223e000000000000000000000000000000000060208701527f3c636972636c652063783d22313636222063793d2235302220723d2232322220602f8701527f7374726f6b653d22000000000000000000000000000000000000000000000000604f870152615bd1815180926020868a0191016146ca565b85017f22207374726f6b652d77696474683d223130222f3e0000000000000000000000838201527f3c636972636c652063783d22313636222063793d2235302220706174684c656e606c8201527f6774683d2231303030302220723d22323222207374726f6b653d220000000000608c820152615c5882518093602060a7850191016146ca565b01017f22207374726f6b652d6461736861727261793d22313030303022207374726f6b838201527f652d646173686f66667365743d220000000000000000000000000000000000006070820152615cb9825180936020607e850191016146ca565b01017f22207374726f6b652d6c696e656361703d22726f756e6422207374726f6b652d838201527f77696474683d223522207472616e73666f726d3d22726f74617465282d393029604e8201527f22207472616e73666f726d2d6f726967696e3d22313636203530222f3e000000606e820152631e17b39f60e11b608b82015203016041810184520182614710565b505060405161582c602082614710565b600d61509f9193929360206040519582615d7b88945180928580880191016146ca565b830164010714051160dd1b8382015267029b0b13634b2b9160c51b6025820152615dae8251809385602d850191016146ca565b01010301601f198101845283614710565b600561509f9193929360206040519582615de288945180928580880191016146ca565b830164010714051160dd1b83820152615dae82518093856025850191016146ca565b6004811015614f275780615e4e5750604051615e21604082614710565b600881527f50726f6772657373000000000000000000000000000000000000000000000000602082015290565b60018103615e925750604051615e65604082614710565b600681527f5374617475730000000000000000000000000000000000000000000000000000602082015290565b600203615ed457604051615ea7604082614710565b600681527f416d6f756e740000000000000000000000000000000000000000000000000000602082015290565b604051615ee2604082614710565b600881527f4475726174696f6e000000000000000000000000000000000000000000000000602082015290565b5f908051801561594a5790600d915f925f925b828410615f355750505050600d02900390565b90919294603b60f81b7fff00000000000000000000000000000000000000000000000000000000000000615f69888561585f565b511614615f7f575b820194600101929190615f22565b859450615f71565b5f908051801561594a57906010915f925f925b828410615fad575050505060041b900390565b90919294603b60f81b7fff00000000000000000000000000000000000000000000000000000000000000615fe1888561585f565b511614615ff7575b820194600101929190615f9a565b859450615fe956fea164736f6c634300081a000a"; uint256 public constant MAX_COUNT = 500; /*////////////////////////////////////////////////////////////////////////// - CORE + FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Deploys {SablierBatchLockup} from precompiled bytecode. @@ -42,16 +39,6 @@ contract Precompiles { require(address(batchLockup) != address(0), "Lockup Precompiles: deployment failed for BatchLockup contract"); } - /// @notice Deploys all Core contracts. - function deployCore(address initialAdmin) - public - returns (ILockupNFTDescriptor nftDescriptor, ISablierLockup lockup, ISablierBatchLockup batchLockup) - { - nftDescriptor = deployNFTDescriptor(); - lockup = deployLockup(initialAdmin); - batchLockup = deployBatchLockup(); - } - /// @notice Deploys {SablierLockup} from precompiled bytecode, passing a default value for the `maxCount` parameter. /// @dev Notes: /// - A default value is passed for `maxCount`. @@ -106,42 +93,13 @@ contract Precompiles { ); } - /*////////////////////////////////////////////////////////////////////////// - PERIPHERY - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Deploys {SablierMerkleFactory} from precompiled bytecode. - function deployMerkleFactory(address initialAdmin) public returns (ISablierMerkleFactory factory) { - bytes memory creationBytecode = bytes.concat(BYTECODE_MERKLE_FACTORY, abi.encode(initialAdmin)); - assembly { - factory := create(0, add(creationBytecode, 0x20), mload(creationBytecode)) - } - require(address(factory) != address(0), "Lockup Precompiles: deployment failed for MerkleFactory contract"); - } - - /*////////////////////////////////////////////////////////////////////////// - PROTOCOL - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Deploys the entire Lockup Protocol from precompiled bytecode. - /// - /// 1. {LockupNFTDescriptor} - /// 2. {SablierLockup} - /// 5. {SablierBatchLockup} - /// 6. {SablierMerkleFactory} + /// @notice Deploys all contracts. function deployProtocol(address initialAdmin) public - returns ( - ILockupNFTDescriptor nftDescriptor, - ISablierLockup lockup, - ISablierBatchLockup batchLockup, - ISablierMerkleFactory merkleFactory - ) + returns (ILockupNFTDescriptor nftDescriptor, ISablierLockup lockup, ISablierBatchLockup batchLockup) { - // Deploy Core. - (nftDescriptor, lockup, batchLockup) = deployCore(initialAdmin); - - // Deploy Periphery. - merkleFactory = deployMerkleFactory(initialAdmin); + nftDescriptor = deployNFTDescriptor(); + lockup = deployLockup(initialAdmin); + batchLockup = deployBatchLockup(); } } diff --git a/script/core/DeployBatchLockup.t.sol b/script/DeployBatchLockup.t.sol similarity index 71% rename from script/core/DeployBatchLockup.t.sol rename to script/DeployBatchLockup.t.sol index 15ffc50f6..7ba8494cb 100644 --- a/script/core/DeployBatchLockup.t.sol +++ b/script/DeployBatchLockup.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { SablierBatchLockup } from "../../src/core/SablierBatchLockup.sol"; +import { SablierBatchLockup } from "../src/SablierBatchLockup.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; contract DeployBatchLockup is BaseScript { /// @dev Deploy via Forge. diff --git a/script/core/DeployDeterministicBatchLockup.t.sol b/script/DeployDeterministicBatchLockup.t.sol similarity index 73% rename from script/core/DeployDeterministicBatchLockup.t.sol rename to script/DeployDeterministicBatchLockup.t.sol index a045b2da4..2224f11bb 100644 --- a/script/core/DeployDeterministicBatchLockup.t.sol +++ b/script/DeployDeterministicBatchLockup.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { SablierBatchLockup } from "../../src/core/SablierBatchLockup.sol"; +import { SablierBatchLockup } from "../src/SablierBatchLockup.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; contract DeployDeterministicBatchLockup is BaseScript { /// @dev Deploy via Forge. diff --git a/script/core/DeployDeterministicLockup.s.sol b/script/DeployDeterministicLockup.s.sol similarity index 74% rename from script/core/DeployDeterministicLockup.s.sol rename to script/DeployDeterministicLockup.s.sol index cf9058486..dd5d2a62c 100644 --- a/script/core/DeployDeterministicLockup.s.sol +++ b/script/DeployDeterministicLockup.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { ILockupNFTDescriptor } from "../../src/core/interfaces/ILockupNFTDescriptor.sol"; -import { SablierLockup } from "../../src/core/SablierLockup.sol"; -import { BaseScript } from "../Base.s.sol"; +import { ILockupNFTDescriptor } from "../src/interfaces/ILockupNFTDescriptor.sol"; +import { SablierLockup } from "../src/SablierLockup.sol"; +import { BaseScript } from "./Base.s.sol"; /// @notice Deploys {SablierLockup} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. diff --git a/script/core/DeployDeterministicNFTDescriptor.s.sol b/script/DeployDeterministicNFTDescriptor.s.sol similarity index 78% rename from script/core/DeployDeterministicNFTDescriptor.s.sol rename to script/DeployDeterministicNFTDescriptor.s.sol index 74e3855b9..18ef5c04c 100644 --- a/script/core/DeployDeterministicNFTDescriptor.s.sol +++ b/script/DeployDeterministicNFTDescriptor.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { LockupNFTDescriptor } from "../../src/core/LockupNFTDescriptor.sol"; +import { LockupNFTDescriptor } from "../src/LockupNFTDescriptor.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; /// @dev Deploys {LockupNFTDescriptor} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. diff --git a/script/DeployDeterministicProtocol.s.sol b/script/DeployDeterministicProtocol.s.sol new file mode 100644 index 000000000..cfe6189a4 --- /dev/null +++ b/script/DeployDeterministicProtocol.s.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.8.22 <0.9.0; + +import { LockupNFTDescriptor } from "../src/LockupNFTDescriptor.sol"; +import { SablierBatchLockup } from "../src/SablierBatchLockup.sol"; +import { SablierLockup } from "../src/SablierLockup.sol"; + +import { DeploymentLogger } from "./DeploymentLogger.s.sol"; + +/// @notice Deploys the Lockup Protocol at deterministic addresses across chains. +contract DeployDeterministicProtocol is DeploymentLogger("deterministic") { + /// @dev Deploys the protocol with the admin set in `adminMap`. + function run() + public + virtual + broadcast + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) + { + address initialAdmin = adminMap[block.chainid]; + + (nftDescriptor, lockup, batchLockup) = _run(initialAdmin); + } + + /// @dev Deploys the protocol with the given `initialAdmin`. + function run(address initialAdmin) + internal + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) + { + (nftDescriptor, lockup, batchLockup) = _run(initialAdmin); + } + + /// @dev Common logic for the run functions. + function _run(address initialAdmin) + internal + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) + { + batchLockup = new SablierBatchLockup{ salt: SALT }(); + nftDescriptor = new LockupNFTDescriptor{ salt: SALT }(); + lockup = new SablierLockup{ salt: SALT }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + + appendToFileDeployedAddresses(address(lockup), address(nftDescriptor), address(batchLockup)); + } +} diff --git a/script/core/DeployLockup.s.sol b/script/DeployLockup.s.sol similarity index 69% rename from script/core/DeployLockup.s.sol rename to script/DeployLockup.s.sol index bb45a3ed5..e5d4fa3ca 100644 --- a/script/core/DeployLockup.s.sol +++ b/script/DeployLockup.s.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { ILockupNFTDescriptor } from "../../src/core/interfaces/ILockupNFTDescriptor.sol"; -import { SablierLockup } from "../../src/core/SablierLockup.sol"; +import { ILockupNFTDescriptor } from "../src/interfaces/ILockupNFTDescriptor.sol"; +import { SablierLockup } from "../src/SablierLockup.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; /// @notice Deploys {SablierLockup} contract. contract DeployLockup is BaseScript { diff --git a/script/core/DeployNFTDescriptor.s.sol b/script/DeployNFTDescriptor.s.sol similarity index 72% rename from script/core/DeployNFTDescriptor.s.sol rename to script/DeployNFTDescriptor.s.sol index 709c268a4..2b504f02f 100644 --- a/script/core/DeployNFTDescriptor.s.sol +++ b/script/DeployNFTDescriptor.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { LockupNFTDescriptor } from "../../src/core/LockupNFTDescriptor.sol"; +import { LockupNFTDescriptor } from "../src/LockupNFTDescriptor.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; /// @notice Deploys {LockupNFTDescriptor} contract. contract DeployNFTDescriptor is BaseScript { diff --git a/script/DeployProtocol.s.sol b/script/DeployProtocol.s.sol new file mode 100644 index 000000000..1eec342cf --- /dev/null +++ b/script/DeployProtocol.s.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.8.22 <0.9.0; + +import { LockupNFTDescriptor } from "../src/LockupNFTDescriptor.sol"; +import { SablierBatchLockup } from "../src/SablierBatchLockup.sol"; +import { SablierLockup } from "../src/SablierLockup.sol"; + +import { DeploymentLogger } from "./DeploymentLogger.s.sol"; + +/// @notice Deploys the Lockup Protocol. +contract DeployProtocol is DeploymentLogger("non_deterministic") { + /// @dev Deploys the protocol with the admin set in `adminMap`. + function run() + public + virtual + broadcast + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) + { + address initialAdmin = adminMap[block.chainid]; + + (nftDescriptor, lockup, batchLockup) = _run(initialAdmin); + } + + /// @dev Deploys the protocol with the given `initialAdmin`. + function run(address initialAdmin) + internal + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) + { + (nftDescriptor, lockup, batchLockup) = _run(initialAdmin); + } + + /// @dev Common logic for the run functions. + function _run(address initialAdmin) + internal + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) + { + batchLockup = new SablierBatchLockup(); + nftDescriptor = new LockupNFTDescriptor(); + lockup = new SablierLockup(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + + appendToFileDeployedAddresses(address(lockup), address(nftDescriptor), address(batchLockup)); + } +} diff --git a/script/protocol/DeploymentLogger.s.sol b/script/DeploymentLogger.s.sol similarity index 82% rename from script/protocol/DeploymentLogger.s.sol rename to script/DeploymentLogger.s.sol index d2baa29b0..b75b4ac79 100644 --- a/script/protocol/DeploymentLogger.s.sol +++ b/script/DeploymentLogger.s.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; /// @dev This contract appends to the `script` directory a markdown file with the deployed addresses in the format used /// in the docs: https://docs.sablier.com/contracts/v2/deployments. @@ -53,59 +53,29 @@ abstract contract DeploymentLogger is BaseScript { } // Set the deployment file path. - deploymentFile = string.concat("script/protocol/", deterministicOrNot, ".md"); + deploymentFile = string.concat("script/", deterministicOrNot, ".md"); // Append the chain name to the deployment file. _appendToFile(string.concat("## ", chainNameMap[block.chainid], "\n")); } /// @dev Function to append the deployed addresses to the deployment file. - function appendToFileDeployedAddresses( - address lockup, - address nftDescriptor, - address batchLockup, - address merkleFactory - ) - internal - { - string memory coreTitle = " ### Core\n"; - _appendToFile(coreTitle); - + function appendToFileDeployedAddresses(address lockup, address nftDescriptor, address batchLockup) internal { string memory firstTwoLines = "| Contract | Address | Deployment |\n | :------- | :------ | :----------|"; _appendToFile(firstTwoLines); - string memory batchLockupLine = _getContractLine({ - contractName: "SablierBatchLockup", - contractAddress: batchLockup.toHexString(), - coreOrPeriphery: "core" - }); + string memory batchLockupLine = + _getContractLine({ contractName: "SablierBatchLockup", contractAddress: batchLockup.toHexString() }); _appendToFile(batchLockupLine); - string memory lockupLine = _getContractLine({ - contractName: "SablierLockup", - contractAddress: lockup.toHexString(), - coreOrPeriphery: "core" - }); + string memory lockupLine = + _getContractLine({ contractName: "SablierLockup", contractAddress: lockup.toHexString() }); _appendToFile(lockupLine); - string memory nftDescriptorLine = _getContractLine({ - contractName: "SablierNFTDescriptor", - contractAddress: nftDescriptor.toHexString(), - coreOrPeriphery: "core" - }); + string memory nftDescriptorLine = + _getContractLine({ contractName: "SablierNFTDescriptor", contractAddress: nftDescriptor.toHexString() }); _appendToFile(nftDescriptorLine); - string memory peripheryTitle = "\n ### Periphery\n\n"; - _appendToFile(peripheryTitle); - _appendToFile(firstTwoLines); - - string memory merkleFactoryLine = _getContractLine({ - contractName: "MerkleFactory", - contractAddress: merkleFactory.toHexString(), - coreOrPeriphery: "periphery" - }); - _appendToFile(merkleFactoryLine); - _appendToFile("\n"); } @@ -190,8 +160,7 @@ abstract contract DeploymentLogger is BaseScript { /// @dev Returns a string for a single contract line formatted according to the docs. function _getContractLine( string memory contractName, - string memory contractAddress, - string memory coreOrPeriphery + string memory contractAddress ) private view @@ -208,13 +177,9 @@ abstract contract DeploymentLogger is BaseScript { "](", explorerMap[block.chainid], contractAddress, - ") | [", - coreOrPeriphery, - "-", + ") | [ Lockup-", version, - "](https://github.com/sablier-labs/v2-deployments/tree/main/", - coreOrPeriphery, - "/", + "](https://github.com/sablier-labs/v2-deployments/tree/main/lockup/", version, ") |" ); diff --git a/script/core/GenerateSVG.s.sol b/script/GenerateSVG.s.sol similarity index 86% rename from script/core/GenerateSVG.s.sol rename to script/GenerateSVG.s.sol index 49b32c8f9..47b7d4964 100644 --- a/script/core/GenerateSVG.s.sol +++ b/script/GenerateSVG.s.sol @@ -2,10 +2,10 @@ pragma solidity >=0.8.22 <0.9.0; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { NFTSVG } from "./../../src/core/libraries/NFTSVG.sol"; -import { SVGElements } from "./../../src/core/libraries/SVGElements.sol"; -import { LockupNFTDescriptor } from "./../../src/core/LockupNFTDescriptor.sol"; -import { BaseScript } from "./../Base.s.sol"; +import { NFTSVG } from "./../src/libraries/NFTSVG.sol"; +import { SVGElements } from "./../src/libraries/SVGElements.sol"; +import { LockupNFTDescriptor } from "./../src/LockupNFTDescriptor.sol"; +import { BaseScript } from "././Base.s.sol"; /// @notice Generates an NFT SVG using the user-provided parameters. contract GenerateSVG is BaseScript, LockupNFTDescriptor { diff --git a/script/core/Init.s.sol b/script/Init.s.sol similarity index 96% rename from script/core/Init.s.sol rename to script/Init.s.sol index ee7363358..a60b2ae4f 100644 --- a/script/core/Init.s.sol +++ b/script/Init.s.sol @@ -6,10 +6,10 @@ import { ud2x18 } from "@prb/math/src/UD2x18.sol"; import { ud60x18 } from "@prb/math/src/UD60x18.sol"; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockup } from "../../src/core/interfaces/ISablierLockup.sol"; -import { Broker, Lockup, LockupDynamic, LockupLinear } from "../../src/core/types/DataTypes.sol"; +import { ISablierLockup } from "../src/interfaces/ISablierLockup.sol"; +import { Broker, Lockup, LockupDynamic, LockupLinear } from "../src/types/DataTypes.sol"; -import { BaseScript } from "../Base.s.sol"; +import { BaseScript } from "./Base.s.sol"; interface IERC20Mint { function mint(address beneficiary, uint256 value) external; diff --git a/script/core/DeployCore.s.sol b/script/core/DeployCore.s.sol deleted file mode 100644 index 2795476bf..000000000 --- a/script/core/DeployCore.s.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { LockupNFTDescriptor } from "../../src/core/LockupNFTDescriptor.sol"; -import { SablierBatchLockup } from "./../../src/core/SablierBatchLockup.sol"; -import { SablierLockup } from "../../src/core/SablierLockup.sol"; - -import { BaseScript } from "../Base.s.sol"; - -/// @notice Deploys all Core contracts. -contract DeployCore is BaseScript { - function run(address initialAdmin) - public - virtual - broadcast - returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) - { - nftDescriptor = new LockupNFTDescriptor(); - lockup = new SablierLockup(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); - batchLockup = new SablierBatchLockup(); - } -} diff --git a/script/core/DeployDeterministicCore.s.sol b/script/core/DeployDeterministicCore.s.sol deleted file mode 100644 index 4eb7c981e..000000000 --- a/script/core/DeployDeterministicCore.s.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { LockupNFTDescriptor } from "../../src/core/LockupNFTDescriptor.sol"; -import { SablierBatchLockup } from "./../../src/core/SablierBatchLockup.sol"; -import { SablierLockup } from "../../src/core/SablierLockup.sol"; -import { BaseScript } from "../Base.s.sol"; - -/// @notice Deploys all Core contracts at deterministic addresses across chains. -/// @dev Reverts if any contract has already been deployed. -contract DeployDeterministicCore is BaseScript { - function run(address initialAdmin) - public - virtual - broadcast - returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) - { - nftDescriptor = new LockupNFTDescriptor{ salt: SALT }(); - lockup = new SablierLockup{ salt: SALT }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); - batchLockup = new SablierBatchLockup{ salt: SALT }(); - } -} diff --git a/script/periphery/CreateMerkleInstant.s.sol b/script/periphery/CreateMerkleInstant.s.sol deleted file mode 100644 index b4ca6f39e..000000000 --- a/script/periphery/CreateMerkleInstant.s.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { ISablierMerkleFactory } from "../../src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleInstant } from "../../src/periphery/interfaces/ISablierMerkleInstant.sol"; -import { MerkleBase } from "../../src/periphery/types/DataTypes.sol"; - -import { BaseScript } from "../Base.s.sol"; - -contract CreateMerkleInstant is BaseScript { - /// @dev Deploy via Forge. - function run() public virtual broadcast returns (ISablierMerkleInstant merkleInstant) { - // Prepare the constructor parameters. - // TODO: Update address once deployed. - ISablierMerkleFactory merkleFactory = ISablierMerkleFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc); - - MerkleBase.ConstructorParams memory baseParams; - baseParams.asset = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); - baseParams.expiration = uint40(block.timestamp + 30 days); - baseParams.initialAdmin = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844; - baseParams.ipfsCID = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"; - baseParams.merkleRoot = 0x0000000000000000000000000000000000000000000000000000000000000000; - baseParams.name = "The Boys Instant"; - - uint256 campaignTotalAmount = 10_000e18; - uint256 recipientCount = 100; - - // Deploy MerkleInstant contract. - merkleInstant = merkleFactory.createMerkleInstant(baseParams, campaignTotalAmount, recipientCount); - } -} diff --git a/script/periphery/CreateMerkleLL.s.sol b/script/periphery/CreateMerkleLL.s.sol deleted file mode 100644 index 690e6ba9e..000000000 --- a/script/periphery/CreateMerkleLL.s.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { ISablierLockup } from "../../src/core/interfaces/ISablierLockup.sol"; -import { ISablierMerkleFactory } from "../../src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleLL } from "../../src/periphery/interfaces/ISablierMerkleLL.sol"; -import { MerkleBase, MerkleLL } from "../../src/periphery/types/DataTypes.sol"; - -import { BaseScript } from "../Base.s.sol"; - -contract CreateMerkleLL is BaseScript { - /// @dev Deploy via Forge. - function run() public virtual broadcast returns (ISablierMerkleLL merkleLL) { - // Prepare the constructor parameters. - // TODO: Update address once deployed. - ISablierMerkleFactory merkleFactory = ISablierMerkleFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc); - - MerkleBase.ConstructorParams memory baseParams; - baseParams.asset = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); - baseParams.expiration = uint40(block.timestamp + 30 days); - baseParams.initialAdmin = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844; - baseParams.ipfsCID = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"; - baseParams.merkleRoot = 0x0000000000000000000000000000000000000000000000000000000000000000; - baseParams.name = "The Boys LL"; - - // Deploy MerkleLL contract. - // TODO: Update address once deployed. - merkleLL = merkleFactory.createMerkleLL({ - baseParams: baseParams, - lockup: ISablierLockup(0x3962f6585946823440d274aD7C719B02b49DE51E), - cancelable: true, - transferable: true, - schedule: MerkleLL.Schedule({ - startTime: 0, // i.e. block.timestamp - startAmount: 10e18, - cliffDuration: 30 days, - cliffAmount: 10e18, - totalDuration: 90 days - }), - aggregateAmount: 10_000e18, - recipientCount: 100 - }); - } -} diff --git a/script/periphery/CreateMerkleLT.s.sol b/script/periphery/CreateMerkleLT.s.sol deleted file mode 100644 index 13f941885..000000000 --- a/script/periphery/CreateMerkleLT.s.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { UD2x18 } from "@prb/math/src/UD2x18.sol"; - -import { ISablierLockup } from "../../src/core/interfaces/ISablierLockup.sol"; -import { ISablierMerkleFactory } from "../../src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleLT } from "../../src/periphery/interfaces/ISablierMerkleLT.sol"; -import { MerkleBase, MerkleLT } from "../../src/periphery/types/DataTypes.sol"; - -import { BaseScript } from "../Base.s.sol"; - -contract CreateMerkleLT is BaseScript { - /// @dev Deploy via Forge. - function run() public virtual broadcast returns (ISablierMerkleLT merkleLT) { - // Prepare the constructor parameters. - // TODO: Update address once deployed. - ISablierMerkleFactory merkleFactory = ISablierMerkleFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc); - - MerkleBase.ConstructorParams memory baseParams; - baseParams.asset = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); - baseParams.expiration = uint40(block.timestamp + 30 days); - baseParams.initialAdmin = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844; - baseParams.ipfsCID = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"; - baseParams.merkleRoot = 0x0000000000000000000000000000000000000000000000000000000000000000; - baseParams.name = "The Boys LT"; - - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = new MerkleLT.TrancheWithPercentage[](2); - tranchesWithPercentages[0] = - MerkleLT.TrancheWithPercentage({ unlockPercentage: UD2x18.wrap(50), duration: 3600 }); - tranchesWithPercentages[1] = - MerkleLT.TrancheWithPercentage({ unlockPercentage: UD2x18.wrap(50), duration: 7200 }); - - // Deploy MerkleLT contract. - // TODO: Update address once deployed. - merkleLT = merkleFactory.createMerkleLT({ - baseParams: baseParams, - lockup: ISablierLockup(0xf86B359035208e4529686A1825F2D5BeE38c28A8), - cancelable: true, - transferable: true, - streamStartTime: 0, // i.e. block.timestamp - tranchesWithPercentages: tranchesWithPercentages, - aggregateAmount: 10_000e18, - recipientCount: 100 - }); - } -} diff --git a/script/periphery/DeployMerkleFactory.s.sol b/script/periphery/DeployMerkleFactory.s.sol deleted file mode 100644 index decfbf0cb..000000000 --- a/script/periphery/DeployMerkleFactory.s.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { SablierMerkleFactory } from "../../src/periphery/SablierMerkleFactory.sol"; - -import { BaseScript } from "../Base.s.sol"; - -contract DeployMerkleFactory is BaseScript { - /// @dev Deploy via Forge. - function run(address initialAdmin) public virtual broadcast returns (SablierMerkleFactory merkleFactory) { - merkleFactory = new SablierMerkleFactory(initialAdmin); - } -} diff --git a/script/protocol/DeployDeterministicProtocol.s.sol b/script/protocol/DeployDeterministicProtocol.s.sol deleted file mode 100644 index 2ce94952b..000000000 --- a/script/protocol/DeployDeterministicProtocol.s.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { LockupNFTDescriptor } from "./../../src/core/LockupNFTDescriptor.sol"; -import { SablierBatchLockup } from "./../../src/core/SablierBatchLockup.sol"; -import { SablierLockup } from "./../../src/core/SablierLockup.sol"; -import { SablierMerkleFactory } from "./../../src/periphery/SablierMerkleFactory.sol"; -import { DeploymentLogger } from "./DeploymentLogger.s.sol"; - -/// @notice Deploys the Lockup Protocol at deterministic addresses across chains. -contract DeployDeterministicProtocol is DeploymentLogger("deterministic") { - /// @dev Deploys the protocol with the admin set in `adminMap`. - function run() - public - virtual - broadcast - returns ( - LockupNFTDescriptor nftDescriptor, - SablierLockup lockup, - SablierBatchLockup batchLockup, - SablierMerkleFactory merkleLockupFactory - ) - { - address initialAdmin = adminMap[block.chainid]; - - (nftDescriptor, lockup, batchLockup, merkleLockupFactory) = _run(initialAdmin); - } - - /// @dev Deploys the protocol with the given `initialAdmin`. - function run(address initialAdmin) - internal - returns ( - LockupNFTDescriptor nftDescriptor, - SablierLockup lockup, - SablierBatchLockup batchLockup, - SablierMerkleFactory merkleLockupFactory - ) - { - (nftDescriptor, lockup, batchLockup, merkleLockupFactory) = _run(initialAdmin); - } - - /// @dev Common logic for the run functions. - function _run(address initialAdmin) - internal - returns ( - LockupNFTDescriptor nftDescriptor, - SablierLockup lockup, - SablierBatchLockup batchLockup, - SablierMerkleFactory merkleLockupFactory - ) - { - // Deploy Core. - nftDescriptor = new LockupNFTDescriptor{ salt: SALT }(); - lockup = new SablierLockup{ salt: SALT }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); - batchLockup = new SablierBatchLockup{ salt: SALT }(); - - // Deploy Periphery. - merkleLockupFactory = new SablierMerkleFactory{ salt: SALT }(initialAdmin); - - appendToFileDeployedAddresses( - address(lockup), address(nftDescriptor), address(batchLockup), address(merkleLockupFactory) - ); - } -} diff --git a/script/protocol/DeployProtocol.s.sol b/script/protocol/DeployProtocol.s.sol deleted file mode 100644 index d92e4e58c..000000000 --- a/script/protocol/DeployProtocol.s.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { LockupNFTDescriptor } from "./../../src/core/LockupNFTDescriptor.sol"; -import { SablierBatchLockup } from "./../../src/core/SablierBatchLockup.sol"; -import { SablierLockup } from "./../../src/core/SablierLockup.sol"; -import { SablierMerkleFactory } from "./../../src/periphery/SablierMerkleFactory.sol"; -import { DeploymentLogger } from "./DeploymentLogger.s.sol"; - -/// @notice Deploys the Lockup Protocol. -contract DeployProtocol is DeploymentLogger("non_deterministic") { - /// @dev Deploys the protocol with the admin set in `adminMap`. - function run() - public - virtual - broadcast - returns ( - LockupNFTDescriptor nftDescriptor, - SablierLockup lockup, - SablierBatchLockup batchLockup, - SablierMerkleFactory merkleLockupFactory - ) - { - address initialAdmin = adminMap[block.chainid]; - - (nftDescriptor, lockup, batchLockup, merkleLockupFactory) = _run(initialAdmin); - } - - /// @dev Deploys the protocol with the given `initialAdmin`. - function run(address initialAdmin) - internal - returns ( - LockupNFTDescriptor nftDescriptor, - SablierLockup lockup, - SablierBatchLockup batchLockup, - SablierMerkleFactory merkleLockupFactory - ) - { - (nftDescriptor, lockup, batchLockup, merkleLockupFactory) = _run(initialAdmin); - } - - /// @dev Common logic for the run functions. - function _run(address initialAdmin) - internal - returns ( - LockupNFTDescriptor nftDescriptor, - SablierLockup lockup, - SablierBatchLockup batchLockup, - SablierMerkleFactory merkleLockupFactory - ) - { - // Deploy Core. - nftDescriptor = new LockupNFTDescriptor(); - lockup = new SablierLockup(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); - batchLockup = new SablierBatchLockup(); - - // Deploy Periphery. - merkleLockupFactory = new SablierMerkleFactory(initialAdmin); - - appendToFileDeployedAddresses( - address(lockup), address(nftDescriptor), address(batchLockup), address(merkleLockupFactory) - ); - } -} diff --git a/shell/generate-svg.sh b/shell/generate-svg.sh index 56b233038..7748644d6 100755 --- a/shell/generate-svg.sh +++ b/shell/generate-svg.sh @@ -18,7 +18,7 @@ arg_duration=${4:-"91"} # Run the Forge script and extract the SVG from stdout output=$( - forge script script/core/GenerateSVG.s.sol \ + forge script script/GenerateSVG.s.sol \ --sig "run(uint256,string,string,uint256)" \ "$arg_progress" \ "$arg_status" \ diff --git a/shell/prepare-artifacts.sh b/shell/prepare-artifacts.sh index 6db458496..9349325ec 100755 --- a/shell/prepare-artifacts.sh +++ b/shell/prepare-artifacts.sh @@ -16,54 +16,32 @@ rm -rf $artifacts # Create the new artifacts directories mkdir $artifacts \ - "$artifacts/core" \ - "$artifacts/core/interfaces" \ - "$artifacts/core/libraries" \ + "$artifacts/interfaces" \ + "$artifacts/libraries" \ "$artifacts/erc20" \ - "$artifacts/erc721" \ - "$artifacts/periphery" \ - "$artifacts/periphery/interfaces" \ - "$artifacts/periphery/libraries" + "$artifacts/erc721" ################################################ -#### CORE #### +#### LOCKUP #### ################################################ -core=./artifacts/core -cp out-optimized/LockupNFTDescriptor.sol/LockupNFTDescriptor.json $core -cp out-optimized/SablierLockup.sol/SablierLockup.json $core +lockup=./artifacts/ +cp out-optimized/LockupNFTDescriptor.sol/LockupNFTDescriptor.json $lockup +cp out-optimized/SablierLockup.sol/SablierLockup.json $lockup +cp out-optimized/SablierBatchLockup.sol/SablierBatchLockup.json $lockup -core_interfaces=./artifacts/core/interfaces -cp out-optimized/ILockupNFTDescriptor.sol/ILockupNFTDescriptor.json $core_interfaces -cp out-optimized/ISablierLockupRecipient.sol/ISablierLockupRecipient.json $core_interfaces -cp out-optimized/ISablierLockupBase.sol/ISablierLockupBase.json $core_interfaces -cp out-optimized/ISablierLockup.sol/ISablierLockup.json $core_interfaces +lockup_interfaces=./artifacts/interfaces +cp out-optimized/ISablierBatchLockup.sol/ISablierBatchLockup.json $lockup_interfaces +cp out-optimized/ILockupNFTDescriptor.sol/ILockupNFTDescriptor.json $lockup_interfaces +cp out-optimized/ISablierLockupRecipient.sol/ISablierLockupRecipient.json $lockup_interfaces +cp out-optimized/ISablierLockupBase.sol/ISablierLockupBase.json $lockup_interfaces +cp out-optimized/ISablierLockup.sol/ISablierLockup.json $lockup_interfaces -core_libraries=./artifacts/core/libraries -cp out-optimized/Errors.sol/Errors.json $core_libraries -cp out-optimized/Helpers.sol/Helpers.json $core_libraries -cp out-optimized/VestingMath.sol/VestingMath.json $core_libraries +lockup_libraries=./artifacts/libraries +cp out-optimized/Errors.sol/Errors.json $lockup_libraries +cp out-optimized/Helpers.sol/Helpers.json $lockup_libraries +cp out-optimized/VestingMath.sol/VestingMath.json $lockup_libraries -################################################ -#### PERIPHERY #### -################################################ - -periphery=./artifacts/periphery -cp out-optimized/SablierBatchLockup.sol/SablierBatchLockup.json $periphery -cp out-optimized/SablierMerkleFactory.sol/SablierMerkleFactory.json $periphery -cp out-optimized/SablierMerkleInstant.sol/SablierMerkleInstant.json $periphery -cp out-optimized/SablierMerkleLL.sol/SablierMerkleLL.json $periphery -cp out-optimized/SablierMerkleLT.sol/SablierMerkleLT.json $periphery - -periphery_interfaces=./artifacts/periphery/interfaces -cp out-optimized/ISablierBatchLockup.sol/ISablierBatchLockup.json $periphery_interfaces -cp out-optimized/ISablierMerkleFactory.sol/ISablierMerkleFactory.json $periphery_interfaces -cp out-optimized/ISablierMerkleInstant.sol/ISablierMerkleInstant.json $periphery_interfaces -cp out-optimized/ISablierMerkleLL.sol/ISablierMerkleLL.json $periphery_interfaces -cp out-optimized/ISablierMerkleLT.sol/ISablierMerkleLT.json $periphery_interfaces - -periphery_libraries=./artifacts/periphery/libraries -cp out-optimized/libraries/Errors.sol/Errors.json $periphery_libraries ################################################ #### OTHERS #### diff --git a/shell/update-precompiles.sh b/shell/update-precompiles.sh index 04f70e6f6..abcbf9f42 100755 --- a/shell/update-precompiles.sh +++ b/shell/update-precompiles.sh @@ -14,7 +14,6 @@ FOUNDRY_PROFILE=optimized forge build # Retrieve the raw bytecodes, removing the "0x" prefix batch_lockup=$(cat out-optimized/SablierBatchLockup.sol/SablierBatchLockup.json | jq -r '.bytecode.object' | cut -c 3-) lockup=$(cat out-optimized/SablierLockup.sol/SablierLockup.json | jq -r '.bytecode.object' | cut -c 3-) -merkle_factory=$(cat out-optimized/SablierMerkleFactory.sol/SablierMerkleFactory.json | jq -r '.bytecode.object' | cut -c 3-) nft_descriptor=$(cat out-optimized/LockupNFTDescriptor.sol/LockupNFTDescriptor.json | jq -r '.bytecode.object' | cut -c 3-) precompiles_path="precompiles/Precompiles.sol" @@ -26,7 +25,6 @@ fi # Replace the current bytecodes sd "(BYTECODE_BATCH_LOCKUP =)[^;]+;" "\$1 hex\"$batch_lockup\";" $precompiles_path sd "(BYTECODE_LOCKUP =)[^;]+;" "\$1 hex\"$lockup\";" $precompiles_path -sd "(BYTECODE_MERKLE_FACTORY =)[^;]+;" "\$1 hex\"$merkle_factory\";" $precompiles_path sd "(BYTECODE_NFT_DESCRIPTOR =)[^;]+;" "\$1 hex\"$nft_descriptor\";" $precompiles_path # Reformat the code with Forge diff --git a/src/core/LockupNFTDescriptor.sol b/src/LockupNFTDescriptor.sol similarity index 100% rename from src/core/LockupNFTDescriptor.sol rename to src/LockupNFTDescriptor.sol diff --git a/src/core/SablierBatchLockup.sol b/src/SablierBatchLockup.sol similarity index 100% rename from src/core/SablierBatchLockup.sol rename to src/SablierBatchLockup.sol diff --git a/src/core/SablierLockup.sol b/src/SablierLockup.sol similarity index 100% rename from src/core/SablierLockup.sol rename to src/SablierLockup.sol diff --git a/src/core/abstracts/Adminable.sol b/src/abstracts/Adminable.sol similarity index 100% rename from src/core/abstracts/Adminable.sol rename to src/abstracts/Adminable.sol diff --git a/src/core/abstracts/Batch.sol b/src/abstracts/Batch.sol similarity index 100% rename from src/core/abstracts/Batch.sol rename to src/abstracts/Batch.sol diff --git a/src/core/abstracts/NoDelegateCall.sol b/src/abstracts/NoDelegateCall.sol similarity index 100% rename from src/core/abstracts/NoDelegateCall.sol rename to src/abstracts/NoDelegateCall.sol diff --git a/src/core/abstracts/SablierLockupBase.sol b/src/abstracts/SablierLockupBase.sol similarity index 100% rename from src/core/abstracts/SablierLockupBase.sol rename to src/abstracts/SablierLockupBase.sol diff --git a/src/core/interfaces/IAdminable.sol b/src/interfaces/IAdminable.sol similarity index 100% rename from src/core/interfaces/IAdminable.sol rename to src/interfaces/IAdminable.sol diff --git a/src/core/interfaces/IBatch.sol b/src/interfaces/IBatch.sol similarity index 100% rename from src/core/interfaces/IBatch.sol rename to src/interfaces/IBatch.sol diff --git a/src/core/interfaces/ILockupNFTDescriptor.sol b/src/interfaces/ILockupNFTDescriptor.sol similarity index 100% rename from src/core/interfaces/ILockupNFTDescriptor.sol rename to src/interfaces/ILockupNFTDescriptor.sol diff --git a/src/core/interfaces/ISablierBatchLockup.sol b/src/interfaces/ISablierBatchLockup.sol similarity index 98% rename from src/core/interfaces/ISablierBatchLockup.sol rename to src/interfaces/ISablierBatchLockup.sol index db2cc457e..057dca9cf 100644 --- a/src/core/interfaces/ISablierBatchLockup.sol +++ b/src/interfaces/ISablierBatchLockup.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierLockup } from "../../core/interfaces/ISablierLockup.sol"; +import { ISablierLockup } from "../interfaces/ISablierLockup.sol"; import { BatchLockup } from "../types/DataTypes.sol"; diff --git a/src/core/interfaces/ISablierLockup.sol b/src/interfaces/ISablierLockup.sol similarity index 100% rename from src/core/interfaces/ISablierLockup.sol rename to src/interfaces/ISablierLockup.sol diff --git a/src/core/interfaces/ISablierLockupBase.sol b/src/interfaces/ISablierLockupBase.sol similarity index 100% rename from src/core/interfaces/ISablierLockupBase.sol rename to src/interfaces/ISablierLockupBase.sol diff --git a/src/core/interfaces/ISablierLockupRecipient.sol b/src/interfaces/ISablierLockupRecipient.sol similarity index 100% rename from src/core/interfaces/ISablierLockupRecipient.sol rename to src/interfaces/ISablierLockupRecipient.sol diff --git a/src/core/libraries/Errors.sol b/src/libraries/Errors.sol similarity index 100% rename from src/core/libraries/Errors.sol rename to src/libraries/Errors.sol diff --git a/src/core/libraries/Helpers.sol b/src/libraries/Helpers.sol similarity index 100% rename from src/core/libraries/Helpers.sol rename to src/libraries/Helpers.sol diff --git a/src/core/libraries/NFTSVG.sol b/src/libraries/NFTSVG.sol similarity index 100% rename from src/core/libraries/NFTSVG.sol rename to src/libraries/NFTSVG.sol diff --git a/src/core/libraries/SVGElements.sol b/src/libraries/SVGElements.sol similarity index 100% rename from src/core/libraries/SVGElements.sol rename to src/libraries/SVGElements.sol diff --git a/src/core/libraries/VestingMath.sol b/src/libraries/VestingMath.sol similarity index 100% rename from src/core/libraries/VestingMath.sol rename to src/libraries/VestingMath.sol diff --git a/src/periphery/SablierMerkleFactory.sol b/src/periphery/SablierMerkleFactory.sol deleted file mode 100644 index 3cd80bff1..000000000 --- a/src/periphery/SablierMerkleFactory.sol +++ /dev/null @@ -1,302 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity >=0.8.22; - -import { uUNIT } from "@prb/math/src/UD2x18.sol"; - -import { Adminable } from "../core/abstracts/Adminable.sol"; -import { ISablierLockup } from "../core/interfaces/ISablierLockup.sol"; - -import { ISablierMerkleBase } from "./interfaces/ISablierMerkleBase.sol"; -import { ISablierMerkleFactory } from "./interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleInstant } from "./interfaces/ISablierMerkleInstant.sol"; -import { ISablierMerkleLL } from "./interfaces/ISablierMerkleLL.sol"; -import { ISablierMerkleLT } from "./interfaces/ISablierMerkleLT.sol"; -import { Errors } from "./libraries/Errors.sol"; -import { SablierMerkleInstant } from "./SablierMerkleInstant.sol"; -import { SablierMerkleLL } from "./SablierMerkleLL.sol"; -import { SablierMerkleLT } from "./SablierMerkleLT.sol"; -import { MerkleBase, MerkleFactory, MerkleLL, MerkleLT } from "./types/DataTypes.sol"; - -/// @title SablierMerkleFactory -/// @notice See the documentation in {ISablierMerkleFactory}. -contract SablierMerkleFactory is - ISablierMerkleFactory, // 2 inherited components - Adminable // 1 inherited component -{ - /*////////////////////////////////////////////////////////////////////////// - STATE VARIABLES - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleFactory - uint256 public override defaultSablierFee; - - /// @dev A mapping of custom Sablier fees by user. - mapping(address campaignCreator => MerkleFactory.SablierFeeByUser customFee) private _sablierFeeByUsers; - - /*////////////////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////////////////*/ - - /// @param initialAdmin The address of the initial contract admin. - constructor(address initialAdmin) Adminable(initialAdmin) { } - - /*////////////////////////////////////////////////////////////////////////// - USER-FACING CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleFactory - function isPercentagesSum100(MerkleLT.TrancheWithPercentage[] calldata tranches) - external - pure - override - returns (bool result) - { - uint64 totalPercentage; - for (uint256 i = 0; i < tranches.length; ++i) { - totalPercentage += tranches[i].unlockPercentage.unwrap(); - } - return totalPercentage == uUNIT; - } - - /// @inheritdoc ISablierMerkleFactory - function sablierFeeByUser(address campaignCreator) - external - view - override - returns (MerkleFactory.SablierFeeByUser memory) - { - return _sablierFeeByUsers[campaignCreator]; - } - - /*////////////////////////////////////////////////////////////////////////// - ADMIN-FACING NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleFactory - function resetSablierFeeByUser(address campaignCreator) external override onlyAdmin { - delete _sablierFeeByUsers[campaignCreator]; - - // Log the reset. - emit ResetSablierFee({ admin: msg.sender, campaignCreator: campaignCreator }); - } - - /// @inheritdoc ISablierMerkleFactory - function setDefaultSablierFee(uint256 defaultFee) external override onlyAdmin { - // Effect: update the default Sablier fee. - defaultSablierFee = defaultFee; - - emit SetDefaultSablierFee(msg.sender, defaultFee); - } - - /// @inheritdoc ISablierMerkleFactory - function setSablierFeeByUser(address campaignCreator, uint256 fee) external override onlyAdmin { - MerkleFactory.SablierFeeByUser storage feeByUser = _sablierFeeByUsers[campaignCreator]; - - // Check: if user does not belong to the custom fee list. - if (!feeByUser.enabled) feeByUser.enabled = true; - - // Effect: update the Sablier fee for the given campaign creator. - feeByUser.fee = fee; - - // Log the update. - emit SetSablierFeeForUser({ admin: msg.sender, campaignCreator: campaignCreator, sablierFee: fee }); - } - - /// @inheritdoc ISablierMerkleFactory - function withdrawFees(address payable to, ISablierMerkleBase merkleBase) external override onlyAdmin { - // Check: the withdrawal address is not zero. - if (to == address(0)) { - revert Errors.SablierMerkleFactory_WithdrawToZeroAddress(); - } - - // Effect: call `withdrawFees` on the MerkleBase contract. - uint256 fees = merkleBase.withdrawFees(to); - - // Log the withdrawal. - emit WithdrawSablierFees({ admin: msg.sender, merkleBase: merkleBase, to: to, sablierFees: fees }); - } - - /*////////////////////////////////////////////////////////////////////////// - USER-FACING NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleFactory - function createMerkleInstant( - MerkleBase.ConstructorParams memory baseParams, - uint256 aggregateAmount, - uint256 recipientCount - ) - external - override - returns (ISablierMerkleInstant merkleInstant) - { - // Hash the parameters to generate a salt. - bytes32 salt = keccak256( - abi.encodePacked( - msg.sender, - baseParams.asset, - baseParams.expiration, - baseParams.initialAdmin, - abi.encode(baseParams.ipfsCID), - baseParams.merkleRoot, - bytes32(abi.encodePacked(baseParams.name)) - ) - ); - - // Compute the Sablier fee for the user. - uint256 sablierFee = _computeSablierFeeForUser(msg.sender); - - // Deploy the MerkleInstant contract with CREATE2. - merkleInstant = new SablierMerkleInstant{ salt: salt }(baseParams, sablierFee); - - // Log the creation of the MerkleInstant contract, including some metadata that is not stored on-chain. - emit CreateMerkleInstant(merkleInstant, baseParams, aggregateAmount, recipientCount, sablierFee); - } - - /// @inheritdoc ISablierMerkleFactory - function createMerkleLL( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - MerkleLL.Schedule memory schedule, - uint256 aggregateAmount, - uint256 recipientCount - ) - external - override - returns (ISablierMerkleLL merkleLL) - { - // Hash the parameters to generate a salt. - bytes32 salt = keccak256( - abi.encodePacked( - msg.sender, - baseParams.asset, - baseParams.expiration, - baseParams.initialAdmin, - abi.encode(baseParams.ipfsCID), - baseParams.merkleRoot, - bytes32(abi.encodePacked(baseParams.name)), - lockup, - cancelable, - transferable, - abi.encode(schedule) - ) - ); - - // Compute the Sablier fee for the user. - uint256 sablierFee = _computeSablierFeeForUser(msg.sender); - - // Deploy the MerkleLL contract with CREATE2. - merkleLL = new SablierMerkleLL{ salt: salt }(baseParams, lockup, cancelable, transferable, schedule, sablierFee); - - // Log the creation of the MerkleLL contract, including some metadata that is not stored on-chain. - emit CreateMerkleLL( - merkleLL, - baseParams, - lockup, - cancelable, - transferable, - schedule, - aggregateAmount, - recipientCount, - sablierFee - ); - } - - /// @inheritdoc ISablierMerkleFactory - function createMerkleLT( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - uint40 streamStartTime, - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages, - uint256 aggregateAmount, - uint256 recipientCount - ) - external - override - returns (ISablierMerkleLT merkleLT) - { - // Calculate the sum of percentages and durations across all tranches. - uint256 count = tranchesWithPercentages.length; - uint256 totalDuration; - for (uint256 i = 0; i < count; ++i) { - unchecked { - // Safe to use `unchecked` because its only used in the event. - totalDuration += tranchesWithPercentages[i].duration; - } - } - - // Compute the Sablier fee for the user. - uint256 sablierFee = _computeSablierFeeForUser(msg.sender); - - // Deploy the MerkleLT contract. - merkleLT = _deployMerkleLT( - baseParams, lockup, cancelable, transferable, streamStartTime, tranchesWithPercentages, sablierFee - ); - - // Log the creation of the MerkleLT contract, including some metadata that is not stored on-chain. - emit CreateMerkleLT( - merkleLT, - baseParams, - lockup, - cancelable, - transferable, - streamStartTime, - tranchesWithPercentages, - totalDuration, - aggregateAmount, - recipientCount, - sablierFee - ); - } - - /*////////////////////////////////////////////////////////////////////////// - PRIVATE NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Computes the Sablier fee for the user, use the default fee if not enabled. - function _computeSablierFeeForUser(address user) private view returns (uint256) { - return _sablierFeeByUsers[user].enabled ? _sablierFeeByUsers[user].fee : defaultSablierFee; - } - - /// @notice Deploys a new MerkleLT contract with CREATE2. - /// @dev We need a separate function to prevent the stack too deep error. - function _deployMerkleLT( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - uint40 streamStartTime, - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages, - uint256 sablierFee - ) - private - returns (ISablierMerkleLT merkleLT) - { - // Hash the parameters to generate a salt. - bytes32 salt = keccak256( - abi.encodePacked( - msg.sender, - baseParams.asset, - baseParams.expiration, - baseParams.initialAdmin, - abi.encode(baseParams.ipfsCID), - baseParams.merkleRoot, - bytes32(abi.encodePacked(baseParams.name)), - lockup, - cancelable, - transferable, - streamStartTime, - abi.encode(tranchesWithPercentages) - ) - ); - - // Deploy the MerkleLT contract with CREATE2. - merkleLT = new SablierMerkleLT{ salt: salt }( - baseParams, lockup, cancelable, transferable, streamStartTime, tranchesWithPercentages, sablierFee - ); - } -} diff --git a/src/periphery/SablierMerkleInstant.sol b/src/periphery/SablierMerkleInstant.sol deleted file mode 100644 index 844b8459b..000000000 --- a/src/periphery/SablierMerkleInstant.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; - -import { SablierMerkleBase } from "./abstracts/SablierMerkleBase.sol"; -import { ISablierMerkleInstant } from "./interfaces/ISablierMerkleInstant.sol"; -import { MerkleBase } from "./types/DataTypes.sol"; - -/// @title SablierMerkleInstant -/// @notice See the documentation in {ISablierMerkleInstant}. -contract SablierMerkleInstant is - ISablierMerkleInstant, // 2 inherited components - SablierMerkleBase // 4 inherited components -{ - using SafeERC20 for IERC20; - - /*////////////////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Constructs the contract by initializing the immutable state variables. - constructor( - MerkleBase.ConstructorParams memory baseParams, - uint256 sablierFee - ) - SablierMerkleBase(baseParams, sablierFee) - { } - - /*////////////////////////////////////////////////////////////////////////// - INTERNAL NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc SablierMerkleBase - function _claim(uint256 index, address recipient, uint128 amount) internal override { - // Interaction: withdraw the assets to the recipient. - ASSET.safeTransfer(recipient, amount); - - // Log the claim. - emit Claim(index, recipient, amount); - } -} diff --git a/src/periphery/SablierMerkleLL.sol b/src/periphery/SablierMerkleLL.sol deleted file mode 100644 index eada7ad10..000000000 --- a/src/periphery/SablierMerkleLL.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { ud } from "@prb/math/src/UD60x18.sol"; - -import { ISablierLockup } from "../core/interfaces/ISablierLockup.sol"; -import { Broker, Lockup, LockupLinear } from "../core/types/DataTypes.sol"; - -import { SablierMerkleBase } from "./abstracts/SablierMerkleBase.sol"; -import { ISablierMerkleLL } from "./interfaces/ISablierMerkleLL.sol"; -import { MerkleBase, MerkleLL } from "./types/DataTypes.sol"; - -/// @title SablierMerkleLL -/// @notice See the documentation in {ISablierMerkleLL}. -contract SablierMerkleLL is - ISablierMerkleLL, // 2 inherited components - SablierMerkleBase // 4 inherited components -{ - using SafeERC20 for IERC20; - - /*////////////////////////////////////////////////////////////////////////// - STATE VARIABLES - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleLL - bool public immutable override CANCELABLE; - - /// @inheritdoc ISablierMerkleLL - ISablierLockup public immutable override LOCKUP; - - /// @inheritdoc ISablierMerkleLL - bool public immutable override TRANSFERABLE; - - /// @inheritdoc ISablierMerkleLL - MerkleLL.Schedule public override schedule; - - /*////////////////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Constructs the contract by initializing the immutable state variables, and max approving the Lockup - /// contract. - constructor( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - MerkleLL.Schedule memory schedule_, - uint256 sablierFee - ) - SablierMerkleBase(baseParams, sablierFee) - { - CANCELABLE = cancelable; - LOCKUP = lockup; - TRANSFERABLE = transferable; - schedule = schedule_; - - // Max approve the Lockup contract to spend funds from the MerkleLL contract. - ASSET.forceApprove(address(LOCKUP), type(uint256).max); - } - - /*////////////////////////////////////////////////////////////////////////// - USER-FACING NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc SablierMerkleBase - function _claim(uint256 index, address recipient, uint128 amount) internal override { - // Calculate the timestamps for the stream. - Lockup.Timestamps memory timestamps; - if (schedule.startTime == 0) { - timestamps.start = uint40(block.timestamp); - } else { - timestamps.start = schedule.startTime; - } - - uint40 cliffTime; - - // It is safe to use unchecked arithmetic because the `createWithTimestamps` function in the Lockup contract - // will nonetheless make the relevant checks. - unchecked { - if (schedule.cliffDuration > 0) { - cliffTime = timestamps.start + schedule.cliffDuration; - } - timestamps.end = timestamps.start + schedule.totalDuration; - } - - // Interaction: create the stream via {SablierLockup}. - uint256 streamId = LOCKUP.createWithTimestampsLL( - Lockup.CreateWithTimestamps({ - sender: admin, - recipient: recipient, - totalAmount: amount, - asset: ASSET, - cancelable: CANCELABLE, - transferable: TRANSFERABLE, - timestamps: timestamps, - broker: Broker({ account: address(0), fee: ud(0) }) - }), - LockupLinear.UnlockAmounts({ start: schedule.startAmount, cliff: schedule.cliffAmount }), - cliffTime - ); - - // Log the claim. - emit Claim(index, recipient, amount, streamId); - } -} diff --git a/src/periphery/SablierMerkleLT.sol b/src/periphery/SablierMerkleLT.sol deleted file mode 100644 index 9df43efd8..000000000 --- a/src/periphery/SablierMerkleLT.sol +++ /dev/null @@ -1,201 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { uUNIT } from "@prb/math/src/UD2x18.sol"; -import { UD60x18, ud60x18, ZERO } from "@prb/math/src/UD60x18.sol"; - -import { ISablierLockup } from "../core/interfaces/ISablierLockup.sol"; -import { Broker, Lockup, LockupTranched } from "../core/types/DataTypes.sol"; - -import { SablierMerkleBase } from "./abstracts/SablierMerkleBase.sol"; -import { ISablierMerkleLT } from "./interfaces/ISablierMerkleLT.sol"; -import { Errors } from "./libraries/Errors.sol"; -import { MerkleBase, MerkleLT } from "./types/DataTypes.sol"; - -/// @title SablierMerkleLT -/// @notice See the documentation in {ISablierMerkleLT}. -contract SablierMerkleLT is - ISablierMerkleLT, // 2 inherited components - SablierMerkleBase // 4 inherited components -{ - using SafeERC20 for IERC20; - - /*////////////////////////////////////////////////////////////////////////// - STATE VARIABLES - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleLT - bool public immutable override CANCELABLE; - - /// @inheritdoc ISablierMerkleLT - ISablierLockup public immutable override LOCKUP; - - /// @inheritdoc ISablierMerkleLT - uint40 public immutable override STREAM_START_TIME; - - /// @inheritdoc ISablierMerkleLT - uint64 public immutable override TOTAL_PERCENTAGE; - - /// @inheritdoc ISablierMerkleLT - bool public immutable override TRANSFERABLE; - - /// @dev The tranches with their respective unlock percentages and durations. - MerkleLT.TrancheWithPercentage[] internal _tranchesWithPercentages; - - /*////////////////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Constructs the contract by initializing the immutable state variables, and max approving the Lockup - /// contract. - constructor( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - uint40 streamStartTime, - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages, - uint256 sablierFee - ) - SablierMerkleBase(baseParams, sablierFee) - { - CANCELABLE = cancelable; - LOCKUP = lockup; - STREAM_START_TIME = streamStartTime; - TRANSFERABLE = transferable; - - uint256 count = tranchesWithPercentages.length; - - // Calculate the total percentage of the tranches and save them in the contract state. - uint64 totalPercentage; - for (uint256 i = 0; i < count; ++i) { - uint64 percentage = tranchesWithPercentages[i].unlockPercentage.unwrap(); - totalPercentage += percentage; - _tranchesWithPercentages.push(tranchesWithPercentages[i]); - } - TOTAL_PERCENTAGE = totalPercentage; - - // Max approve the Lockup contract to spend funds from the MerkleLT contract. - ASSET.forceApprove(address(LOCKUP), type(uint256).max); - } - - /*////////////////////////////////////////////////////////////////////////// - USER-FACING CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleLT - function getTranchesWithPercentages() external view override returns (MerkleLT.TrancheWithPercentage[] memory) { - return _tranchesWithPercentages; - } - - /*////////////////////////////////////////////////////////////////////////// - INTERNAL NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc SablierMerkleBase - function _claim(uint256 index, address recipient, uint128 amount) internal override { - // Check: the sum of percentages equals 100%. - if (TOTAL_PERCENTAGE != uUNIT) { - revert Errors.SablierMerkleLT_TotalPercentageNotOneHundred(TOTAL_PERCENTAGE); - } - - // Calculate the tranches based on the unlock percentages. - (uint40 startTime, LockupTranched.Tranche[] memory tranches) = _calculateStartTimeAndTranches(amount); - - // Calculate the stream's end time. - uint40 endTime; - unchecked { - endTime = tranches[tranches.length - 1].timestamp; - } - - // Interaction: create the stream via {SablierLockup-createWithTimestampsLT}. - uint256 streamId = LOCKUP.createWithTimestampsLT( - Lockup.CreateWithTimestamps({ - sender: admin, - recipient: recipient, - totalAmount: amount, - asset: ASSET, - cancelable: CANCELABLE, - transferable: TRANSFERABLE, - timestamps: Lockup.Timestamps({ start: startTime, end: endTime }), - broker: Broker({ account: address(0), fee: ZERO }) - }), - tranches - ); - - // Log the claim. - emit Claim(index, recipient, amount, streamId); - } - - /*////////////////////////////////////////////////////////////////////////// - INTERNAL CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Calculates the start time, and the tranches based on the claim amount and the unlock percentages for each - /// tranche. - function _calculateStartTimeAndTranches(uint128 claimAmount) - internal - view - returns (uint40 startTime, LockupTranched.Tranche[] memory tranches) - { - // Calculate the start time. - if (STREAM_START_TIME == 0) { - startTime = uint40(block.timestamp); - } else { - startTime = STREAM_START_TIME; - } - - // Load the tranches in memory (to save gas). - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = _tranchesWithPercentages; - - // Declare the variables needed for calculation. - uint128 calculatedAmountsSum; - UD60x18 claimAmountUD = ud60x18(claimAmount); - uint256 trancheCount = tranchesWithPercentages.length; - tranches = new LockupTranched.Tranche[](trancheCount); - - unchecked { - // Convert the tranche's percentage from the `UD2x18` to the `UD60x18` type. - UD60x18 percentage = (tranchesWithPercentages[0].unlockPercentage).intoUD60x18(); - - // Calculate the tranche's amount by multiplying the claim amount by the unlock percentage. - uint128 calculatedAmount = claimAmountUD.mul(percentage).intoUint128(); - - // The first tranche is precomputed because it is needed in the for loop below. - tranches[0] = LockupTranched.Tranche({ - amount: calculatedAmount, - timestamp: startTime + tranchesWithPercentages[0].duration - }); - - // Add the calculated tranche amount. - calculatedAmountsSum += calculatedAmount; - - // Iterate over each tranche to calculate its timestamp and unlock amount. - for (uint256 i = 1; i < trancheCount; ++i) { - percentage = (tranchesWithPercentages[i].unlockPercentage).intoUD60x18(); - calculatedAmount = claimAmountUD.mul(percentage).intoUint128(); - - tranches[i] = LockupTranched.Tranche({ - amount: calculatedAmount, - timestamp: tranches[i - 1].timestamp + tranchesWithPercentages[i].duration - }); - - calculatedAmountsSum += calculatedAmount; - } - } - - // It should never be the case that the sum of the calculated amounts is greater than the claim amount because - // PRBMath always rounds down. - assert(calculatedAmountsSum <= claimAmount); - - // Since there can be rounding errors, the last tranche amount needs to be adjusted to ensure the sum of all - // tranche amounts equals the claim amount. - if (calculatedAmountsSum < claimAmount) { - unchecked { - tranches[trancheCount - 1].amount += claimAmount - calculatedAmountsSum; - } - } - } -} diff --git a/src/periphery/abstracts/SablierMerkleBase.sol b/src/periphery/abstracts/SablierMerkleBase.sol deleted file mode 100644 index 87f7dbe7d..000000000 --- a/src/periphery/abstracts/SablierMerkleBase.sol +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; -import { BitMaps } from "@openzeppelin/contracts/utils/structs/BitMaps.sol"; -import { Adminable } from "./../../core/abstracts/Adminable.sol"; -import { ISablierMerkleBase } from "./../interfaces/ISablierMerkleBase.sol"; -import { Errors } from "./../libraries/Errors.sol"; -import { MerkleBase } from "./../types/DataTypes.sol"; - -/// @title SablierMerkleBase -/// @notice See the documentation in {ISablierMerkleBase}. -abstract contract SablierMerkleBase is - ISablierMerkleBase, // 2 inherited component - Adminable // 1 inherited component -{ - using BitMaps for BitMaps.BitMap; - using SafeERC20 for IERC20; - - /*////////////////////////////////////////////////////////////////////////// - STATE VARIABLES - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleBase - IERC20 public immutable override ASSET; - - /// @inheritdoc ISablierMerkleBase - uint40 public immutable override EXPIRATION; - - /// @inheritdoc ISablierMerkleBase - address public immutable override FACTORY; - - /// @inheritdoc ISablierMerkleBase - bytes32 public immutable override MERKLE_ROOT; - - /// @dev The name of the campaign stored as bytes32. - bytes32 internal immutable NAME; - - /// @inheritdoc ISablierMerkleBase - uint256 public immutable override SABLIER_FEE; - - /// @inheritdoc ISablierMerkleBase - string public override ipfsCID; - - /// @dev Packed booleans that record the history of claims. - BitMaps.BitMap internal _claimedBitMap; - - /// @dev The timestamp when the first claim is made. - uint40 internal _firstClaimTime; - - /*////////////////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Constructs the contract by initializing the immutable state variables. - constructor(MerkleBase.ConstructorParams memory params, uint256 sablierFee) Adminable(params.initialAdmin) { - // Check: the campaign name is not greater than 32 bytes - if (bytes(params.name).length > 32) { - revert Errors.SablierMerkleBase_CampaignNameTooLong({ nameLength: bytes(params.name).length, maxLength: 32 }); - } - - ASSET = params.asset; - EXPIRATION = params.expiration; - FACTORY = msg.sender; - ipfsCID = params.ipfsCID; - MERKLE_ROOT = params.merkleRoot; - NAME = bytes32(abi.encodePacked(params.name)); - SABLIER_FEE = sablierFee; - } - - /*////////////////////////////////////////////////////////////////////////// - USER-FACING CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleBase - function getFirstClaimTime() external view override returns (uint40) { - return _firstClaimTime; - } - - /// @inheritdoc ISablierMerkleBase - function hasClaimed(uint256 index) public view override returns (bool) { - return _claimedBitMap.get(index); - } - - /// @inheritdoc ISablierMerkleBase - function hasExpired() public view override returns (bool) { - return EXPIRATION > 0 && EXPIRATION <= block.timestamp; - } - - /// @inheritdoc ISablierMerkleBase - function name() external view override returns (string memory) { - return string(abi.encodePacked(NAME)); - } - - /*////////////////////////////////////////////////////////////////////////// - USER-FACING NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @inheritdoc ISablierMerkleBase - function claim( - uint256 index, - address recipient, - uint128 amount, - bytes32[] calldata merkleProof - ) - external - payable - override - { - // Check: the campaign has not expired. - if (hasExpired()) { - revert Errors.SablierMerkleBase_CampaignExpired({ blockTimestamp: block.timestamp, expiration: EXPIRATION }); - } - - // Check: `msg.value` is not less than the Sablier fee. - if (msg.value < SABLIER_FEE) { - revert Errors.SablierMerkleBase_InsufficientFeePayment(msg.value, SABLIER_FEE); - } - - // Check: the index has not been claimed. - if (_claimedBitMap.get(index)) { - revert Errors.SablierMerkleBase_StreamClaimed(index); - } - - // Generate the Merkle tree leaf by hashing the corresponding parameters. Hashing twice prevents second - // preimage attacks. - bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(index, recipient, amount)))); - - // Check: the input claim is included in the Merkle tree. - if (!MerkleProof.verify(merkleProof, MERKLE_ROOT, leaf)) { - revert Errors.SablierMerkleBase_InvalidProof(); - } - - // Effect: set the `_firstClaimTime` if its zero. - if (_firstClaimTime == 0) { - _firstClaimTime = uint40(block.timestamp); - } - - // Effect: mark the index as claimed. - _claimedBitMap.set(index); - - // Call the internal virtual function. - _claim(index, recipient, amount); - } - - /// @inheritdoc ISablierMerkleBase - function clawback(address to, uint128 amount) external override onlyAdmin { - // Check: current timestamp is over the grace period and the campaign has not expired. - if (_hasGracePeriodPassed() && !hasExpired()) { - revert Errors.SablierMerkleBase_ClawbackNotAllowed({ - blockTimestamp: block.timestamp, - expiration: EXPIRATION, - firstClaimTime: _firstClaimTime - }); - } - - // Effect: transfer the tokens to the provided address. - ASSET.safeTransfer(to, amount); - - // Log the clawback. - emit Clawback(admin, to, amount); - } - - /// @inheritdoc ISablierMerkleBase - function withdrawFees(address payable to) external override returns (uint256 feeAmount) { - // Check: the msg.sender is the FACTORY. - if (msg.sender != FACTORY) { - revert Errors.SablierMerkleBase_CallerNotFactory(FACTORY, msg.sender); - } - - feeAmount = address(this).balance; - - // Effect: transfer the fees to the provided address. - (bool success,) = to.call{ value: feeAmount }(""); - - // Revert if the call failed. - if (!success) { - revert Errors.SablierMerkleBase_FeeWithdrawFailed(to, feeAmount); - } - } - - /*////////////////////////////////////////////////////////////////////////// - INTERNAL CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Returns a flag indicating whether the grace period has passed. - /// @dev The grace period is 7 days after the first claim. - function _hasGracePeriodPassed() internal view returns (bool) { - return _firstClaimTime > 0 && block.timestamp > _firstClaimTime + 7 days; - } - - /*////////////////////////////////////////////////////////////////////////// - INTERNAL NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev This function is implemented by child contracts, so the logic varies depending on the model. - function _claim(uint256 index, address recipient, uint128 amount) internal virtual; -} diff --git a/src/periphery/interfaces/ISablierMerkleBase.sol b/src/periphery/interfaces/ISablierMerkleBase.sol deleted file mode 100644 index 63ee9d8f5..000000000 --- a/src/periphery/interfaces/ISablierMerkleBase.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { IAdminable } from "../../core/interfaces/IAdminable.sol"; - -/// @title ISablierMerkleBase -/// @dev This is the base interface for Merkle Lockups and Merkle Instant. -interface ISablierMerkleBase is IAdminable { - /*////////////////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Emitted when the admin claws back the unclaimed tokens. - event Clawback(address indexed admin, address indexed to, uint128 amount); - - /*////////////////////////////////////////////////////////////////////////// - CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice The ERC-20 asset to distribute. - /// @dev This is an immutable state variable. - function ASSET() external returns (IERC20); - - /// @notice The cut-off point for the campaign, as a Unix timestamp. A value of zero means there is no expiration. - /// @dev This is an immutable state variable. - function EXPIRATION() external returns (uint40); - - /// @notice Retrieves the address of the factory contract. - function FACTORY() external view returns (address); - - /// @notice The root of the Merkle tree used to validate the proofs of inclusion. - /// @dev This is an immutable state variable. - function MERKLE_ROOT() external returns (bytes32); - - /// @notice Retrieves the minimum fee required to claim an Airstream, paid in ETH. - function SABLIER_FEE() external view returns (uint256); - - /// @notice Returns the timestamp when the first claim is made. - function getFirstClaimTime() external view returns (uint40); - - /// @notice Returns a flag indicating whether a claim has been made for a given index. - /// @dev Uses a bitmap to save gas. - /// @param index The index of the recipient to check. - function hasClaimed(uint256 index) external returns (bool); - - /// @notice Returns a flag indicating whether the campaign has expired. - function hasExpired() external view returns (bool); - - /// @notice The content identifier for indexing the campaign on IPFS. - function ipfsCID() external view returns (string memory); - - /// @notice Retrieves the name of the campaign. - function name() external returns (string memory); - - /*////////////////////////////////////////////////////////////////////////// - NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Makes the claim. - /// - /// @dev Depending on the Merkle campaign, it either transfers assets to the recipient or creates a Lockup stream - /// with an NFT minted to the recipient. - /// - /// Requirements: - /// - The campaign must not have expired. - /// - The stream must not have been claimed already. - /// - The Merkle proof must be valid. - /// - The `msg.value` must not be less than `SABLIER_FEE`. - /// - /// @param index The index of the recipient in the Merkle tree. - /// @param recipient The address of the airdrop recipient. - /// @param amount The amount of ERC-20 assets to be transferred to the recipient. - /// @param merkleProof The proof of inclusion in the Merkle tree. - function claim(uint256 index, address recipient, uint128 amount, bytes32[] calldata merkleProof) external payable; - - /// @notice Claws back the unclaimed tokens from the campaign. - /// - /// @dev Emits a {Clawback} event. - /// - /// Requirements: - /// - msg.sender must be the admin. - /// - No claim must be made, OR - /// The current timestamp must not exceed 7 days after the first claim, OR - /// The campaign must be expired. - /// - /// @param to The address to receive the tokens. - /// @param amount The amount of tokens to claw back. - function clawback(address to, uint128 amount) external; - - /// @notice Withdraws the Sablier fees accrued to the provided address. - /// - /// @dev This function transfers ETH to the provided address. If the receiver is a contract, it must be able to - /// receive ETH. - /// - /// Requirements: - /// - msg.sender must be the `FACTORY` contract. - /// - /// @param to The address to receive the Sablier fees. - /// @return feeAmount The amount of ETH transferred to the provided address. - function withdrawFees(address payable to) external returns (uint256 feeAmount); -} diff --git a/src/periphery/interfaces/ISablierMerkleFactory.sol b/src/periphery/interfaces/ISablierMerkleFactory.sol deleted file mode 100644 index 54a45eeb1..000000000 --- a/src/periphery/interfaces/ISablierMerkleFactory.sol +++ /dev/null @@ -1,233 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IAdminable } from "../../core/interfaces/IAdminable.sol"; -import { ISablierLockup } from "../../core/interfaces/ISablierLockup.sol"; - -import { ISablierMerkleBase } from "../interfaces/ISablierMerkleBase.sol"; -import { MerkleBase, MerkleFactory, MerkleLL, MerkleLT } from "../types/DataTypes.sol"; -import { ISablierMerkleInstant } from "./ISablierMerkleInstant.sol"; -import { ISablierMerkleLL } from "./ISablierMerkleLL.sol"; -import { ISablierMerkleLT } from "./ISablierMerkleLT.sol"; - -/// @title ISablierMerkleFactory -/// @notice A contract that deploys Merkle Lockups and Merkle Instant campaigns. Both of these use Merkle proofs for -/// token distribution. Merkle Lockup enable Airstreams, a portmanteau of "airdrop" and "stream". This is an airdrop -/// model where the tokens are distributed over time, as opposed to all at once. On the other hand, Merkle Instant -/// enables instant airdrops where tokens are unlocked and distributed immediately. See the Sablier docs for more -/// guidance: https://docs.sablier.com -/// @dev Deploys Merkle Lockup and Merkle Instant campaigns with CREATE2. -interface ISablierMerkleFactory is IAdminable { - /*////////////////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Emitted when a {SablierMerkleInstant} campaign is created. - event CreateMerkleInstant( - ISablierMerkleInstant indexed merkleInstant, - MerkleBase.ConstructorParams baseParams, - uint256 aggregateAmount, - uint256 recipientCount, - uint256 sablierFee - ); - - /// @notice Emitted when a {SablierMerkleLL} campaign is created. - event CreateMerkleLL( - ISablierMerkleLL indexed merkleLL, - MerkleBase.ConstructorParams baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - MerkleLL.Schedule schedule, - uint256 aggregateAmount, - uint256 recipientCount, - uint256 sablierFee - ); - - /// @notice Emitted when a {SablierMerkleLT} campaign is created. - event CreateMerkleLT( - ISablierMerkleLT indexed merkleLT, - MerkleBase.ConstructorParams baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - uint40 streamStartTime, - MerkleLT.TrancheWithPercentage[] tranchesWithPercentages, - uint256 totalDuration, - uint256 aggregateAmount, - uint256 recipientCount, - uint256 sablierFee - ); - - /// @notice Emitted when the admin resets Sablier fee to default for a specific user. - event ResetSablierFee(address indexed admin, address indexed campaignCreator); - - /// @notice Emitted when the default Sablier fee is set by the admin. - event SetDefaultSablierFee(address indexed admin, uint256 defaultSablierFee); - - /// @notice Emitted when the admin sets Sablier fee for a specific user. - event SetSablierFeeForUser(address indexed admin, address indexed campaignCreator, uint256 sablierFee); - - /// @notice Emitted when the Sablier fees are claimed by the Sablier admin. - event WithdrawSablierFees( - address indexed admin, ISablierMerkleBase indexed merkleBase, address to, uint256 sablierFees - ); - - /*////////////////////////////////////////////////////////////////////////// - CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Verifies if the sum of percentages in `tranches` equals 100% , i.e. 1e18. - /// @dev Reverts if the sum of percentages overflows. - /// @param tranches The tranches with their respective unlock percentages. - /// @return result True if the sum of percentages equals 100%, otherwise false. - function isPercentagesSum100(MerkleLT.TrancheWithPercentage[] calldata tranches) - external - pure - returns (bool result); - - /// @notice Retrieves the default Sablier fee required to claim an airstream. - /// @dev A minimum of this fee must be paid in ETH during {SablierMerkleBase.claim}. - function defaultSablierFee() external view returns (uint256); - - /// @notice Retrieves the custom Sablier fee struct for a specified campaign creator. - /// @param campaignCreator the address of the user for whom the details are being retrieved. - function sablierFeeByUser(address campaignCreator) external view returns (MerkleFactory.SablierFeeByUser memory); - - /*////////////////////////////////////////////////////////////////////////// - NON-CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Creates a new MerkleInstant campaign for instant distribution of assets. - /// - /// @dev Emits a {CreateMerkleInstant} event. - /// - /// Notes: - /// - The MerkleInstant contract is created with CREATE2. - /// - The immutable Sablier fee will be set to the default value unless a custom fee is set. - /// - /// @param baseParams Struct encapsulating the {SablierMerkleBase} parameters, which are documented in - /// {DataTypes}. - /// @param aggregateAmount The total amount of ERC-20 assets to be distributed to all recipients. - /// @param recipientCount The total number of recipients who are eligible to claim. - /// @return merkleInstant The address of the newly created MerkleInstant contract. - function createMerkleInstant( - MerkleBase.ConstructorParams memory baseParams, - uint256 aggregateAmount, - uint256 recipientCount - ) - external - returns (ISablierMerkleInstant merkleInstant); - - /// @notice Creates a new Merkle Lockup campaign with a Lockup Linear distribution. - /// - /// @dev Emits a {CreateMerkleLL} event. - /// - /// Notes: - /// - The MerkleLL contract is created with CREATE2. - /// - The immutable Sablier fee will be set to the default value unless a custom fee is set. - /// - /// @param baseParams Struct encapsulating the {SablierMerkleBase} parameters, which are documented in - /// {DataTypes}. - /// @param lockup The address of the {SablierLockup} contract. - /// @param cancelable Indicates if the stream will be cancelable after claiming. - /// @param transferable Indicates if the stream will be transferable after claiming. - /// @param schedule Struct encapsulating the unlocks schedule, which are documented in {DataTypes}. - /// @param aggregateAmount The total amount of ERC-20 assets to be distributed to all recipients. - /// @param recipientCount The total number of recipients who are eligible to claim. - /// @return merkleLL The address of the newly created Merkle Lockup contract. - function createMerkleLL( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - MerkleLL.Schedule memory schedule, - uint256 aggregateAmount, - uint256 recipientCount - ) - external - returns (ISablierMerkleLL merkleLL); - - /// @notice Creates a new Merkle Lockup campaign with a Lockup Tranched distribution. - /// - /// @dev Emits a {CreateMerkleLT} event. - /// - /// Notes: - /// - The MerkleLT contract is created with CREATE2. - /// - The immutable Sablier fee will be set to the default value unless a custom fee is set. - /// - /// @param baseParams Struct encapsulating the {SablierMerkleBase} parameters, which are documented in - /// {DataTypes}. - /// @param lockup The address of the {SablierLockup} contract. - /// @param cancelable Indicates if the stream will be cancelable after claiming. - /// @param transferable Indicates if the stream will be transferable after claiming. - /// @param streamStartTime The start time of the streams created through {SablierMerkleBase.claim}. - /// @param tranchesWithPercentages The tranches with their respective unlock percentages. - /// @param aggregateAmount The total amount of ERC-20 assets to be distributed to all recipients. - /// @param recipientCount The total number of recipients who are eligible to claim. - /// @return merkleLT The address of the newly created Merkle Lockup contract. - function createMerkleLT( - MerkleBase.ConstructorParams memory baseParams, - ISablierLockup lockup, - bool cancelable, - bool transferable, - uint40 streamStartTime, - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages, - uint256 aggregateAmount, - uint256 recipientCount - ) - external - returns (ISablierMerkleLT merkleLT); - - /// @notice Resets the Sablier fee to default. - /// @dev Emits a {ResetSablierFee} event. - /// - /// Notes: - /// - The default fee will only be applied to the future campaigns. - /// - /// Requirements: - /// - msg.sender must be the admin. - /// - /// @param campaignCreator The user for whom the fee is being reset for. - function resetSablierFeeByUser(address campaignCreator) external; - - /// @notice Sets the custom Sablier fee for a campaign creator. - /// @dev Emits a {SetSablierFee} event. - /// - /// Notes: - /// - The new fee will only be applied to the future campaigns. - /// - /// Requirements: - /// - msg.sender must be the admin. - /// - /// @param campaignCreator The user for whom the fee is being set. - /// @param fee The new fee to be set. - function setSablierFeeByUser(address campaignCreator, uint256 fee) external; - - /// @notice Sets the default Sablier fee for claiming an airstream. - /// @dev Emits a {SetDefaultSablierFee} event. - /// - /// Notes: - /// - The new default fee will only be applied to the future campaigns and will not affect the ones already - /// deployed. - /// - /// Requirements: - /// - msg.sender must be the admin. - /// - /// @param defaultFee The new detault fee to be set. - function setDefaultSablierFee(uint256 defaultFee) external; - - /// @notice Withdraws the Sablier fees accrued on `merkleBase` contract. - /// @dev Emits a {WithdrawSablierFees} event. - /// - /// Notes: - /// - This function transfers ETH to the provided address. If the receiver is a contract, it must be able to receive - /// ETH. - /// - /// Requirements: - /// - msg.sender must be the admin. - /// - `to` must not be the zero address. - /// - /// @param to The address to receive the Sablier fees. - function withdrawFees(address payable to, ISablierMerkleBase merkleBase) external; -} diff --git a/src/periphery/interfaces/ISablierMerkleInstant.sol b/src/periphery/interfaces/ISablierMerkleInstant.sol deleted file mode 100644 index 002aa2aeb..000000000 --- a/src/periphery/interfaces/ISablierMerkleInstant.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { ISablierMerkleBase } from "./ISablierMerkleBase.sol"; - -/// @title ISablierMerkleInstant -/// @notice MerkleInstant enables instant airdrop campaigns. -interface ISablierMerkleInstant is ISablierMerkleBase { - /*////////////////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Emitted when a recipient claims an instant airdrop. - event Claim(uint256 index, address indexed recipient, uint128 amount); -} diff --git a/src/periphery/interfaces/ISablierMerkleLL.sol b/src/periphery/interfaces/ISablierMerkleLL.sol deleted file mode 100644 index 5428288ec..000000000 --- a/src/periphery/interfaces/ISablierMerkleLL.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { ISablierLockup } from "../../core/interfaces/ISablierLockup.sol"; - -import { ISablierMerkleBase } from "./ISablierMerkleBase.sol"; - -/// @title ISablierMerkleLL -/// @notice Merkle Lockup campaign that creates Lockup Linear streams. -interface ISablierMerkleLL is ISablierMerkleBase { - /*////////////////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Emitted when a recipient claims a stream. - event Claim(uint256 index, address indexed recipient, uint128 amount, uint256 indexed streamId); - - /*////////////////////////////////////////////////////////////////////////// - CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice A flag indicating whether the streams can be canceled. - /// @dev This is an immutable state variable. - function CANCELABLE() external returns (bool); - - /// @notice The address of the {SablierLockup} contract. - function LOCKUP() external view returns (ISablierLockup); - - /// @notice A flag indicating whether the stream NFTs are transferable. - /// @dev This is an immutable state variable. - function TRANSFERABLE() external returns (bool); - - /// @notice The start time, start unlock amount, cliff duration, cliff unclock amount and the end duration used to - /// calculate the time variables in `Lockup.CreateWithTimestampsLL`. - /// @dev A start time value of zero will be considered as `block.timestamp`. - function schedule() - external - view - returns (uint40 startTime, uint128 startAmount, uint40 cliffDuration, uint128 cliffAmount, uint40 endDuration); -} diff --git a/src/periphery/interfaces/ISablierMerkleLT.sol b/src/periphery/interfaces/ISablierMerkleLT.sol deleted file mode 100644 index 450c85288..000000000 --- a/src/periphery/interfaces/ISablierMerkleLT.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { ISablierLockup } from "./../../core/interfaces/ISablierLockup.sol"; -import { MerkleLT } from "./../types/DataTypes.sol"; -import { ISablierMerkleBase } from "./ISablierMerkleBase.sol"; - -/// @title ISablierMerkleLT -/// @notice Merkle Lockup campaign that creates Lockup Tranched streams. -interface ISablierMerkleLT is ISablierMerkleBase { - /*////////////////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Emitted when a recipient claims a stream. - event Claim(uint256 index, address indexed recipient, uint128 amount, uint256 indexed streamId); - - /*////////////////////////////////////////////////////////////////////////// - CONSTANT FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice A flag indicating whether the streams can be canceled. - /// @dev This is an immutable state variable. - function CANCELABLE() external returns (bool); - - /// @notice The address of the {SablierLockup} contract. - function LOCKUP() external view returns (ISablierLockup); - - /// @notice The start time of the streams created through {SablierMerkleBase.claim} function. - /// @dev A start time value of zero will be considered as `block.timestamp`. - function STREAM_START_TIME() external returns (uint40); - - /// @notice The total percentage of the tranches. - function TOTAL_PERCENTAGE() external view returns (uint64); - - /// @notice A flag indicating whether the stream NFTs are transferable. - /// @dev This is an immutable state variable. - function TRANSFERABLE() external returns (bool); - - /// @notice Retrieves the tranches with their respective unlock percentages and durations. - function getTranchesWithPercentages() external view returns (MerkleLT.TrancheWithPercentage[] memory); -} diff --git a/src/periphery/libraries/Errors.sol b/src/periphery/libraries/Errors.sol deleted file mode 100644 index 885135822..000000000 --- a/src/periphery/libraries/Errors.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -/// @title Errors -/// @notice Library containing all custom errors the protocol may revert with. -library Errors { - /*////////////////////////////////////////////////////////////////////////// - SABLIER-MERKLE-FACTORY - //////////////////////////////////////////////////////////////////////////*/ - - error SablierMerkleFactory_WithdrawToZeroAddress(); - - /*////////////////////////////////////////////////////////////////////////// - SABLIER-MERKLE-BASE - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Thrown when caller is not the factory contract. - error SablierMerkleBase_CallerNotFactory(address factory, address caller); - - /// @notice Thrown when trying to claim after the campaign has expired. - error SablierMerkleBase_CampaignExpired(uint256 blockTimestamp, uint40 expiration); - - /// @notice Thrown when trying to create a campaign with a name that is too long. - error SablierMerkleBase_CampaignNameTooLong(uint256 nameLength, uint256 maxLength); - - /// @notice Thrown when trying to clawback when the current timestamp is over the grace period and the campaign has - /// not expired. - error SablierMerkleBase_ClawbackNotAllowed(uint256 blockTimestamp, uint40 expiration, uint40 firstClaimTime); - - /// @notice Thrown if the Sablier fees withdraw failed. - error SablierMerkleBase_FeeWithdrawFailed(address to, uint256 amount); - - /// @notice Thrown when trying to claim with an insufficient fee payment. - error SablierMerkleBase_InsufficientFeePayment(uint256 feePaid, uint256 sablierFee); - - /// @notice Thrown when trying to claim with an invalid Merkle proof. - error SablierMerkleBase_InvalidProof(); - - /// @notice Thrown when trying to claim the same stream more than once. - error SablierMerkleBase_StreamClaimed(uint256 index); - - /*////////////////////////////////////////////////////////////////////////// - SABLIER-MERKLE-LT - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Thrown when trying to claim from an LT campaign with tranches' unlock percentages not adding up to 100%. - error SablierMerkleLT_TotalPercentageNotOneHundred(uint64 totalPercentage); -} diff --git a/src/periphery/types/DataTypes.sol b/src/periphery/types/DataTypes.sol deleted file mode 100644 index 6dbb22d24..000000000 --- a/src/periphery/types/DataTypes.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { UD2x18 } from "@prb/math/src/UD2x18.sol"; - -library MerkleBase { - /// @notice Struct encapsulating the base constructor parameters of a Merkle campaign. - /// @param asset The contract address of the ERC-20 asset to be distributed. - /// @param expiration The expiration of the campaign, as a Unix timestamp. - /// @param initialAdmin The initial admin of the campaign. - /// @param ipfsCID The content identifier for indexing the contract on IPFS. - /// @param merkleRoot The Merkle root of the claim data. - /// @param name The name of the campaign. - struct ConstructorParams { - IERC20 asset; - uint40 expiration; - address initialAdmin; - string ipfsCID; - bytes32 merkleRoot; - string name; - } -} - -library MerkleFactory { - /// @notice Struct encapsulating the custom fee details for a given campaign creator. - /// @param enabled Whether the fee is enabled. If false, the default fee will be applied for campaigns created by - /// the given creator. - /// @param fee The fee amount. - struct SablierFeeByUser { - bool enabled; - uint256 fee; - } -} - -library MerkleLL { - /// @notice Struct encapsulating the start time, cliff duration and the end duration used to construct the time - /// variables in `Lockup.CreateWithTimestampsLL`. - /// @dev A start time value of zero will be considered as `block.timestamp`. - /// @param startTime The start time of the stream. - /// @param startAmount The amount to be unlocked at the start time. - /// @param cliffDuration The duration of the cliff. - /// @param cliffAmount The amount to be unlocked at the cliff time. - /// @param totalDuration The total duration of the stream. - struct Schedule { - uint40 startTime; - uint128 startAmount; - uint40 cliffDuration; - uint128 cliffAmount; - uint40 totalDuration; - } -} - -library MerkleLT { - /// @notice Struct encapsulating the unlock percentage and duration of a tranche. - /// @dev Since users may have different amounts allocated, this struct makes it possible to calculate the amounts - /// at claim time. An 18-decimal format is used to represent percentages: 100% = 1e18. For more information, see - /// the PRBMath documentation on UD2x18: https://github.com/PaulRBerg/prb-math - /// @param unlockPercentage The percentage designated to be unlocked in this tranche. - /// @param duration The time difference in seconds between this tranche and the previous one. - struct TrancheWithPercentage { - // slot 0 - UD2x18 unlockPercentage; - uint40 duration; - } -} diff --git a/src/core/types/DataTypes.sol b/src/types/DataTypes.sol similarity index 100% rename from src/core/types/DataTypes.sol rename to src/types/DataTypes.sol diff --git a/test/Base.t.sol b/test/Base.t.sol index a9855fc04..48f283cf9 100644 --- a/test/Base.t.sol +++ b/test/Base.t.sol @@ -2,18 +2,15 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ILockupNFTDescriptor } from "src/core/interfaces/ILockupNFTDescriptor.sol"; -import { ISablierBatchLockup } from "src/core/interfaces/ISablierBatchLockup.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { LockupNFTDescriptor } from "src/core/LockupNFTDescriptor.sol"; -import { SablierBatchLockup } from "src/core/SablierBatchLockup.sol"; -import { SablierLockup } from "src/core/SablierLockup.sol"; -import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.sol"; -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleInstant } from "src/periphery/interfaces/ISablierMerkleInstant.sol"; -import { ISablierMerkleLL } from "src/periphery/interfaces/ISablierMerkleLL.sol"; -import { ISablierMerkleLT } from "src/periphery/interfaces/ISablierMerkleLT.sol"; -import { SablierMerkleFactory } from "src/periphery/SablierMerkleFactory.sol"; + +import { ILockupNFTDescriptor } from "src/interfaces/ILockupNFTDescriptor.sol"; +import { ISablierBatchLockup } from "src/interfaces/ISablierBatchLockup.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { LockupNFTDescriptor } from "src/LockupNFTDescriptor.sol"; +import { SablierBatchLockup } from "src/SablierBatchLockup.sol"; +import { SablierLockup } from "src/SablierLockup.sol"; +import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/types/DataTypes.sol"; + import { ERC20MissingReturn } from "./mocks/erc20/ERC20MissingReturn.sol"; import { ERC20Mock } from "./mocks/erc20/ERC20Mock.sol"; import { RecipientGood } from "./mocks/Hooks.sol"; @@ -42,10 +39,6 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi ERC20Mock internal dai; Defaults internal defaults; ISablierLockup internal lockup; - ISablierMerkleFactory internal merkleFactory; - ISablierMerkleInstant internal merkleInstant; - ISablierMerkleLL internal merkleLL; - ISablierMerkleLT internal merkleLT; ILockupNFTDescriptor internal nftDescriptor; NFTDescriptorMock internal nftDescriptorMock; Noop internal noop; @@ -83,24 +76,15 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi // Deploy the NFT descriptor mock. nftDescriptorMock = new NFTDescriptorMock(); - // Set the Sablier fee on the Merkle factory. - merkleFactory.setDefaultSablierFee(defaults.DEFAULT_SABLIER_FEE()); - // Create users for testing. users.alice = createUser("Alice"); users.broker = createUser("Broker"); - users.campaignOwner = createUser("CampaignOwner"); users.eve = createUser("Eve"); users.operator = createUser("Operator"); users.recipient = createUser("Recipient"); - users.recipient1 = createUser("Recipient1"); - users.recipient2 = createUser("Recipient2"); - users.recipient3 = createUser("Recipient3"); - users.recipient4 = createUser("Recipient4"); users.sender = createUser("Sender"); defaults.setUsers(users); - defaults.initMerkleTree(); // Set the variables in Modifiers contract. setVariables(defaults, users); @@ -132,10 +116,8 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi resetPrank({ msgSender: from }); dai.approve({ spender: address(batchLockup), value: MAX_UINT256 }); dai.approve({ spender: address(lockup), value: MAX_UINT256 }); - dai.approve({ spender: address(merkleFactory), value: MAX_UINT256 }); usdt.approve({ spender: address(batchLockup), value: MAX_UINT256 }); usdt.approve({ spender: address(lockup), value: MAX_UINT256 }); - usdt.approve({ spender: address(merkleFactory), value: MAX_UINT256 }); } /// @dev Generates a user, labels its address, funds it with test assets, and approves the protocol contracts. @@ -158,14 +140,11 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi batchLockup = new SablierBatchLockup(); nftDescriptor = new LockupNFTDescriptor(); lockup = new SablierLockup(users.admin, nftDescriptor, defaults.MAX_COUNT()); - merkleFactory = new SablierMerkleFactory(users.admin); } else { - (nftDescriptor, lockup, batchLockup, merkleFactory) = - deployOptimizedProtocol(users.admin, defaults.MAX_COUNT()); + (nftDescriptor, lockup, batchLockup) = deployOptimizedProtocol(users.admin, defaults.MAX_COUNT()); } vm.label({ account: address(batchLockup), newLabel: "BatchLockup" }); vm.label({ account: address(lockup), newLabel: "Lockup" }); - vm.label({ account: address(merkleFactory), newLabel: "MerkleFactory" }); vm.label({ account: address(nftDescriptor), newLabel: "NFTDescriptor" }); } @@ -224,22 +203,22 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi CALL EXPECTS - LOCKUP //////////////////////////////////////////////////////////////////////////*/ - /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLD}, each with the specified `params`. + /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLD}. function expectMultipleCallsToCreateWithDurationsLD( uint64 count, Lockup.CreateWithDurations memory params, - LockupDynamic.SegmentWithDuration[] memory segments + LockupDynamic.SegmentWithDuration[] memory segmentsWithDuration ) internal { vm.expectCall({ callee: address(lockup), count: count, - data: abi.encodeCall(ISablierLockup.createWithDurationsLD, (params, segments)) + data: abi.encodeCall(ISablierLockup.createWithDurationsLD, (params, segmentsWithDuration)) }); } - /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLL}, each with the specified `params`. + /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLL}. function expectMultipleCallsToCreateWithDurationsLL( uint64 count, Lockup.CreateWithDurations memory params, @@ -255,7 +234,7 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi }); } - /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLT}, each with the specified `params`. + /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLT}. function expectMultipleCallsToCreateWithDurationsLT( uint64 count, Lockup.CreateWithDurations memory params, @@ -270,7 +249,7 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi }); } - /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLD}, each with the specified `params`. + /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLD}. function expectMultipleCallsToCreateWithTimestampsLD( uint64 count, Lockup.CreateWithTimestamps memory params, @@ -285,8 +264,7 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi }); } - /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLL}, each with the specified - /// `params`. + /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLL}. function expectMultipleCallsToCreateWithTimestampsLL( uint64 count, Lockup.CreateWithTimestamps memory params, @@ -302,8 +280,7 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi }); } - /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLT}, each with the specified - /// `params`. + /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLT}. function expectMultipleCallsToCreateWithTimestampsLT( uint64 count, Lockup.CreateWithTimestamps memory params, diff --git a/test/core/fork/Fork.t.sol b/test/fork/Fork.t.sol similarity index 98% rename from test/core/fork/Fork.t.sol rename to test/fork/Fork.t.sol index 04acc8540..f2300bbeb 100644 --- a/test/core/fork/Fork.t.sol +++ b/test/fork/Fork.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Base_Test } from "./../../Base.t.sol"; +import { Base_Test } from "./../Base.t.sol"; /// @notice Common logic needed by all fork tests. abstract contract Fork_Test is Base_Test { diff --git a/test/core/fork/LockupDynamic.t.sol b/test/fork/LockupDynamic.t.sol similarity index 98% rename from test/core/fork/LockupDynamic.t.sol rename to test/fork/LockupDynamic.t.sol index a0d77adfd..d82a3a4cf 100644 --- a/test/core/fork/LockupDynamic.t.sol +++ b/test/fork/LockupDynamic.t.sol @@ -4,9 +4,9 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Broker, Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Broker, Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Fork_Test } from "./Fork.t.sol"; abstract contract Lockup_Dynamic_Fork_Test is Fork_Test { diff --git a/test/core/fork/LockupLinear.t.sol b/test/fork/LockupLinear.t.sol similarity index 98% rename from test/core/fork/LockupLinear.t.sol rename to test/fork/LockupLinear.t.sol index 1efccf6bd..5a0c27eda 100644 --- a/test/core/fork/LockupLinear.t.sol +++ b/test/fork/LockupLinear.t.sol @@ -5,9 +5,9 @@ import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { ud } from "@prb/math/src/UD60x18.sol"; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Broker, Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Broker, Lockup, LockupLinear } from "src/types/DataTypes.sol"; import { Fork_Test } from "./Fork.t.sol"; abstract contract Lockup_Linear_Fork_Test is Fork_Test { diff --git a/test/core/fork/LockupTranched.t.sol b/test/fork/LockupTranched.t.sol similarity index 98% rename from test/core/fork/LockupTranched.t.sol rename to test/fork/LockupTranched.t.sol index 6079cd653..4cad7056f 100644 --- a/test/core/fork/LockupTranched.t.sol +++ b/test/fork/LockupTranched.t.sol @@ -4,9 +4,9 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Broker, Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Broker, Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Fork_Test } from "./Fork.t.sol"; abstract contract Lockup_Tranched_Fork_Test is Fork_Test { diff --git a/test/core/fork/NFTDescriptor.t.sol b/test/fork/NFTDescriptor.t.sol similarity index 98% rename from test/core/fork/NFTDescriptor.t.sol rename to test/fork/NFTDescriptor.t.sol index 4beca5108..0ea8fce46 100644 --- a/test/core/fork/NFTDescriptor.t.sol +++ b/test/fork/NFTDescriptor.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; import { Fork_Test } from "./Fork.t.sol"; @@ -51,7 +51,7 @@ contract NFTDescriptor_Fork_Test is Fork_Test { _; } - /// @dev Loads the Lockup v1.2.0 contracts pre-deployed on Mainnet. + /// @dev Loads the Lockup v1.3.0 contracts pre-deployed on Mainnet. modifier loadDeployments_v1_3_0() { // TODO: Add the deployment addresses for Lockup v1.3.0. // Deploy some streams temporarity for the test diff --git a/test/core/fork/assets/DAI.t.sol b/test/fork/assets/DAI.t.sol similarity index 100% rename from test/core/fork/assets/DAI.t.sol rename to test/fork/assets/DAI.t.sol diff --git a/test/core/fork/assets/EURS.t.sol b/test/fork/assets/EURS.t.sol similarity index 100% rename from test/core/fork/assets/EURS.t.sol rename to test/fork/assets/EURS.t.sol diff --git a/test/core/fork/assets/SHIB.t.sol b/test/fork/assets/SHIB.t.sol similarity index 100% rename from test/core/fork/assets/SHIB.t.sol rename to test/fork/assets/SHIB.t.sol diff --git a/test/core/fork/assets/USDC.t.sol b/test/fork/assets/USDC.t.sol similarity index 100% rename from test/core/fork/assets/USDC.t.sol rename to test/fork/assets/USDC.t.sol diff --git a/test/core/fork/assets/USDT.t.sol b/test/fork/assets/USDT.t.sol similarity index 100% rename from test/core/fork/assets/USDT.t.sol rename to test/fork/assets/USDT.t.sol diff --git a/test/core/integration/Integration.t.sol b/test/integration/Integration.t.sol similarity index 98% rename from test/core/integration/Integration.t.sol rename to test/integration/Integration.t.sol index db6e42f92..01c3a68ba 100644 --- a/test/core/integration/Integration.t.sol +++ b/test/integration/Integration.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/types/DataTypes.sol"; -import { Base_Test } from "../../Base.t.sol"; +import { Base_Test } from "../Base.t.sol"; import { RecipientInterfaceIDIncorrect, RecipientInterfaceIDMissing, RecipientInvalidSelector, RecipientReentrant, RecipientReverting -} from "../../mocks/Hooks.sol"; +} from "../mocks/Hooks.sol"; /// @notice Common logic needed by all integration tests, both concrete and fuzz tests. abstract contract Integration_Test is Base_Test { diff --git a/test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol b/test/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol similarity index 78% rename from test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol rename to test/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol index 895043314..acc01c3e9 100644 --- a/test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol +++ b/test/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { BatchLockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { BatchLockup } from "src/types/DataTypes.sol"; -import { Base_Test } from "test/Base.t.sol"; - -contract CreateWithDurationsLD_Integration_Test is Base_Test { - function setUp() public virtual override { - Base_Test.setUp(); - resetPrank({ msgSender: users.sender }); - } +import { Integration_Test } from "../../../Integration.t.sol"; +contract CreateWithDurationsLD_Integration_Test is Integration_Test { function test_RevertWhen_BatchSizeZero() external { BatchLockup.CreateWithDurationsLD[] memory batchParams = new BatchLockup.CreateWithDurationsLD[](0); vm.expectRevert(Errors.SablierBatchLockup_BatchSizeZero.selector); @@ -26,10 +21,11 @@ contract CreateWithDurationsLD_Integration_Test is Base_Test { to: address(batchLockup), value: defaults.TOTAL_TRANSFER_AMOUNT() }); + expectMultipleCallsToCreateWithDurationsLD({ count: defaults.BATCH_SIZE(), params: defaults.createWithDurationsBrokerNull(), - segments: defaults.segmentsWithDurations() + segmentsWithDuration: defaults.segmentsWithDurations() }); expectMultipleCallsToTransferFrom({ count: defaults.BATCH_SIZE(), @@ -38,10 +34,12 @@ contract CreateWithDurationsLD_Integration_Test is Base_Test { value: defaults.DEPOSIT_AMOUNT() }); + uint256 firstStreamId = lockup.nextStreamId(); + // Assert that the batch of streams has been created successfully. uint256[] memory actualStreamIds = batchLockup.createWithDurationsLD(lockup, dai, defaults.batchCreateWithDurationsLD()); - uint256[] memory expectedStreamIds = defaults.incrementalStreamIds(); + uint256[] memory expectedStreamIds = defaults.incrementalStreamIds({ firstStreamId: firstStreamId }); assertEq(actualStreamIds, expectedStreamIds, "stream ids mismatch"); } } diff --git a/test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree b/test/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree similarity index 100% rename from test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree rename to test/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree diff --git a/test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol b/test/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol similarity index 81% rename from test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol rename to test/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol index ae9e846e4..9c9fb203d 100644 --- a/test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol +++ b/test/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { BatchLockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { BatchLockup } from "src/types/DataTypes.sol"; -import { Base_Test } from "test/Base.t.sol"; - -contract CreateWithDurationsLL_Integration_Test is Base_Test { - function setUp() public virtual override { - Base_Test.setUp(); - resetPrank({ msgSender: users.sender }); - } +import { Integration_Test } from "../../../Integration.t.sol"; +contract CreateWithDurationsLL_Integration_Test is Integration_Test { function test_RevertWhen_BatchSizeZero() external { BatchLockup.CreateWithDurationsLL[] memory batchParams = new BatchLockup.CreateWithDurationsLL[](0); vm.expectRevert(Errors.SablierBatchLockup_BatchSizeZero.selector); @@ -40,10 +35,12 @@ contract CreateWithDurationsLL_Integration_Test is Base_Test { value: defaults.DEPOSIT_AMOUNT() }); + uint256 firstStreamId = lockup.nextStreamId(); + // Assert that the batch of streams has been created successfully. uint256[] memory actualStreamIds = batchLockup.createWithDurationsLL(lockup, dai, defaults.batchCreateWithDurationsLL()); - uint256[] memory expectedStreamIds = defaults.incrementalStreamIds(); + uint256[] memory expectedStreamIds = defaults.incrementalStreamIds({ firstStreamId: firstStreamId }); assertEq(actualStreamIds, expectedStreamIds, "stream ids mismatch"); } } diff --git a/test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree b/test/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree similarity index 100% rename from test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree rename to test/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree diff --git a/test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol b/test/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol similarity index 81% rename from test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol rename to test/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol index a2f0172d3..8a4fa4cd8 100644 --- a/test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol +++ b/test/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { BatchLockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { BatchLockup } from "src/types/DataTypes.sol"; -import { Base_Test } from "test/Base.t.sol"; - -contract CreateWithDurationsLT_Integration_Test is Base_Test { - function setUp() public virtual override { - Base_Test.setUp(); - resetPrank({ msgSender: users.sender }); - } +import { Integration_Test } from "../../../Integration.t.sol"; +contract CreateWithDurationsLT_Integration_Test is Integration_Test { function test_RevertWhen_BatchSizeZero() external { BatchLockup.CreateWithDurationsLT[] memory batchParams = new BatchLockup.CreateWithDurationsLT[](0); vm.expectRevert(Errors.SablierBatchLockup_BatchSizeZero.selector); @@ -39,10 +34,12 @@ contract CreateWithDurationsLT_Integration_Test is Base_Test { value: defaults.DEPOSIT_AMOUNT() }); + uint256 firstStreamId = lockup.nextStreamId(); + // Assert that the batch of streams has been created successfully. uint256[] memory actualStreamIds = batchLockup.createWithDurationsLT(lockup, dai, defaults.batchCreateWithDurationsLT()); - uint256[] memory expectedStreamIds = defaults.incrementalStreamIds(); + uint256[] memory expectedStreamIds = defaults.incrementalStreamIds({ firstStreamId: firstStreamId }); assertEq(actualStreamIds, expectedStreamIds, "stream ids mismatch"); } } diff --git a/test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree b/test/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree similarity index 100% rename from test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree rename to test/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree diff --git a/test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol b/test/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol similarity index 81% rename from test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol rename to test/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol index b4478106d..72142aa4e 100644 --- a/test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol +++ b/test/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { BatchLockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { BatchLockup } from "src/types/DataTypes.sol"; -import { Base_Test } from "test/Base.t.sol"; - -contract CreateWithTimestampsLD_Integration_Test is Base_Test { - function setUp() public virtual override { - Base_Test.setUp(); - resetPrank({ msgSender: users.sender }); - } +import { Integration_Test } from "../../../Integration.t.sol"; +contract CreateWithTimestampsLD_Integration_Test is Integration_Test { function test_RevertWhen_BatchSizeZero() external { BatchLockup.CreateWithTimestampsLD[] memory batchParams = new BatchLockup.CreateWithTimestampsLD[](0); vm.expectRevert(Errors.SablierBatchLockup_BatchSizeZero.selector); @@ -39,10 +34,12 @@ contract CreateWithTimestampsLD_Integration_Test is Base_Test { value: defaults.DEPOSIT_AMOUNT() }); + uint256 firstStreamId = lockup.nextStreamId(); + // Assert that the batch of streams has been created successfully. uint256[] memory actualStreamIds = batchLockup.createWithTimestampsLD(lockup, dai, defaults.batchCreateWithTimestampsLD()); - uint256[] memory expectedStreamIds = defaults.incrementalStreamIds(); + uint256[] memory expectedStreamIds = defaults.incrementalStreamIds({ firstStreamId: firstStreamId }); assertEq(actualStreamIds, expectedStreamIds, "stream ids mismatch"); } } diff --git a/test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree b/test/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree similarity index 100% rename from test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree rename to test/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree diff --git a/test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol b/test/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol similarity index 81% rename from test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol rename to test/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol index 673719c34..9437ff4ae 100644 --- a/test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol +++ b/test/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { BatchLockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { BatchLockup } from "src/types/DataTypes.sol"; -import { Base_Test } from "test/Base.t.sol"; - -contract CreateWithTimestampsLL_Integration_Test is Base_Test { - function setUp() public virtual override { - Base_Test.setUp(); - resetPrank({ msgSender: users.sender }); - } +import { Integration_Test } from "../../../Integration.t.sol"; +contract CreateWithTimestampsLL_Integration_Test is Integration_Test { function test_RevertWhen_BatchSizeZero() external { BatchLockup.CreateWithTimestampsLL[] memory batchParams = new BatchLockup.CreateWithTimestampsLL[](0); vm.expectRevert(Errors.SablierBatchLockup_BatchSizeZero.selector); @@ -40,10 +35,12 @@ contract CreateWithTimestampsLL_Integration_Test is Base_Test { value: defaults.DEPOSIT_AMOUNT() }); + uint256 firstStreamId = lockup.nextStreamId(); + // Assert that the batch of streams has been created successfully. uint256[] memory actualStreamIds = batchLockup.createWithTimestampsLL(lockup, dai, defaults.batchCreateWithTimestampsLL()); - uint256[] memory expectedStreamIds = defaults.incrementalStreamIds(); + uint256[] memory expectedStreamIds = defaults.incrementalStreamIds({ firstStreamId: firstStreamId }); assertEq(actualStreamIds, expectedStreamIds, "stream ids mismatch"); } } diff --git a/test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree b/test/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree similarity index 100% rename from test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree rename to test/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree diff --git a/test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol b/test/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol similarity index 81% rename from test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol rename to test/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol index c3fea43ef..a83be0993 100644 --- a/test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol +++ b/test/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { BatchLockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { BatchLockup } from "src/types/DataTypes.sol"; -import { Base_Test } from "test/Base.t.sol"; - -contract CreateWithTimestampsLT_Integration_Test is Base_Test { - function setUp() public virtual override { - Base_Test.setUp(); - resetPrank({ msgSender: users.sender }); - } +import { Integration_Test } from "../../../Integration.t.sol"; +contract CreateWithTimestampsLT_Integration_Test is Integration_Test { function test_RevertWhen_BatchSizeZero() external { BatchLockup.CreateWithTimestampsLT[] memory batchParams = new BatchLockup.CreateWithTimestampsLT[](0); vm.expectRevert(Errors.SablierBatchLockup_BatchSizeZero.selector); @@ -39,10 +34,12 @@ contract CreateWithTimestampsLT_Integration_Test is Base_Test { value: defaults.DEPOSIT_AMOUNT() }); + uint256 firstStreamId = lockup.nextStreamId(); + // Assert that the batch of streams has been created successfully. uint256[] memory actualStreamIds = batchLockup.createWithTimestampsLT(lockup, dai, defaults.batchCreateWithTimestampsLT()); - uint256[] memory expectedStreamIds = defaults.incrementalStreamIds(); + uint256[] memory expectedStreamIds = defaults.incrementalStreamIds({ firstStreamId: firstStreamId }); assertEq(actualStreamIds, expectedStreamIds, "stream ids mismatch"); } } diff --git a/test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree b/test/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree similarity index 100% rename from test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree rename to test/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree diff --git a/test/core/integration/concrete/constructor.t.sol b/test/integration/concrete/constructor.t.sol similarity index 94% rename from test/core/integration/concrete/constructor.t.sol rename to test/integration/concrete/constructor.t.sol index 1fe56e3e6..34f97b8b1 100644 --- a/test/core/integration/concrete/constructor.t.sol +++ b/test/integration/concrete/constructor.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22 <0.9.0; import { UD60x18 } from "@prb/math/src/UD60x18.sol"; -import { IAdminable } from "src/core/interfaces/IAdminable.sol"; -import { SablierLockup } from "src/core/SablierLockup.sol"; +import { IAdminable } from "src/interfaces/IAdminable.sol"; +import { SablierLockup } from "src/SablierLockup.sol"; import { Integration_Test } from "../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol b/test/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol similarity index 93% rename from test/core/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol rename to test/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol index cbafeccf1..f4352cd8c 100644 --- a/test/core/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol +++ b/test/integration/concrete/lockup-base/allow-to-hook/allowToHook.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/allow-to-hook/allowToHook.tree b/test/integration/concrete/lockup-base/allow-to-hook/allowToHook.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/allow-to-hook/allowToHook.tree rename to test/integration/concrete/lockup-base/allow-to-hook/allowToHook.tree diff --git a/test/core/integration/concrete/lockup-base/batch/batch.t.sol b/test/integration/concrete/lockup-base/batch/batch.t.sol similarity index 91% rename from test/core/integration/concrete/lockup-base/batch/batch.t.sol rename to test/integration/concrete/lockup-base/batch/batch.t.sol index ad2303b0f..bb1c14e07 100644 --- a/test/core/integration/concrete/lockup-base/batch/batch.t.sol +++ b/test/integration/concrete/lockup-base/batch/batch.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; +import { Errors } from "src/libraries/Errors.sol"; -import { Integration_Test } from "./../../../Integration.t.sol"; +import { Integration_Test } from "../../../Integration.t.sol"; contract Batch_Integration_Concrete_Test is Integration_Test { function test_RevertWhen_CallFunctionNotExist() external { diff --git a/test/core/integration/concrete/lockup-base/batch/batch.tree b/test/integration/concrete/lockup-base/batch/batch.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/batch/batch.tree rename to test/integration/concrete/lockup-base/batch/batch.tree diff --git a/test/core/integration/concrete/lockup-base/burn/burn.t.sol b/test/integration/concrete/lockup-base/burn/burn.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-base/burn/burn.t.sol rename to test/integration/concrete/lockup-base/burn/burn.t.sol index 2dc0d4357..3d0df5184 100644 --- a/test/core/integration/concrete/lockup-base/burn/burn.t.sol +++ b/test/integration/concrete/lockup-base/burn/burn.t.sol @@ -4,8 +4,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC721Errors } from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Integration_Test } from "./../../../Integration.t.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Integration_Test } from "../../../Integration.t.sol"; contract Burn_Integration_Concrete_Test is Integration_Test { function test_RevertWhen_DelegateCall() external { diff --git a/test/core/integration/concrete/lockup-base/burn/burn.tree b/test/integration/concrete/lockup-base/burn/burn.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/burn/burn.tree rename to test/integration/concrete/lockup-base/burn/burn.tree diff --git a/test/core/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol b/test/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol rename to test/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol index 796709a23..57c5f5379 100644 --- a/test/core/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol +++ b/test/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.t.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.22 <0.9.0; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.tree b/test/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.tree rename to test/integration/concrete/lockup-base/cancel-multiple/cancelMultiple.tree diff --git a/test/core/integration/concrete/lockup-base/cancel/cancel.t.sol b/test/integration/concrete/lockup-base/cancel/cancel.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-base/cancel/cancel.t.sol rename to test/integration/concrete/lockup-base/cancel/cancel.t.sol index c62440605..7a0c0bd55 100644 --- a/test/core/integration/concrete/lockup-base/cancel/cancel.t.sol +++ b/test/integration/concrete/lockup-base/cancel/cancel.t.sol @@ -3,10 +3,10 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { ISablierLockupRecipient } from "src/core/interfaces/ISablierLockupRecipient.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { ISablierLockupRecipient } from "src/interfaces/ISablierLockupRecipient.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/cancel/cancel.tree b/test/integration/concrete/lockup-base/cancel/cancel.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/cancel/cancel.tree rename to test/integration/concrete/lockup-base/cancel/cancel.tree diff --git a/test/core/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol b/test/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol rename to test/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol index 01075b9d1..e15543337 100644 --- a/test/core/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol +++ b/test/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.t.sol @@ -5,9 +5,9 @@ import { IERC721Errors } from "@openzeppelin/contracts/interfaces/draft-IERC6093 import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { UD60x18, ud } from "@prb/math/src/UD60x18.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; -import { Integration_Test } from "./../../../Integration.t.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; +import { Integration_Test } from "../../../Integration.t.sol"; abstract contract CreateWithTimestamps_Integration_Concrete_Test is Integration_Test { /*////////////////////////////////////////////////////////////////////////// diff --git a/test/core/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.tree b/test/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.tree rename to test/integration/concrete/lockup-base/create-with-timestamps/createWithTimestamps.tree diff --git a/test/core/integration/concrete/lockup-base/getters/getters.t.sol b/test/integration/concrete/lockup-base/getters/getters.t.sol similarity index 99% rename from test/core/integration/concrete/lockup-base/getters/getters.t.sol rename to test/integration/concrete/lockup-base/getters/getters.t.sol index ea1b1315c..b094b7d7a 100644 --- a/test/core/integration/concrete/lockup-base/getters/getters.t.sol +++ b/test/integration/concrete/lockup-base/getters/getters.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC721Errors } from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Integration_Test } from "./../../../Integration.t.sol"; +import { Integration_Test } from "../../../Integration.t.sol"; contract Getters_Integration_Concrete_Test is Integration_Test { /*////////////////////////////////////////////////////////////////////////// diff --git a/test/core/integration/concrete/lockup-base/getters/getters.tree b/test/integration/concrete/lockup-base/getters/getters.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/getters/getters.tree rename to test/integration/concrete/lockup-base/getters/getters.tree diff --git a/test/core/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.t.sol b/test/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.t.sol similarity index 100% rename from test/core/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.t.sol rename to test/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.t.sol diff --git a/test/core/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.tree b/test/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.tree rename to test/integration/concrete/lockup-base/refundable-amount-of/refundableAmountOf.tree diff --git a/test/core/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol b/test/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol rename to test/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol index 6648b0951..5007d5c0c 100644 --- a/test/core/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol +++ b/test/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.t.sol @@ -4,8 +4,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.tree b/test/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.tree rename to test/integration/concrete/lockup-base/renounce-multiple/renounceMultiple.tree diff --git a/test/core/integration/concrete/lockup-base/renounce/renounce.t.sol b/test/integration/concrete/lockup-base/renounce/renounce.t.sol similarity index 95% rename from test/core/integration/concrete/lockup-base/renounce/renounce.t.sol rename to test/integration/concrete/lockup-base/renounce/renounce.t.sol index d94e5143b..d3eede3e4 100644 --- a/test/core/integration/concrete/lockup-base/renounce/renounce.t.sol +++ b/test/integration/concrete/lockup-base/renounce/renounce.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/renounce/renounce.tree b/test/integration/concrete/lockup-base/renounce/renounce.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/renounce/renounce.tree rename to test/integration/concrete/lockup-base/renounce/renounce.tree diff --git a/test/core/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol b/test/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol similarity index 86% rename from test/core/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol rename to test/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol index d0c048827..431017b39 100644 --- a/test/core/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol +++ b/test/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.t.sol @@ -2,11 +2,11 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ILockupNFTDescriptor } from "src/core/interfaces/ILockupNFTDescriptor.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { LockupNFTDescriptor } from "src/core/LockupNFTDescriptor.sol"; -import { Integration_Test } from "./../../../Integration.t.sol"; +import { ILockupNFTDescriptor } from "src/interfaces/ILockupNFTDescriptor.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { LockupNFTDescriptor } from "src/LockupNFTDescriptor.sol"; +import { Integration_Test } from "../../../Integration.t.sol"; contract SetNFTDescriptor_Integration_Concrete_Test is Integration_Test { function test_RevertWhen_CallerNotAdmin() external { diff --git a/test/core/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.tree b/test/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.tree rename to test/integration/concrete/lockup-base/set-nft-descriptor/setNFTDescriptor.tree diff --git a/test/core/integration/concrete/lockup-base/status-of/statusOf.t.sol b/test/integration/concrete/lockup-base/status-of/statusOf.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-base/status-of/statusOf.t.sol rename to test/integration/concrete/lockup-base/status-of/statusOf.t.sol index 8196874a2..f54ed0828 100644 --- a/test/core/integration/concrete/lockup-base/status-of/statusOf.t.sol +++ b/test/integration/concrete/lockup-base/status-of/statusOf.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/status-of/statusOf.tree b/test/integration/concrete/lockup-base/status-of/statusOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/status-of/statusOf.tree rename to test/integration/concrete/lockup-base/status-of/statusOf.tree diff --git a/test/core/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.t.sol b/test/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.t.sol similarity index 100% rename from test/core/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.t.sol rename to test/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.t.sol diff --git a/test/core/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.tree b/test/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.tree rename to test/integration/concrete/lockup-base/streamed-amount-of/streamedAmountOf.tree diff --git a/test/core/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol b/test/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol rename to test/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol index a2f0e7558..6ceb88a94 100644 --- a/test/core/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol +++ b/test/integration/concrete/lockup-base/transfer-from/transferFrom.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/transfer-from/transferFrom.tree b/test/integration/concrete/lockup-base/transfer-from/transferFrom.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/transfer-from/transferFrom.tree rename to test/integration/concrete/lockup-base/transfer-from/transferFrom.tree diff --git a/test/core/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol b/test/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol similarity index 98% rename from test/core/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol rename to test/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol index 63ce59d37..8a8363556 100644 --- a/test/core/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol +++ b/test/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockupRecipient } from "src/core/interfaces/ISablierLockupRecipient.sol"; +import { ISablierLockupRecipient } from "src/interfaces/ISablierLockupRecipient.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.tree b/test/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.tree rename to test/integration/concrete/lockup-base/withdraw-hooks/withdrawHooks.tree diff --git a/test/core/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol b/test/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol rename to test/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol index fe3e1c0ac..0881ca580 100644 --- a/test/core/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol +++ b/test/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.t.sol @@ -5,9 +5,9 @@ import { IERC721Errors } from "@openzeppelin/contracts/interfaces/draft-IERC6093 import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Integration_Test } from "./../../../Integration.t.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Integration_Test } from "../../../Integration.t.sol"; contract WithdrawMaxAndTransfer_Integration_Concrete_Test is Integration_Test { function test_RevertWhen_DelegateCall() external { diff --git a/test/core/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree b/test/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree rename to test/integration/concrete/lockup-base/withdraw-max-and-transfer/withdrawMaxAndTransfer.tree diff --git a/test/core/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol b/test/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol rename to test/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol index d34366a84..4757be1bd 100644 --- a/test/core/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol +++ b/test/integration/concrete/lockup-base/withdraw-max/withdrawMax.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/withdraw-max/withdrawMax.tree b/test/integration/concrete/lockup-base/withdraw-max/withdrawMax.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/withdraw-max/withdrawMax.tree rename to test/integration/concrete/lockup-base/withdraw-max/withdrawMax.tree diff --git a/test/core/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol b/test/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol rename to test/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol index 8a96bfaf0..2a00ccd30 100644 --- a/test/core/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol +++ b/test/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.t.sol @@ -2,9 +2,9 @@ pragma solidity >=0.8.22 <0.9.0; import { Solarray } from "solarray/src/Solarray.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.tree b/test/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.tree rename to test/integration/concrete/lockup-base/withdraw-multiple/withdrawMultiple.tree diff --git a/test/core/integration/concrete/lockup-base/withdraw/withdraw.t.sol b/test/integration/concrete/lockup-base/withdraw/withdraw.t.sol similarity index 98% rename from test/core/integration/concrete/lockup-base/withdraw/withdraw.t.sol rename to test/integration/concrete/lockup-base/withdraw/withdraw.t.sol index 36e2dae7b..1a2a800f0 100644 --- a/test/core/integration/concrete/lockup-base/withdraw/withdraw.t.sol +++ b/test/integration/concrete/lockup-base/withdraw/withdraw.t.sol @@ -3,10 +3,10 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { ISablierLockupRecipient } from "src/core/interfaces/ISablierLockupRecipient.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { ISablierLockupRecipient } from "src/interfaces/ISablierLockupRecipient.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../../Integration.t.sol"; diff --git a/test/core/integration/concrete/lockup-base/withdraw/withdraw.tree b/test/integration/concrete/lockup-base/withdraw/withdraw.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/withdraw/withdraw.tree rename to test/integration/concrete/lockup-base/withdraw/withdraw.tree diff --git a/test/core/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol b/test/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol similarity index 100% rename from test/core/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol rename to test/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol diff --git a/test/core/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.tree b/test/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.tree rename to test/integration/concrete/lockup-base/withdrawable-amount-of/withdrawableAmountOf.tree diff --git a/test/core/integration/concrete/lockup-dynamic/LockupDynamic.t.sol b/test/integration/concrete/lockup-dynamic/LockupDynamic.t.sol similarity index 80% rename from test/core/integration/concrete/lockup-dynamic/LockupDynamic.t.sol rename to test/integration/concrete/lockup-dynamic/LockupDynamic.t.sol index b823a7788..c156a9890 100644 --- a/test/core/integration/concrete/lockup-dynamic/LockupDynamic.t.sol +++ b/test/integration/concrete/lockup-dynamic/LockupDynamic.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; -import { Integration_Test } from "./../../Integration.t.sol"; -import { Cancel_Integration_Concrete_Test } from "./../lockup-base/cancel/cancel.t.sol"; +import { Integration_Test } from "../../Integration.t.sol"; +import { Cancel_Integration_Concrete_Test } from "../lockup-base/cancel/cancel.t.sol"; import { RefundableAmountOf_Integration_Concrete_Test } from - "./../lockup-base/refundable-amount-of/refundableAmountOf.t.sol"; -import { Renounce_Integration_Concrete_Test } from "./../lockup-base/renounce/renounce.t.sol"; -import { Withdraw_Integration_Concrete_Test } from "./../lockup-base/withdraw/withdraw.t.sol"; + "../lockup-base/refundable-amount-of/refundableAmountOf.t.sol"; +import { Renounce_Integration_Concrete_Test } from "../lockup-base/renounce/renounce.t.sol"; +import { Withdraw_Integration_Concrete_Test } from "../lockup-base/withdraw/withdraw.t.sol"; abstract contract Lockup_Dynamic_Integration_Concrete_Test is Integration_Test { function setUp() public virtual override { diff --git a/test/core/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol b/test/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol rename to test/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol index 92fb5ee28..1463eee53 100644 --- a/test/core/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol +++ b/test/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.t.sol @@ -4,9 +4,9 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { ud2x18 } from "@prb/math/src/UD2x18.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Lockup_Dynamic_Integration_Concrete_Test } from "../LockupDynamic.t.sol"; diff --git a/test/core/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.tree b/test/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.tree similarity index 100% rename from test/core/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.tree rename to test/integration/concrete/lockup-dynamic/create-with-durations-ld/createWithDurationsLD.tree diff --git a/test/core/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol b/test/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol similarity index 98% rename from test/core/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol rename to test/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol index f2c12f801..9499f8007 100644 --- a/test/core/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol +++ b/test/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.t.sol @@ -5,9 +5,9 @@ import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { stdError } from "forge-std/src/StdError.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { CreateWithTimestamps_Integration_Concrete_Test, diff --git a/test/core/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.tree b/test/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.tree similarity index 100% rename from test/core/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.tree rename to test/integration/concrete/lockup-dynamic/create-with-timestamps-ld/createWithTimestampsLD.tree diff --git a/test/core/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol b/test/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol similarity index 89% rename from test/core/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol rename to test/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol index a8c17056e..2b00d0e88 100644 --- a/test/core/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol +++ b/test/integration/concrete/lockup-dynamic/get-segments/getSegments.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Lockup_Dynamic_Integration_Concrete_Test } from "../LockupDynamic.t.sol"; diff --git a/test/core/integration/concrete/lockup-dynamic/get-segments/getSegments.tree b/test/integration/concrete/lockup-dynamic/get-segments/getSegments.tree similarity index 100% rename from test/core/integration/concrete/lockup-dynamic/get-segments/getSegments.tree rename to test/integration/concrete/lockup-dynamic/get-segments/getSegments.tree diff --git a/test/core/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol b/test/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol similarity index 91% rename from test/core/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol rename to test/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol index 0695eeb52..ae3073043 100644 --- a/test/core/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol +++ b/test/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.t.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { LockupDynamic } from "src/core/types/DataTypes.sol"; -import { StreamedAmountOf_Integration_Concrete_Test } from - "./../../lockup-base/streamed-amount-of/streamedAmountOf.t.sol"; +import { LockupDynamic } from "src/types/DataTypes.sol"; +import { StreamedAmountOf_Integration_Concrete_Test } from "../../lockup-base/streamed-amount-of/streamedAmountOf.t.sol"; import { Lockup_Dynamic_Integration_Concrete_Test, Integration_Test } from "../LockupDynamic.t.sol"; contract StreamedAmountOf_Lockup_Dynamic_Integration_Concrete_Test is diff --git a/test/core/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.tree b/test/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.tree rename to test/integration/concrete/lockup-dynamic/streamed-amount-of/streamedAmountOf.tree diff --git a/test/core/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol b/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol similarity index 99% rename from test/core/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol rename to test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol index 82eefe9b8..895a3c5dc 100644 --- a/test/core/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol +++ b/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.t.sol @@ -7,7 +7,7 @@ import { console2 } from "forge-std/src/console2.sol"; import { StdStyle } from "forge-std/src/StdStyle.sol"; import { Base64 } from "solady/src/utils/Base64.sol"; -import { Integration_Test } from "test/core/integration/Integration.t.sol"; +import { Integration_Test } from "test/integration/Integration.t.sol"; /// @dev Requirements for these tests to work: /// - The stream ID must be 1 diff --git a/test/core/integration/concrete/lockup-dynamic/token-uri/tokenURI.tree b/test/integration/concrete/lockup-dynamic/token-uri/tokenURI.tree similarity index 100% rename from test/core/integration/concrete/lockup-dynamic/token-uri/tokenURI.tree rename to test/integration/concrete/lockup-dynamic/token-uri/tokenURI.tree diff --git a/test/core/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol b/test/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol rename to test/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol index 5663bc4e0..b10aff093 100644 --- a/test/core/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol +++ b/test/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; import { WithdrawableAmountOf_Integration_Concrete_Test } from - "./../../lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol"; + "../../lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol"; import { Lockup_Dynamic_Integration_Concrete_Test, Integration_Test } from "../LockupDynamic.t.sol"; contract WithdrawableAmountOf_Lockup_Dynamic_Integration_Concrete_Test is diff --git a/test/core/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.tree b/test/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.tree rename to test/integration/concrete/lockup-dynamic/withdrawable-amount-of/withdrawableAmountOf.tree diff --git a/test/core/integration/concrete/lockup-linear/LockupLinear.t.sol b/test/integration/concrete/lockup-linear/LockupLinear.t.sol similarity index 80% rename from test/core/integration/concrete/lockup-linear/LockupLinear.t.sol rename to test/integration/concrete/lockup-linear/LockupLinear.t.sol index 66a56180d..c91be3585 100644 --- a/test/core/integration/concrete/lockup-linear/LockupLinear.t.sol +++ b/test/integration/concrete/lockup-linear/LockupLinear.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; -import { Integration_Test } from "./../../Integration.t.sol"; -import { Cancel_Integration_Concrete_Test } from "./../lockup-base/cancel/cancel.t.sol"; +import { Integration_Test } from "../../Integration.t.sol"; +import { Cancel_Integration_Concrete_Test } from "../lockup-base/cancel/cancel.t.sol"; import { RefundableAmountOf_Integration_Concrete_Test } from - "./../lockup-base/refundable-amount-of/refundableAmountOf.t.sol"; -import { Renounce_Integration_Concrete_Test } from "./../lockup-base/renounce/renounce.t.sol"; -import { Withdraw_Integration_Concrete_Test } from "./../lockup-base/withdraw/withdraw.t.sol"; + "../lockup-base/refundable-amount-of/refundableAmountOf.t.sol"; +import { Renounce_Integration_Concrete_Test } from "../lockup-base/renounce/renounce.t.sol"; +import { Withdraw_Integration_Concrete_Test } from "../lockup-base/withdraw/withdraw.t.sol"; abstract contract Lockup_Linear_Integration_Concrete_Test is Integration_Test { function setUp() public virtual override { diff --git a/test/core/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol b/test/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol rename to test/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol index 1e6cbcfd1..69084ea91 100644 --- a/test/core/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol +++ b/test/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.t.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupLinear } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Concrete_Test } from "../LockupLinear.t.sol"; diff --git a/test/core/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.tree b/test/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.tree rename to test/integration/concrete/lockup-linear/create-with-durations-ll/createWithDurationsLL.tree diff --git a/test/core/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol b/test/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol rename to test/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol index ee3ac6897..8689259f0 100644 --- a/test/core/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol +++ b/test/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.t.sol @@ -4,9 +4,9 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { CreateWithTimestamps_Integration_Concrete_Test, diff --git a/test/core/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.tree b/test/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.tree rename to test/integration/concrete/lockup-linear/create-with-timestamps-ll/createWithTimestampsLL.tree diff --git a/test/core/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol b/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol similarity index 90% rename from test/core/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol rename to test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol index 3888145b8..62e370f51 100644 --- a/test/core/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol +++ b/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Concrete_Test } from "../LockupLinear.t.sol"; diff --git a/test/core/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree b/test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree rename to test/integration/concrete/lockup-linear/get-cliff-time/getCliffTime.tree diff --git a/test/core/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol b/test/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol similarity index 95% rename from test/core/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol rename to test/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol index 24b8b8687..9b96fb96f 100644 --- a/test/core/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol +++ b/test/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupLinear } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Concrete_Test } from "../LockupLinear.t.sol"; diff --git a/test/core/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.tree b/test/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.tree rename to test/integration/concrete/lockup-linear/get-unlock-amounts/getUnlockAmounts.tree diff --git a/test/core/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol b/test/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol rename to test/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol index b15f05761..128039f68 100644 --- a/test/core/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol +++ b/test/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { StreamedAmountOf_Integration_Concrete_Test } from - "./../../lockup-base/streamed-amount-of/streamedAmountOf.t.sol"; +import { StreamedAmountOf_Integration_Concrete_Test } from "../../lockup-base/streamed-amount-of/streamedAmountOf.t.sol"; import { Lockup_Linear_Integration_Concrete_Test, Integration_Test } from "./../LockupLinear.t.sol"; contract StreamedAmountOf_Lockup_Linear_Integration_Concrete_Test is diff --git a/test/core/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.tree b/test/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.tree rename to test/integration/concrete/lockup-linear/streamed-amount-of/streamedAmountOf.tree diff --git a/test/core/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol b/test/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol similarity index 100% rename from test/core/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol rename to test/integration/concrete/lockup-linear/token-uri/tokenURI.t.sol diff --git a/test/core/integration/concrete/lockup-linear/token-uri/tokenURI.tree b/test/integration/concrete/lockup-linear/token-uri/tokenURI.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/token-uri/tokenURI.tree rename to test/integration/concrete/lockup-linear/token-uri/tokenURI.tree diff --git a/test/core/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol b/test/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol similarity index 95% rename from test/core/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol rename to test/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol index 1f705540b..c4c57167b 100644 --- a/test/core/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol +++ b/test/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; import { WithdrawableAmountOf_Integration_Concrete_Test } from - "./../../lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol"; + "../../lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol"; import { Lockup_Linear_Integration_Concrete_Test, Integration_Test } from "./../LockupLinear.t.sol"; contract WithdrawableAmountOf_Lockup_Linear_Integration_Concrete_Test is diff --git a/test/core/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.tree b/test/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.tree rename to test/integration/concrete/lockup-linear/withdrawable-amount-of/withdrawableAmountOf.tree diff --git a/test/core/integration/concrete/lockup-tranched/LockupTranched.t.sol b/test/integration/concrete/lockup-tranched/LockupTranched.t.sol similarity index 80% rename from test/core/integration/concrete/lockup-tranched/LockupTranched.t.sol rename to test/integration/concrete/lockup-tranched/LockupTranched.t.sol index cc39fbcbf..6d57fb04b 100644 --- a/test/core/integration/concrete/lockup-tranched/LockupTranched.t.sol +++ b/test/integration/concrete/lockup-tranched/LockupTranched.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; -import { Integration_Test } from "./../../Integration.t.sol"; -import { Cancel_Integration_Concrete_Test } from "./../lockup-base/cancel/cancel.t.sol"; +import { Integration_Test } from "../../Integration.t.sol"; +import { Cancel_Integration_Concrete_Test } from "../lockup-base/cancel/cancel.t.sol"; import { RefundableAmountOf_Integration_Concrete_Test } from - "./../lockup-base/refundable-amount-of/refundableAmountOf.t.sol"; -import { Renounce_Integration_Concrete_Test } from "./../lockup-base/renounce/renounce.t.sol"; -import { Withdraw_Integration_Concrete_Test } from "./../lockup-base/withdraw/withdraw.t.sol"; + "../lockup-base/refundable-amount-of/refundableAmountOf.t.sol"; +import { Renounce_Integration_Concrete_Test } from "../lockup-base/renounce/renounce.t.sol"; +import { Withdraw_Integration_Concrete_Test } from "../lockup-base/withdraw/withdraw.t.sol"; abstract contract Lockup_Tranched_Integration_Concrete_Test is Integration_Test { function setUp() public virtual override { diff --git a/test/core/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol b/test/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol similarity index 97% rename from test/core/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol rename to test/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol index 319137a4a..f2896f506 100644 --- a/test/core/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol +++ b/test/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.t.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Lockup_Tranched_Integration_Concrete_Test } from "./../LockupTranched.t.sol"; diff --git a/test/core/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.tree b/test/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.tree similarity index 100% rename from test/core/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.tree rename to test/integration/concrete/lockup-tranched/create-with-durations-lt/createWithDurationsLT.tree diff --git a/test/core/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol b/test/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol similarity index 98% rename from test/core/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol rename to test/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol index afc3d8606..5f233593d 100644 --- a/test/core/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol +++ b/test/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.t.sol @@ -5,9 +5,9 @@ import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { stdError } from "forge-std/src/StdError.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { CreateWithTimestamps_Integration_Concrete_Test, diff --git a/test/core/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.tree b/test/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.tree similarity index 100% rename from test/core/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.tree rename to test/integration/concrete/lockup-tranched/create-with-timestamps-lt/createWithTimestampsLT.tree diff --git a/test/core/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol b/test/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol similarity index 89% rename from test/core/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol rename to test/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol index 7929a439f..2c45bfa1c 100644 --- a/test/core/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol +++ b/test/integration/concrete/lockup-tranched/get-tranches/getTranches.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Lockup_Tranched_Integration_Concrete_Test } from "../LockupTranched.t.sol"; diff --git a/test/core/integration/concrete/lockup-tranched/get-tranches/getTranches.tree b/test/integration/concrete/lockup-tranched/get-tranches/getTranches.tree similarity index 100% rename from test/core/integration/concrete/lockup-tranched/get-tranches/getTranches.tree rename to test/integration/concrete/lockup-tranched/get-tranches/getTranches.tree diff --git a/test/core/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol b/test/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol similarity index 94% rename from test/core/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol rename to test/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol index cfe4064cd..08701b044 100644 --- a/test/core/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol +++ b/test/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { StreamedAmountOf_Integration_Concrete_Test } from - "./../../lockup-base/streamed-amount-of/streamedAmountOf.t.sol"; +import { StreamedAmountOf_Integration_Concrete_Test } from "../../lockup-base/streamed-amount-of/streamedAmountOf.t.sol"; import { Lockup_Tranched_Integration_Concrete_Test, Integration_Test } from "./../LockupTranched.t.sol"; contract StreamedAmountOf_Lockup_Tranched_Integration_Concrete_Test is diff --git a/test/core/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.tree b/test/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.tree rename to test/integration/concrete/lockup-tranched/streamed-amount-of/streamedAmountOf.tree diff --git a/test/core/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol b/test/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol similarity index 100% rename from test/core/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol rename to test/integration/concrete/lockup-tranched/token-uri/tokenURI.t.sol diff --git a/test/core/integration/concrete/lockup-tranched/token-uri/tokenURI.tree b/test/integration/concrete/lockup-tranched/token-uri/tokenURI.tree similarity index 100% rename from test/core/integration/concrete/lockup-tranched/token-uri/tokenURI.tree rename to test/integration/concrete/lockup-tranched/token-uri/tokenURI.tree diff --git a/test/core/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol b/test/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol similarity index 96% rename from test/core/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol rename to test/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol index 69ac01fa5..ac159a91a 100644 --- a/test/core/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol +++ b/test/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; import { WithdrawableAmountOf_Integration_Concrete_Test } from - "./../../lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol"; + "../../lockup-base/withdrawable-amount-of/withdrawableAmountOf.t.sol"; import { Lockup_Tranched_Integration_Concrete_Test, Integration_Test } from "./../LockupTranched.t.sol"; contract WithdrawableAmountOf_Lockup_Tranched_Integration_Concrete_Test is diff --git a/test/core/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.tree b/test/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.tree similarity index 100% rename from test/core/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.tree rename to test/integration/concrete/lockup-tranched/withdrawable-amount-of/withdrawableAmountOf.tree diff --git a/test/core/integration/concrete/nft-descriptor/generateAccentColor.t.sol b/test/integration/concrete/nft-descriptor/generateAccentColor.t.sol similarity index 100% rename from test/core/integration/concrete/nft-descriptor/generateAccentColor.t.sol rename to test/integration/concrete/nft-descriptor/generateAccentColor.t.sol diff --git a/test/core/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.t.sol b/test/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.t.sol similarity index 100% rename from test/core/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.t.sol rename to test/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.t.sol diff --git a/test/core/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.tree b/test/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.tree similarity index 100% rename from test/core/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.tree rename to test/integration/concrete/nft-descriptor/is-allowed-character/IsAllowedCharacter.tree diff --git a/test/core/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol b/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol similarity index 94% rename from test/core/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol rename to test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol index 5f81def48..3bf72d4ff 100644 --- a/test/core/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol +++ b/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import { MockERC721 } from "forge-std/src/mocks/MockERC721.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/integration/concrete/nft-descriptor/map-symbol/mapSymbol.tree b/test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.tree similarity index 100% rename from test/core/integration/concrete/nft-descriptor/map-symbol/mapSymbol.tree rename to test/integration/concrete/nft-descriptor/map-symbol/mapSymbol.tree diff --git a/test/core/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.t.sol b/test/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.t.sol similarity index 100% rename from test/core/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.t.sol rename to test/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.t.sol diff --git a/test/core/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.tree b/test/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.tree similarity index 100% rename from test/core/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.tree rename to test/integration/concrete/nft-descriptor/safe-asset-decimals/safeAssetDecimals.tree diff --git a/test/core/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.t.sol b/test/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.t.sol similarity index 100% rename from test/core/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.t.sol rename to test/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.t.sol diff --git a/test/core/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.tree b/test/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.tree similarity index 100% rename from test/core/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.tree rename to test/integration/concrete/nft-descriptor/safe-asset-symbol/safeAssetSymbol.tree diff --git a/test/core/integration/fuzz/lockup-base/cancel.t.sol b/test/integration/fuzz/lockup-base/cancel.t.sol similarity index 93% rename from test/core/integration/fuzz/lockup-base/cancel.t.sol rename to test/integration/fuzz/lockup-base/cancel.t.sol index 3fe7626c8..30b8f32f5 100644 --- a/test/core/integration/fuzz/lockup-base/cancel.t.sol +++ b/test/integration/fuzz/lockup-base/cancel.t.sol @@ -3,11 +3,11 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { ISablierLockupRecipient } from "src/core/interfaces/ISablierLockupRecipient.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { ISablierLockupRecipient } from "src/interfaces/ISablierLockupRecipient.sol"; +import { Lockup } from "src/types/DataTypes.sol"; -import { Integration_Test } from "./../../Integration.t.sol"; +import { Integration_Test } from "../../Integration.t.sol"; abstract contract Cancel_Integration_Fuzz_Test is Integration_Test { function testFuzz_Cancel_StatusPending(uint256 timeJump) diff --git a/test/core/integration/fuzz/lockup-base/refundableAmountOf.t.sol b/test/integration/fuzz/lockup-base/refundableAmountOf.t.sol similarity index 100% rename from test/core/integration/fuzz/lockup-base/refundableAmountOf.t.sol rename to test/integration/fuzz/lockup-base/refundableAmountOf.t.sol diff --git a/test/core/integration/fuzz/lockup-base/withdraw.t.sol b/test/integration/fuzz/lockup-base/withdraw.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-base/withdraw.t.sol rename to test/integration/fuzz/lockup-base/withdraw.t.sol index 930e93012..137b4e908 100644 --- a/test/core/integration/fuzz/lockup-base/withdraw.t.sol +++ b/test/integration/fuzz/lockup-base/withdraw.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../Integration.t.sol"; diff --git a/test/core/integration/fuzz/lockup-base/withdrawMax.t.sol b/test/integration/fuzz/lockup-base/withdrawMax.t.sol similarity index 96% rename from test/core/integration/fuzz/lockup-base/withdrawMax.t.sol rename to test/integration/fuzz/lockup-base/withdrawMax.t.sol index ef3631ef4..79f3df863 100644 --- a/test/core/integration/fuzz/lockup-base/withdrawMax.t.sol +++ b/test/integration/fuzz/lockup-base/withdrawMax.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../Integration.t.sol"; diff --git a/test/core/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol b/test/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol similarity index 96% rename from test/core/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol rename to test/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol index e15e3b921..7d171e202 100644 --- a/test/core/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol +++ b/test/integration/fuzz/lockup-base/withdrawMaxAndTransfer.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; import { Integration_Test } from "../../Integration.t.sol"; diff --git a/test/core/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol b/test/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol similarity index 91% rename from test/core/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol rename to test/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol index edcea9728..bc2253003 100644 --- a/test/core/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol +++ b/test/integration/fuzz/lockup-dynamic/LockupDynamic.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; -import { Integration_Test } from "./../../Integration.t.sol"; +import { Integration_Test } from "../../Integration.t.sol"; import { Cancel_Integration_Fuzz_Test } from "./../lockup-base/cancel.t.sol"; import { RefundableAmountOf_Integration_Fuzz_Test } from "./../lockup-base/refundableAmountOf.t.sol"; diff --git a/test/core/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol b/test/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol similarity index 97% rename from test/core/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol rename to test/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol index df13e041a..b1e454e15 100644 --- a/test/core/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol +++ b/test/integration/fuzz/lockup-dynamic/createWithDurationsLD.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Lockup_Dynamic_Integration_Fuzz_Test } from "./LockupDynamic.t.sol"; contract CreateWithDurationsLD_Integration_Fuzz_Test is Lockup_Dynamic_Integration_Fuzz_Test { diff --git a/test/core/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol b/test/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol rename to test/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol index b42255a2b..158f88f00 100644 --- a/test/core/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol +++ b/test/integration/fuzz/lockup-dynamic/createWithTimestampsLD.t.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.22 <0.9.0; import { MAX_UD60x18, ud } from "@prb/math/src/UD60x18.sol"; import { stdError } from "forge-std/src/StdError.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Broker, Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Broker, Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Lockup_Dynamic_Integration_Fuzz_Test } from "./LockupDynamic.t.sol"; contract CreateWithTimestampsLD_Integration_Fuzz_Test is Lockup_Dynamic_Integration_Fuzz_Test { diff --git a/test/core/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol b/test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol rename to test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol index 82f62cad8..d19981cad 100644 --- a/test/core/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol +++ b/test/integration/fuzz/lockup-dynamic/streamedAmountOf.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; import { ZERO } from "@prb/math/src/UD60x18.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Lockup_Dynamic_Integration_Fuzz_Test } from "./LockupDynamic.t.sol"; diff --git a/test/core/integration/fuzz/lockup-dynamic/withdraw.t.sol b/test/integration/fuzz/lockup-dynamic/withdraw.t.sol similarity index 97% rename from test/core/integration/fuzz/lockup-dynamic/withdraw.t.sol rename to test/integration/fuzz/lockup-dynamic/withdraw.t.sol index d17180505..9b7249d5d 100644 --- a/test/core/integration/fuzz/lockup-dynamic/withdraw.t.sol +++ b/test/integration/fuzz/lockup-dynamic/withdraw.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Lockup, LockupDynamic } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../Integration.t.sol"; import { Withdraw_Integration_Fuzz_Test } from "./../lockup-base/withdraw.t.sol"; diff --git a/test/core/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol b/test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol rename to test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol index cc423e7bb..e01e6aa44 100644 --- a/test/core/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol +++ b/test/integration/fuzz/lockup-dynamic/withdrawableAmountOf.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Lockup_Dynamic_Integration_Fuzz_Test } from "./LockupDynamic.t.sol"; diff --git a/test/core/integration/fuzz/lockup-linear/LockupLinear.t.sol b/test/integration/fuzz/lockup-linear/LockupLinear.t.sol similarity index 93% rename from test/core/integration/fuzz/lockup-linear/LockupLinear.t.sol rename to test/integration/fuzz/lockup-linear/LockupLinear.t.sol index 1b23505aa..7b3e14589 100644 --- a/test/core/integration/fuzz/lockup-linear/LockupLinear.t.sol +++ b/test/integration/fuzz/lockup-linear/LockupLinear.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; -import { Integration_Test } from "./../../Integration.t.sol"; +import { Integration_Test } from "../../Integration.t.sol"; import { Cancel_Integration_Fuzz_Test } from "./../lockup-base/cancel.t.sol"; import { RefundableAmountOf_Integration_Fuzz_Test } from "./../lockup-base/refundableAmountOf.t.sol"; import { Withdraw_Integration_Fuzz_Test } from "./../lockup-base/withdraw.t.sol"; diff --git a/test/core/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol b/test/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol similarity index 96% rename from test/core/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol rename to test/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol index 0a750cfdd..9df5450b3 100644 --- a/test/core/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol +++ b/test/integration/fuzz/lockup-linear/createWithDurationsLL.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Lockup, LockupLinear } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; diff --git a/test/core/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol b/test/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol similarity index 97% rename from test/core/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol rename to test/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol index 3d84bd96c..90298b970 100644 --- a/test/core/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol +++ b/test/integration/fuzz/lockup-linear/createWithTimestampsLL.t.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.22 <0.9.0; import { MAX_UD60x18, ud } from "@prb/math/src/UD60x18.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Broker, Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Broker, Lockup, LockupLinear } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; diff --git a/test/core/integration/fuzz/lockup-linear/streamedAmountOf.t.sol b/test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-linear/streamedAmountOf.t.sol rename to test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol index e3a7602d0..86e39ad46 100644 --- a/test/core/integration/fuzz/lockup-linear/streamedAmountOf.t.sol +++ b/test/integration/fuzz/lockup-linear/streamedAmountOf.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { LockupLinear } from "src/core/types/DataTypes.sol"; +import { LockupLinear } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; diff --git a/test/core/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol b/test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol rename to test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol index e261d9cc2..9d63eb772 100644 --- a/test/core/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol +++ b/test/integration/fuzz/lockup-linear/withdrawableAmountOf.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; +import { Lockup, LockupLinear } from "src/types/DataTypes.sol"; import { Lockup_Linear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; diff --git a/test/core/integration/fuzz/lockup-tranched/LockupTranched.t.sol b/test/integration/fuzz/lockup-tranched/LockupTranched.t.sol similarity index 96% rename from test/core/integration/fuzz/lockup-tranched/LockupTranched.t.sol rename to test/integration/fuzz/lockup-tranched/LockupTranched.t.sol index 5615a003c..6746d0d8c 100644 --- a/test/core/integration/fuzz/lockup-tranched/LockupTranched.t.sol +++ b/test/integration/fuzz/lockup-tranched/LockupTranched.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Integration_Test } from "./../../Integration.t.sol"; import { Cancel_Integration_Fuzz_Test } from "./../lockup-base/cancel.t.sol"; diff --git a/test/core/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol b/test/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol similarity index 97% rename from test/core/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol rename to test/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol index 75978e4f6..dc327e29f 100644 --- a/test/core/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol +++ b/test/integration/fuzz/lockup-tranched/createWithDurationsLT.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Lockup_Tranched_Integration_Fuzz_Test } from "./LockupTranched.t.sol"; diff --git a/test/core/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol b/test/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol rename to test/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol index acde548af..8befc7388 100644 --- a/test/core/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol +++ b/test/integration/fuzz/lockup-tranched/createWithTimestampsLT.t.sol @@ -4,9 +4,9 @@ pragma solidity >=0.8.22 <0.9.0; import { MAX_UD60x18, ud } from "@prb/math/src/UD60x18.sol"; import { stdError } from "forge-std/src/StdError.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; -import { Broker, Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Errors } from "src/libraries/Errors.sol"; +import { Broker, Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Lockup_Tranched_Integration_Fuzz_Test } from "./LockupTranched.t.sol"; diff --git a/test/core/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol b/test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol rename to test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol index c407b396d..040ebef57 100644 --- a/test/core/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol +++ b/test/integration/fuzz/lockup-tranched/streamedAmountOf.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; import { ZERO } from "@prb/math/src/UD60x18.sol"; -import { Broker, Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { Broker, Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Lockup_Tranched_Integration_Fuzz_Test } from "./LockupTranched.t.sol"; diff --git a/test/core/integration/fuzz/lockup-tranched/withdraw.t.sol b/test/integration/fuzz/lockup-tranched/withdraw.t.sol similarity index 97% rename from test/core/integration/fuzz/lockup-tranched/withdraw.t.sol rename to test/integration/fuzz/lockup-tranched/withdraw.t.sol index 102ad596d..80b056993 100644 --- a/test/core/integration/fuzz/lockup-tranched/withdraw.t.sol +++ b/test/integration/fuzz/lockup-tranched/withdraw.t.sol @@ -2,8 +2,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { Lockup, LockupTranched } from "src/types/DataTypes.sol"; import { Integration_Test } from "../../Integration.t.sol"; import { Withdraw_Integration_Fuzz_Test } from "./../lockup-base/withdraw.t.sol"; diff --git a/test/core/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol b/test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol similarity index 98% rename from test/core/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol rename to test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol index 9b0c88604..4f417b235 100644 --- a/test/core/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol +++ b/test/integration/fuzz/lockup-tranched/withdrawableAmountOf.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; import { ZERO } from "@prb/math/src/UD60x18.sol"; -import { Broker, Lockup } from "src/core/types/DataTypes.sol"; +import { Broker, Lockup } from "src/types/DataTypes.sol"; import { Lockup_Tranched_Integration_Fuzz_Test } from "./LockupTranched.t.sol"; diff --git a/test/core/integration/fuzz/nft-descriptor/isAllowedCharacter.t.sol b/test/integration/fuzz/nft-descriptor/isAllowedCharacter.t.sol similarity index 100% rename from test/core/integration/fuzz/nft-descriptor/isAllowedCharacter.t.sol rename to test/integration/fuzz/nft-descriptor/isAllowedCharacter.t.sol diff --git a/test/core/invariant/Invariant.t.sol b/test/invariant/Invariant.t.sol similarity index 99% rename from test/core/invariant/Invariant.t.sol rename to test/invariant/Invariant.t.sol index bec22824e..5d3ff1a2f 100644 --- a/test/core/invariant/Invariant.t.sol +++ b/test/invariant/Invariant.t.sol @@ -2,8 +2,8 @@ pragma solidity >=0.8.22 <0.9.0; import { StdInvariant } from "forge-std/src/StdInvariant.sol"; -import { Lockup, LockupDynamic, LockupTranched } from "src/core/types/DataTypes.sol"; -import { Base_Test } from "../../Base.t.sol"; +import { Lockup, LockupDynamic, LockupTranched } from "src/types/DataTypes.sol"; +import { Base_Test } from "../Base.t.sol"; import { LockupCreateHandler } from "./handlers/LockupCreateHandler.sol"; import { LockupHandler } from "./handlers/LockupHandler.sol"; import { LockupStore } from "./stores/LockupStore.sol"; diff --git a/test/core/invariant/handlers/BaseHandler.sol b/test/invariant/handlers/BaseHandler.sol similarity index 94% rename from test/core/invariant/handlers/BaseHandler.sol rename to test/invariant/handlers/BaseHandler.sol index e7c3485fb..91729834a 100644 --- a/test/core/invariant/handlers/BaseHandler.sol +++ b/test/invariant/handlers/BaseHandler.sol @@ -3,10 +3,10 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { StdCheats } from "forge-std/src/StdCheats.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; -import { Constants } from "../../../utils/Constants.sol"; -import { Fuzzers } from "../../../utils/Fuzzers.sol"; +import { Constants } from "../../utils/Constants.sol"; +import { Fuzzers } from "../../utils/Fuzzers.sol"; /// @notice Base contract with common logic needed by {LockupHandler} and {LockupCreateHandler} contracts. abstract contract BaseHandler is Constants, Fuzzers, StdCheats { diff --git a/test/core/invariant/handlers/LockupCreateHandler.sol b/test/invariant/handlers/LockupCreateHandler.sol similarity index 99% rename from test/core/invariant/handlers/LockupCreateHandler.sol rename to test/invariant/handlers/LockupCreateHandler.sol index 7c06a1da3..0d565701d 100644 --- a/test/core/invariant/handlers/LockupCreateHandler.sol +++ b/test/invariant/handlers/LockupCreateHandler.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/types/DataTypes.sol"; import { Calculations } from "test/utils/Calculations.sol"; import { LockupStore } from "../stores/LockupStore.sol"; diff --git a/test/core/invariant/handlers/LockupHandler.sol b/test/invariant/handlers/LockupHandler.sol similarity index 98% rename from test/core/invariant/handlers/LockupHandler.sol rename to test/invariant/handlers/LockupHandler.sol index d648fb6a7..ce29db482 100644 --- a/test/core/invariant/handlers/LockupHandler.sol +++ b/test/invariant/handlers/LockupHandler.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { LockupStore } from "../stores/LockupStore.sol"; import { BaseHandler } from "./BaseHandler.sol"; diff --git a/test/core/invariant/stores/LockupStore.sol b/test/invariant/stores/LockupStore.sol similarity index 96% rename from test/core/invariant/stores/LockupStore.sol rename to test/invariant/stores/LockupStore.sol index 8d108d1aa..0314ac96a 100644 --- a/test/core/invariant/stores/LockupStore.sol +++ b/test/invariant/stores/LockupStore.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; /// @dev Storage variables needed by all lockup handlers. contract LockupStore { diff --git a/test/mocks/AdminableMock.sol b/test/mocks/AdminableMock.sol index 1b1d81bb1..b262f066d 100644 --- a/test/mocks/AdminableMock.sol +++ b/test/mocks/AdminableMock.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; -import { Adminable } from "src/core/abstracts/Adminable.sol"; +import { Adminable } from "src/abstracts/Adminable.sol"; contract AdminableMock is Adminable { constructor(address initialAdmin) Adminable(initialAdmin) { } diff --git a/test/mocks/Hooks.sol b/test/mocks/Hooks.sol index 203c2a91a..43ebbd549 100644 --- a/test/mocks/Hooks.sol +++ b/test/mocks/Hooks.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.22; import { IERC165, ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import { ISablierLockupBase } from "src/core/interfaces/ISablierLockupBase.sol"; -import { ISablierLockupRecipient } from "src/core/interfaces/ISablierLockupRecipient.sol"; +import { ISablierLockupBase } from "src/interfaces/ISablierLockupBase.sol"; +import { ISablierLockupRecipient } from "src/interfaces/ISablierLockupRecipient.sol"; contract RecipientGood is ISablierLockupRecipient, ERC165 { function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { diff --git a/test/mocks/NFTDescriptorMock.sol b/test/mocks/NFTDescriptorMock.sol index de052f4ab..dd0d47cf0 100644 --- a/test/mocks/NFTDescriptorMock.sol +++ b/test/mocks/NFTDescriptorMock.sol @@ -2,10 +2,10 @@ pragma solidity >=0.8.22; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; -import { NFTSVG } from "src/core/libraries/NFTSVG.sol"; -import { SVGElements } from "src/core/libraries/SVGElements.sol"; -import { LockupNFTDescriptor } from "src/core/LockupNFTDescriptor.sol"; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { NFTSVG } from "src/libraries/NFTSVG.sol"; +import { SVGElements } from "src/libraries/SVGElements.sol"; +import { LockupNFTDescriptor } from "src/LockupNFTDescriptor.sol"; +import { Lockup } from "src/types/DataTypes.sol"; /// @dev This mock is needed for: /// - Running the tests against the `--via-ir` precompiles diff --git a/test/mocks/ReceiveEth.sol b/test/mocks/ReceiveEth.sol deleted file mode 100644 index 476416a20..000000000 --- a/test/mocks/ReceiveEth.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22; - -/// @dev This contract does not implement receive ether or fallback function. -contract ContractWithoutReceiveEth { } - -/// @dev This contract implements receive ether function. -contract ContractWithReceiveEth { - receive() external payable { } -} diff --git a/test/periphery/Periphery.t.sol b/test/periphery/Periphery.t.sol deleted file mode 100644 index 064e4ab72..000000000 --- a/test/periphery/Periphery.t.sol +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { LockupLinear } from "src/core/types/DataTypes.sol"; -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { SablierMerkleInstant } from "src/periphery/SablierMerkleInstant.sol"; -import { SablierMerkleLL } from "src/periphery/SablierMerkleLL.sol"; -import { SablierMerkleLT } from "src/periphery/SablierMerkleLT.sol"; - -import { Base_Test } from "../Base.t.sol"; -import { ContractWithoutReceiveEth, ContractWithReceiveEth } from "../mocks/ReceiveEth.sol"; - -contract Periphery_Test is Base_Test { - /*////////////////////////////////////////////////////////////////////////// - TEST CONTRACTS - //////////////////////////////////////////////////////////////////////////*/ - - ContractWithoutReceiveEth internal contractWithoutReceiveEth; - ContractWithReceiveEth internal contractWithReceiveEth; - - /*////////////////////////////////////////////////////////////////////////// - SET-UP FUNCTION - //////////////////////////////////////////////////////////////////////////*/ - - function setUp() public virtual override { - Base_Test.setUp(); - - contractWithoutReceiveEth = new ContractWithoutReceiveEth(); - contractWithReceiveEth = new ContractWithReceiveEth(); - vm.label({ account: address(contractWithoutReceiveEth), newLabel: "Contract Without Receive Eth" }); - vm.label({ account: address(contractWithReceiveEth), newLabel: "Contract With Receive Eth" }); - } - - /*////////////////////////////////////////////////////////////////////////// - CALL EXPECTS - MERKLE LOCKUP - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Expects a call to {ISablierMerkleBase.claim} with data provided. - function expectCallToClaimWithData( - address merkleLockup, - uint256 sablierFee, - uint256 index, - address recipient, - uint128 amount, - bytes32[] memory merkleProof - ) - internal - { - vm.expectCall( - merkleLockup, sablierFee, abi.encodeCall(ISablierMerkleBase.claim, (index, recipient, amount, merkleProof)) - ); - } - - /// @dev Expects a call to {ISablierMerkleBase.claim} with msgValue as `msg.value`. - function expectCallToClaimWithMsgValue(address merkleLockup, uint256 msgValue) internal { - vm.expectCall( - merkleLockup, - msgValue, - abi.encodeCall( - ISablierMerkleBase.claim, - (defaults.INDEX1(), users.recipient1, defaults.CLAIM_AMOUNT(), defaults.index1Proof()) - ) - ); - } - - /*////////////////////////////////////////////////////////////////////////// - MERKLE-BASE - //////////////////////////////////////////////////////////////////////////*/ - - function computeMerkleInstantAddress( - address caller, - address campaignOwner, - IERC20 asset_, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - bytes32 salt = keccak256( - abi.encodePacked( - caller, - address(asset_), - expiration, - campaignOwner, - abi.encode(defaults.IPFS_CID()), - merkleRoot, - defaults.NAME_BYTES32() - ) - ); - bytes32 creationBytecodeHash = - keccak256(getMerkleInstantBytecode(campaignOwner, asset_, merkleRoot, expiration, sablierFee)); - return vm.computeCreate2Address({ - salt: salt, - initCodeHash: creationBytecodeHash, - deployer: address(merkleFactory) - }); - } - - function computeMerkleLLAddress( - address caller, - address campaignOwner, - IERC20 asset_, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - bytes32 salt = keccak256( - abi.encodePacked( - caller, - address(asset_), - expiration, - campaignOwner, - abi.encode(defaults.IPFS_CID()), - merkleRoot, - defaults.NAME_BYTES32(), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - abi.encode(defaults.schedule()) - ) - ); - bytes32 creationBytecodeHash = - keccak256(getMerkleLLBytecode(campaignOwner, asset_, merkleRoot, expiration, sablierFee)); - return vm.computeCreate2Address({ - salt: salt, - initCodeHash: creationBytecodeHash, - deployer: address(merkleFactory) - }); - } - - function computeMerkleLTAddress( - address caller, - address campaignOwner, - IERC20 asset_, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - bytes32 salt = keccak256( - abi.encodePacked( - caller, - address(asset_), - expiration, - campaignOwner, - abi.encode(defaults.IPFS_CID()), - merkleRoot, - defaults.NAME_BYTES32(), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.STREAM_START_TIME_ZERO(), - abi.encode(defaults.tranchesWithPercentages()) - ) - ); - bytes32 creationBytecodeHash = - keccak256(getMerkleLTBytecode(campaignOwner, asset_, merkleRoot, expiration, sablierFee)); - return vm.computeCreate2Address({ - salt: salt, - initCodeHash: creationBytecodeHash, - deployer: address(merkleFactory) - }); - } - - function getMerkleInstantBytecode( - address campaignOwner, - IERC20 asset_, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (bytes memory) - { - bytes memory constructorArgs = - abi.encode(defaults.baseParams(campaignOwner, asset_, expiration, merkleRoot), sablierFee); - if (!isTestOptimizedProfile()) { - return bytes.concat(type(SablierMerkleInstant).creationCode, constructorArgs); - } else { - return bytes.concat( - vm.getCode("out-optimized/SablierMerkleInstant.sol/SablierMerkleInstant.json"), constructorArgs - ); - } - } - - function getMerkleLLBytecode( - address campaignOwner, - IERC20 asset_, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (bytes memory) - { - bytes memory constructorArgs = abi.encode( - defaults.baseParams(campaignOwner, asset_, expiration, merkleRoot), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.schedule(), - sablierFee - ); - if (!isTestOptimizedProfile()) { - return bytes.concat(type(SablierMerkleLL).creationCode, constructorArgs); - } else { - return bytes.concat(vm.getCode("out-optimized/SablierMerkleLL.sol/SablierMerkleLL.json"), constructorArgs); - } - } - - function getMerkleLTBytecode( - address campaignOwner, - IERC20 asset_, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (bytes memory) - { - bytes memory constructorArgs = abi.encode( - defaults.baseParams(campaignOwner, asset_, expiration, merkleRoot), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.STREAM_START_TIME_ZERO(), - defaults.tranchesWithPercentages(), - sablierFee - ); - if (!isTestOptimizedProfile()) { - return bytes.concat(type(SablierMerkleLT).creationCode, constructorArgs); - } else { - return bytes.concat(vm.getCode("out-optimized/SablierMerkleLT.sol/SablierMerkleLT.json"), constructorArgs); - } - } -} diff --git a/test/periphery/fork/Fork.t.sol b/test/periphery/fork/Fork.t.sol deleted file mode 100644 index c7f3c38ad..000000000 --- a/test/periphery/fork/Fork.t.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Merkle } from "./../../utils/Murky.sol"; -import { Periphery_Test } from "./../Periphery.t.sol"; - -/// @notice Common logic needed by all fork tests. -abstract contract Fork_Test is Periphery_Test, Merkle { - /*////////////////////////////////////////////////////////////////////////// - STATE VARIABLES - //////////////////////////////////////////////////////////////////////////*/ - - IERC20 internal immutable FORK_ASSET; - - /*////////////////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////////////////*/ - - constructor(IERC20 forkAsset) { - FORK_ASSET = forkAsset; - } - - /*////////////////////////////////////////////////////////////////////////// - SET-UP FUNCTION - //////////////////////////////////////////////////////////////////////////*/ - - function setUp() public virtual override { - // Fork Ethereum Mainnet at a specific block number. - vm.createSelectFork({ blockNumber: 20_428_723, urlOrAlias: "mainnet" }); - - // Set up the parent test contract. - Periphery_Test.setUp(); - - // Load the pre-deployed external dependencies. - // TODO: Update addresses once deployed. - // lockup = ISablierLockup(0x6Fe81F4Bf1aF1b829f0E701647808f3Aa4b0BdE7); - } - - /*////////////////////////////////////////////////////////////////////////// - HELPERS - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Checks the user assumptions. - function checkUsers(address user, address recipient) internal virtual { - // The protocol does not allow the zero address to interact with it. - vm.assume(user != address(0) && recipient != address(0)); - - // The goal is to not have overlapping users because the asset balance tests would fail otherwise. - vm.assume(user != recipient); - vm.assume(user != address(lockup) && recipient != address(lockup)); - - // Avoid users blacklisted by USDC or USDT. - assumeNoBlacklisted(address(FORK_ASSET), user); - assumeNoBlacklisted(address(FORK_ASSET), recipient); - } -} diff --git a/test/periphery/fork/assets/USDC.t.sol b/test/periphery/fork/assets/USDC.t.sol deleted file mode 100644 index e2700ecde..000000000 --- a/test/periphery/fork/assets/USDC.t.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { CreateWithTimestampsLD_BatchLockup_Fork_Test } from "../batch-lockup/createWithTimestampsLD.t.sol"; -import { CreateWithTimestampsLL_BatchLockup_Fork_Test } from "../batch-lockup/createWithTimestampsLL.t.sol"; -import { CreateWithTimestampsLT_BatchLockup_Fork_Test } from "../batch-lockup/createWithTimestampsLT.t.sol"; -import { MerkleInstant_Fork_Test } from "../merkle-campaign/MerkleInstant.t.sol"; -import { MerkleLL_Fork_Test } from "../merkle-campaign/MerkleLL.t.sol"; -import { MerkleLT_Fork_Test } from "../merkle-campaign/MerkleLT.t.sol"; - -/// @dev An ERC-20 asset with 6 decimals. -IERC20 constant usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); - -contract USDC_CreateWithTimestampsLD_BatchLockup_Fork_Test is CreateWithTimestampsLD_BatchLockup_Fork_Test(usdc) { } - -contract USDC_CreateWithTimestampsLL_BatchLockup_Fork_Test is CreateWithTimestampsLL_BatchLockup_Fork_Test(usdc) { } - -contract USDC_CreateWithTimestampsLT_BatchLockup_Fork_Test is CreateWithTimestampsLT_BatchLockup_Fork_Test(usdc) { } - -contract USDC_MerkleInstant_Fork_Test is MerkleInstant_Fork_Test(usdc) { } - -contract USDC_MerkleLL_Fork_Test is MerkleLL_Fork_Test(usdc) { } - -contract USDC_MerkleLT_Fork_Test is MerkleLT_Fork_Test(usdc) { } diff --git a/test/periphery/fork/assets/USDT.t.sol b/test/periphery/fork/assets/USDT.t.sol deleted file mode 100644 index 8d3163dd9..000000000 --- a/test/periphery/fork/assets/USDT.t.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { CreateWithTimestampsLD_BatchLockup_Fork_Test } from "../batch-lockup/createWithTimestampsLD.t.sol"; -import { CreateWithTimestampsLL_BatchLockup_Fork_Test } from "../batch-lockup/createWithTimestampsLL.t.sol"; -import { CreateWithTimestampsLT_BatchLockup_Fork_Test } from "../batch-lockup/createWithTimestampsLT.t.sol"; -import { MerkleInstant_Fork_Test } from "../merkle-campaign/MerkleInstant.t.sol"; -import { MerkleLL_Fork_Test } from "../merkle-campaign/MerkleLL.t.sol"; -import { MerkleLT_Fork_Test } from "../merkle-campaign/MerkleLT.t.sol"; - -/// @dev An ERC-20 asset that suffers from the missing return value bug. -IERC20 constant usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); - -contract USDT_CreateWithTimestampsLD_BatchLockup_Fork_Test is CreateWithTimestampsLD_BatchLockup_Fork_Test(usdt) { } - -contract USDT_CreateWithTimestampsLL_BatchLockup_Fork_Test is CreateWithTimestampsLL_BatchLockup_Fork_Test(usdt) { } - -contract USDT_CreateWithTimestampsLT_BatchLockup_Fork_Test is CreateWithTimestampsLT_BatchLockup_Fork_Test(usdt) { } - -contract USDT_MerkleInstant_Fork_Test is MerkleInstant_Fork_Test(usdt) { } - -contract USDT_MerkleLL_Fork_Test is MerkleLL_Fork_Test(usdt) { } - -contract USDT_MerkleLT_Fork_Test is MerkleLT_Fork_Test(usdt) { } diff --git a/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol b/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol deleted file mode 100644 index ac8f34983..000000000 --- a/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { BatchLockup, Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; - -import { ArrayBuilder } from "../../../utils/ArrayBuilder.sol"; -import { BatchLockupBuilder } from "../../../utils/BatchLockupBuilder.sol"; -import { Fork_Test } from "../Fork.t.sol"; - -/// @dev Runs against multiple fork assets. -abstract contract CreateWithTimestampsLD_BatchLockup_Fork_Test is Fork_Test { - constructor(IERC20 asset_) Fork_Test(asset_) { } - - struct CreateWithTimestampsParams { - uint128 batchSize; - address sender; - address recipient; - uint128 perStreamAmount; - uint40 startTime; - LockupDynamic.Segment[] segments; - } - - function testForkFuzz_CreateWithTimestampsLD(CreateWithTimestampsParams memory params) external { - vm.assume(params.segments.length != 0); - params.batchSize = boundUint128(params.batchSize, 1, 20); - params.startTime = boundUint40(params.startTime, getBlockTimestamp(), getBlockTimestamp() + 24 hours); - fuzzSegmentTimestamps(params.segments, params.startTime); - (params.perStreamAmount,) = fuzzDynamicStreamAmounts({ - upperBound: MAX_UINT128 / params.batchSize, - segments: params.segments, - brokerFee: defaults.brokerNull().fee - }); - - checkUsers(params.sender, params.recipient); - - uint256 firstStreamId = lockup.nextStreamId(); - uint128 totalTransferAmount = params.perStreamAmount * params.batchSize; - - deal({ token: address(FORK_ASSET), to: params.sender, give: uint256(totalTransferAmount) }); - approveContract({ asset_: FORK_ASSET, from: params.sender, spender: address(batchLockup) }); - - Lockup.Timestamps memory timestamps = - Lockup.Timestamps({ start: params.startTime, end: params.segments[params.segments.length - 1].timestamp }); - - Lockup.CreateWithTimestamps memory createWithTimestamps = Lockup.CreateWithTimestamps({ - sender: params.sender, - recipient: params.recipient, - totalAmount: params.perStreamAmount, - asset: FORK_ASSET, - cancelable: true, - transferable: true, - timestamps: timestamps, - broker: defaults.brokerNull() - }); - - BatchLockup.CreateWithTimestampsLD[] memory batchParams = - BatchLockupBuilder.fillBatch(createWithTimestamps, params.segments, params.batchSize); - - expectCallToTransferFrom({ - asset: FORK_ASSET, - from: params.sender, - to: address(batchLockup), - value: totalTransferAmount - }); - expectMultipleCallsToCreateWithTimestampsLD({ - count: uint64(params.batchSize), - params: createWithTimestamps, - segments: params.segments - }); - expectMultipleCallsToTransferFrom({ - asset: FORK_ASSET, - count: uint64(params.batchSize), - from: address(batchLockup), - to: address(lockup), - value: params.perStreamAmount - }); - - uint256[] memory actualStreamIds = batchLockup.createWithTimestampsLD(lockup, FORK_ASSET, batchParams); - uint256[] memory expectedStreamIds = ArrayBuilder.fillStreamIds(firstStreamId, params.batchSize); - assertEq(actualStreamIds, expectedStreamIds); - } -} diff --git a/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol b/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol deleted file mode 100644 index 098befcf3..000000000 --- a/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol +++ /dev/null @@ -1,87 +0,0 @@ - // SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { BatchLockup, Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; - -import { ArrayBuilder } from "../../../utils/ArrayBuilder.sol"; -import { BatchLockupBuilder } from "../../../utils/BatchLockupBuilder.sol"; -import { Fork_Test } from "../Fork.t.sol"; - -/// @dev Runs against multiple fork assets. -abstract contract CreateWithTimestampsLL_BatchLockup_Fork_Test is Fork_Test { - constructor(IERC20 asset_) Fork_Test(asset_) { } - - struct CreateWithTimestampsParams { - uint128 batchSize; - Lockup.Timestamps timestamps; - uint40 cliffTime; - LockupLinear.UnlockAmounts unlockAmounts; - address sender; - address recipient; - uint128 perStreamAmount; - } - - function testForkFuzz_CreateWithTimestampsLL(CreateWithTimestampsParams memory params) external { - params.batchSize = boundUint128(params.batchSize, 1, 20); - params.perStreamAmount = boundUint128(params.perStreamAmount, 1, MAX_UINT128 / params.batchSize); - params.timestamps.start = - boundUint40(params.timestamps.start, getBlockTimestamp(), getBlockTimestamp() + 24 hours); - params.cliffTime = - boundUint40(params.cliffTime, params.timestamps.start + 1 seconds, params.timestamps.start + 52 weeks); - params.timestamps.end = boundUint40(params.timestamps.end, params.cliffTime + 1 seconds, MAX_UNIX_TIMESTAMP); - - // Bound the unlock amounts. - params.unlockAmounts.start = boundUint128(params.unlockAmounts.start, 0, params.perStreamAmount); - params.unlockAmounts.cliff = params.cliffTime > 0 - ? boundUint128(params.unlockAmounts.cliff, 0, params.perStreamAmount - params.unlockAmounts.start) - : 0; - - checkUsers(params.sender, params.recipient); - - uint256 firstStreamId = lockup.nextStreamId(); - uint128 totalTransferAmount = params.perStreamAmount * params.batchSize; - - deal({ token: address(FORK_ASSET), to: params.sender, give: uint256(totalTransferAmount) }); - approveContract({ asset_: FORK_ASSET, from: params.sender, spender: address(batchLockup) }); - - Lockup.CreateWithTimestamps memory createParams = Lockup.CreateWithTimestamps({ - sender: params.sender, - recipient: params.recipient, - totalAmount: params.perStreamAmount, - asset: FORK_ASSET, - cancelable: true, - transferable: true, - timestamps: params.timestamps, - broker: defaults.brokerNull() - }); - BatchLockup.CreateWithTimestampsLL[] memory batchParams = - BatchLockupBuilder.fillBatch(createParams, params.unlockAmounts, params.cliffTime, params.batchSize); - - // Asset flow: sender → batch → Sablier - expectCallToTransferFrom({ - asset: FORK_ASSET, - from: params.sender, - to: address(batchLockup), - value: totalTransferAmount - }); - expectMultipleCallsToCreateWithTimestampsLL({ - count: uint64(params.batchSize), - params: createParams, - unlockAmounts: params.unlockAmounts, - cliffTime: params.cliffTime - }); - expectMultipleCallsToTransferFrom({ - asset: FORK_ASSET, - count: uint64(params.batchSize), - from: address(batchLockup), - to: address(lockup), - value: params.perStreamAmount - }); - - uint256[] memory actualStreamIds = batchLockup.createWithTimestampsLL(lockup, FORK_ASSET, batchParams); - uint256[] memory expectedStreamIds = ArrayBuilder.fillStreamIds(firstStreamId, params.batchSize); - assertEq(actualStreamIds, expectedStreamIds); - } -} diff --git a/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol b/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol deleted file mode 100644 index 60184abf3..000000000 --- a/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import { BatchLockup, Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; - -import { ArrayBuilder } from "../../../utils/ArrayBuilder.sol"; -import { BatchLockupBuilder } from "../../../utils/BatchLockupBuilder.sol"; -import { Fork_Test } from "../Fork.t.sol"; - -/// @dev Runs against multiple fork assets. -abstract contract CreateWithTimestampsLT_BatchLockup_Fork_Test is Fork_Test { - constructor(IERC20 asset_) Fork_Test(asset_) { } - - struct CreateWithTimestampsParams { - uint128 batchSize; - address sender; - address recipient; - uint128 perStreamAmount; - uint40 startTime; - LockupTranched.Tranche[] tranches; - } - - function testForkFuzz_CreateWithTimestampsLT(CreateWithTimestampsParams memory params) external { - vm.assume(params.tranches.length != 0); - params.batchSize = boundUint128(params.batchSize, 1, 20); - params.startTime = boundUint40(params.startTime, getBlockTimestamp(), getBlockTimestamp() + 24 hours); - fuzzTrancheTimestamps(params.tranches, params.startTime); - (params.perStreamAmount,) = fuzzTranchedStreamAmounts({ - upperBound: MAX_UINT128 / params.batchSize, - tranches: params.tranches, - brokerFee: defaults.brokerNull().fee - }); - - Lockup.Timestamps memory timestamps = - Lockup.Timestamps({ start: params.startTime, end: params.tranches[params.tranches.length - 1].timestamp }); - - checkUsers(params.sender, params.recipient); - - uint256 firstStreamId = lockup.nextStreamId(); - uint128 totalTransferAmount = params.perStreamAmount * params.batchSize; - - deal({ token: address(FORK_ASSET), to: params.sender, give: uint256(totalTransferAmount) }); - approveContract({ asset_: FORK_ASSET, from: params.sender, spender: address(batchLockup) }); - - Lockup.CreateWithTimestamps memory createWithTimestamps = Lockup.CreateWithTimestamps({ - sender: params.sender, - recipient: params.recipient, - totalAmount: params.perStreamAmount, - asset: FORK_ASSET, - cancelable: true, - transferable: true, - timestamps: timestamps, - broker: defaults.brokerNull() - }); - BatchLockup.CreateWithTimestampsLT[] memory batchParams = - BatchLockupBuilder.fillBatch(createWithTimestamps, params.tranches, params.batchSize); - - expectCallToTransferFrom({ - asset: FORK_ASSET, - from: params.sender, - to: address(batchLockup), - value: totalTransferAmount - }); - expectMultipleCallsToCreateWithTimestampsLT({ - count: uint64(params.batchSize), - params: createWithTimestamps, - tranches: params.tranches - }); - expectMultipleCallsToTransferFrom({ - asset: FORK_ASSET, - count: uint64(params.batchSize), - from: address(batchLockup), - to: address(lockup), - value: params.perStreamAmount - }); - - uint256[] memory actualStreamIds = batchLockup.createWithTimestampsLT(lockup, FORK_ASSET, batchParams); - uint256[] memory expectedStreamIds = ArrayBuilder.fillStreamIds(firstStreamId, params.batchSize); - assertEq(actualStreamIds, expectedStreamIds); - } -} diff --git a/test/periphery/fork/merkle-campaign/MerkleInstant.t.sol b/test/periphery/fork/merkle-campaign/MerkleInstant.t.sol deleted file mode 100644 index 2663c2a74..000000000 --- a/test/periphery/fork/merkle-campaign/MerkleInstant.t.sol +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Arrays } from "@openzeppelin/contracts/utils/Arrays.sol"; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleBase, ISablierMerkleInstant } from "src/periphery/interfaces/ISablierMerkleInstant.sol"; - -import { MerkleBase } from "src/periphery/types/DataTypes.sol"; - -import { MerkleBuilder } from "./../../../utils/MerkleBuilder.sol"; -import { Fork_Test } from "./../Fork.t.sol"; - -abstract contract MerkleInstant_Fork_Test is Fork_Test { - using MerkleBuilder for uint256[]; - - constructor(IERC20 asset_) Fork_Test(asset_) { } - - /// @dev Encapsulates the data needed to compute a Merkle tree leaf. - struct LeafData { - uint256 index; - uint256 recipientSeed; - uint128 amount; - } - - struct Params { - address campaignOwner; - uint40 expiration; - LeafData[] leafData; - uint256 posBeforeSort; - } - - struct Vars { - uint256 aggregateAmount; - uint128[] amounts; - MerkleBase.ConstructorParams baseParams; - uint128 clawbackAmount; - address expectedMerkleInstant; - uint256[] indexes; - uint256 leafPos; - uint256 leafToClaim; - ISablierMerkleInstant merkleInstant; - bytes32[] merkleProof; - bytes32 merkleRoot; - address[] recipients; - uint256 recipientCount; - } - - // We need the leaves as a storage variable so that we can use OpenZeppelin's {Arrays.findUpperBound}. - uint256[] public leaves; - - function testForkFuzz_MerkleInstant(Params memory params) external { - vm.assume(params.campaignOwner != address(0) && params.campaignOwner != users.campaignOwner); - vm.assume(params.leafData.length > 0); - assumeNoBlacklisted({ token: address(FORK_ASSET), addr: params.campaignOwner }); - params.posBeforeSort = _bound(params.posBeforeSort, 0, params.leafData.length - 1); - - // The expiration must be either zero or greater than the block timestamp. - if (params.expiration != 0) { - params.expiration = boundUint40(params.expiration, getBlockTimestamp() + 1 seconds, MAX_UNIX_TIMESTAMP); - } - - /*////////////////////////////////////////////////////////////////////////// - CREATE - //////////////////////////////////////////////////////////////////////////*/ - - Vars memory vars; - vars.recipientCount = params.leafData.length; - vars.amounts = new uint128[](vars.recipientCount); - vars.indexes = new uint256[](vars.recipientCount); - vars.recipients = new address[](vars.recipientCount); - for (uint256 i = 0; i < vars.recipientCount; ++i) { - vars.indexes[i] = params.leafData[i].index; - - // Bound each leaf amount so that `aggregateAmount` does not overflow. - vars.amounts[i] = boundUint128(params.leafData[i].amount, 1, uint128(MAX_UINT128 / vars.recipientCount - 1)); - vars.aggregateAmount += vars.amounts[i]; - - // Avoid zero recipient addresses. - uint256 boundedRecipientSeed = _bound(params.leafData[i].recipientSeed, 1, type(uint160).max); - vars.recipients[i] = address(uint160(boundedRecipientSeed)); - } - - leaves = new uint256[](vars.recipientCount); - leaves = MerkleBuilder.computeLeaves(vars.indexes, vars.recipients, vars.amounts); - - // Sort the leaves in ascending order to match the production environment. - MerkleBuilder.sortLeaves(leaves); - - // Compute the Merkle root. - if (leaves.length == 1) { - // If there is only one leaf, the Merkle root is the hash of the leaf itself. - vars.merkleRoot = bytes32(leaves[0]); - } else { - vars.merkleRoot = getRoot(leaves.toBytes32()); - } - - // Make the campaign owner as the caller. - resetPrank({ msgSender: params.campaignOwner }); - - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - - vars.expectedMerkleInstant = computeMerkleInstantAddress( - params.campaignOwner, params.campaignOwner, FORK_ASSET, vars.merkleRoot, params.expiration, sablierFee - ); - - vars.baseParams = defaults.baseParams({ - campaignOwner: params.campaignOwner, - asset_: FORK_ASSET, - merkleRoot: vars.merkleRoot, - expiration: params.expiration - }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleInstant({ - merkleInstant: ISablierMerkleInstant(vars.expectedMerkleInstant), - baseParams: vars.baseParams, - aggregateAmount: vars.aggregateAmount, - recipientCount: vars.recipientCount, - sablierFee: sablierFee - }); - - vars.merkleInstant = merkleFactory.createMerkleInstant({ - baseParams: vars.baseParams, - aggregateAmount: vars.aggregateAmount, - recipientCount: vars.recipientCount - }); - - // Fund the MerkleInstant contract. - deal({ token: address(FORK_ASSET), to: address(vars.merkleInstant), give: vars.aggregateAmount }); - - assertGt(address(vars.merkleInstant).code.length, 0, "MerkleInstant contract not created"); - assertEq( - address(vars.merkleInstant), - vars.expectedMerkleInstant, - "MerkleInstant contract does not match computed address" - ); - - /*////////////////////////////////////////////////////////////////////////// - CLAIM - //////////////////////////////////////////////////////////////////////////*/ - - // Make the recipient as the caller. - resetPrank({ msgSender: vars.recipients[params.posBeforeSort] }); - vm.deal(vars.recipients[params.posBeforeSort], 1 ether); - - assertFalse(vars.merkleInstant.hasClaimed(vars.indexes[params.posBeforeSort])); - - vars.leafToClaim = MerkleBuilder.computeLeaf( - vars.indexes[params.posBeforeSort], - vars.recipients[params.posBeforeSort], - vars.amounts[params.posBeforeSort] - ); - vars.leafPos = Arrays.findUpperBound(leaves, vars.leafToClaim); - - vm.expectEmit({ emitter: address(vars.merkleInstant) }); - emit ISablierMerkleInstant.Claim( - vars.indexes[params.posBeforeSort], - vars.recipients[params.posBeforeSort], - vars.amounts[params.posBeforeSort] - ); - - // Compute the Merkle proof. - if (leaves.length == 1) { - // If there is only one leaf, the Merkle proof should be an empty array as no proof is needed because the - // leaf is the root. - } else { - vars.merkleProof = getProof(leaves.toBytes32(), vars.leafPos); - } - - expectCallToClaimWithData({ - merkleLockup: address(vars.merkleInstant), - sablierFee: sablierFee, - index: vars.indexes[params.posBeforeSort], - recipient: vars.recipients[params.posBeforeSort], - amount: vars.amounts[params.posBeforeSort], - merkleProof: vars.merkleProof - }); - - expectCallToTransfer({ - asset: FORK_ASSET, - to: vars.recipients[params.posBeforeSort], - value: vars.amounts[params.posBeforeSort] - }); - - vars.merkleInstant.claim{ value: sablierFee }({ - index: vars.indexes[params.posBeforeSort], - recipient: vars.recipients[params.posBeforeSort], - amount: vars.amounts[params.posBeforeSort], - merkleProof: vars.merkleProof - }); - - assertTrue(vars.merkleInstant.hasClaimed(vars.indexes[params.posBeforeSort])); - - /*////////////////////////////////////////////////////////////////////////// - CLAWBACK - //////////////////////////////////////////////////////////////////////////*/ - - // Make the campaign owner as the caller. - resetPrank({ msgSender: params.campaignOwner }); - - if (params.expiration > 0) { - vars.clawbackAmount = uint128(FORK_ASSET.balanceOf(address(vars.merkleInstant))); - vm.warp({ newTimestamp: uint256(params.expiration) + 1 seconds }); - - expectCallToTransfer({ asset: FORK_ASSET, to: params.campaignOwner, value: vars.clawbackAmount }); - vm.expectEmit({ emitter: address(vars.merkleInstant) }); - emit ISablierMerkleBase.Clawback({ - to: params.campaignOwner, - admin: params.campaignOwner, - amount: vars.clawbackAmount - }); - vars.merkleInstant.clawback({ to: params.campaignOwner, amount: vars.clawbackAmount }); - } - - /*////////////////////////////////////////////////////////////////////////// - WITHDRAW-FEE - //////////////////////////////////////////////////////////////////////////*/ - - // Make the factory admin as the caller. - resetPrank({ msgSender: users.admin }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.WithdrawSablierFees({ - admin: users.admin, - merkleBase: vars.merkleInstant, - to: users.admin, - sablierFees: sablierFee - }); - merkleFactory.withdrawFees({ to: payable(users.admin), merkleBase: vars.merkleInstant }); - - assertEq(address(vars.merkleInstant).balance, 0, "merkle lockup ether balance"); - assertEq(users.admin.balance, sablierFee, "admin ether balance"); - } -} diff --git a/test/periphery/fork/merkle-campaign/MerkleLL.t.sol b/test/periphery/fork/merkle-campaign/MerkleLL.t.sol deleted file mode 100644 index 5d2c768e5..000000000 --- a/test/periphery/fork/merkle-campaign/MerkleLL.t.sol +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Arrays } from "@openzeppelin/contracts/utils/Arrays.sol"; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleBase, ISablierMerkleLL } from "src/periphery/interfaces/ISablierMerkleLL.sol"; -import { MerkleBase } from "src/periphery/types/DataTypes.sol"; - -import { MerkleBuilder } from "./../../../utils/MerkleBuilder.sol"; -import { Fork_Test } from "./../Fork.t.sol"; - -abstract contract MerkleLL_Fork_Test is Fork_Test { - using MerkleBuilder for uint256[]; - - constructor(IERC20 asset_) Fork_Test(asset_) { } - - /// @dev Encapsulates the data needed to compute a Merkle tree leaf. - struct LeafData { - uint256 index; - uint256 recipientSeed; - uint128 amount; - } - - struct Params { - address campaignOwner; - uint40 expiration; - LeafData[] leafData; - uint256 posBeforeSort; - } - - struct Vars { - uint256 aggregateAmount; - uint128[] amounts; - MerkleBase.ConstructorParams baseParams; - uint128 clawbackAmount; - address expectedLL; - uint256 expectedStreamId; - uint256[] indexes; - uint256 leafPos; - uint256 leafToClaim; - ISablierMerkleLL merkleLL; - bytes32[] merkleProof; - bytes32 merkleRoot; - address[] recipients; - uint256 recipientCount; - } - - // We need the leaves as a storage variable so that we can use OpenZeppelin's {Arrays.findUpperBound}. - uint256[] public leaves; - - function testForkFuzz_MerkleLL(Params memory params) external { - vm.assume(params.campaignOwner != address(0) && params.campaignOwner != users.campaignOwner); - vm.assume(params.leafData.length > 0); - assumeNoBlacklisted({ token: address(FORK_ASSET), addr: params.campaignOwner }); - params.posBeforeSort = _bound(params.posBeforeSort, 0, params.leafData.length - 1); - - // The expiration must be either zero or greater than the block timestamp. - if (params.expiration != 0) { - params.expiration = boundUint40(params.expiration, getBlockTimestamp() + 1 seconds, MAX_UNIX_TIMESTAMP); - } - - /*////////////////////////////////////////////////////////////////////////// - CREATE - //////////////////////////////////////////////////////////////////////////*/ - - Vars memory vars; - vars.recipientCount = params.leafData.length; - vars.amounts = new uint128[](vars.recipientCount); - vars.indexes = new uint256[](vars.recipientCount); - vars.recipients = new address[](vars.recipientCount); - for (uint256 i = 0; i < vars.recipientCount; ++i) { - vars.indexes[i] = params.leafData[i].index; - - // Bound each leaf amount so that `aggregateAmount` does not overflow. - vars.amounts[i] = boundUint128( - params.leafData[i].amount, - defaults.START_AMOUNT() + defaults.CLIFF_AMOUNT(), - uint128(MAX_UINT128 / vars.recipientCount - 1) - ); - vars.aggregateAmount += vars.amounts[i]; - - // Avoid zero recipient addresses. - uint256 boundedRecipientSeed = _bound(params.leafData[i].recipientSeed, 1, type(uint160).max); - vars.recipients[i] = address(uint160(boundedRecipientSeed)); - } - - leaves = new uint256[](vars.recipientCount); - leaves = MerkleBuilder.computeLeaves(vars.indexes, vars.recipients, vars.amounts); - - // Sort the leaves in ascending order to match the production environment. - MerkleBuilder.sortLeaves(leaves); - - // Compute the Merkle root. - if (leaves.length == 1) { - // If there is only one leaf, the Merkle root is the hash of the leaf itself. - vars.merkleRoot = bytes32(leaves[0]); - } else { - vars.merkleRoot = getRoot(leaves.toBytes32()); - } - - // Make the campaign owner as the caller. - resetPrank({ msgSender: params.campaignOwner }); - - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - - vars.expectedLL = computeMerkleLLAddress( - params.campaignOwner, params.campaignOwner, FORK_ASSET, vars.merkleRoot, params.expiration, sablierFee - ); - - vars.baseParams = defaults.baseParams({ - campaignOwner: params.campaignOwner, - asset_: FORK_ASSET, - merkleRoot: vars.merkleRoot, - expiration: params.expiration - }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleLL({ - merkleLL: ISablierMerkleLL(vars.expectedLL), - baseParams: vars.baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: defaults.schedule(), - aggregateAmount: vars.aggregateAmount, - recipientCount: vars.recipientCount, - sablierFee: sablierFee - }); - - vars.merkleLL = merkleFactory.createMerkleLL({ - baseParams: vars.baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: defaults.schedule(), - aggregateAmount: vars.aggregateAmount, - recipientCount: vars.recipientCount - }); - - // Fund the MerkleLL contract. - deal({ token: address(FORK_ASSET), to: address(vars.merkleLL), give: vars.aggregateAmount }); - - assertGt(address(vars.merkleLL).code.length, 0, "MerkleLL contract not created"); - assertEq(address(vars.merkleLL), vars.expectedLL, "MerkleLL contract does not match computed address"); - - /*////////////////////////////////////////////////////////////////////////// - CLAIM - //////////////////////////////////////////////////////////////////////////*/ - - // Make the recipient as the caller. - resetPrank({ msgSender: vars.recipients[params.posBeforeSort] }); - vm.deal(vars.recipients[params.posBeforeSort], 1 ether); - - assertFalse(vars.merkleLL.hasClaimed(vars.indexes[params.posBeforeSort])); - - vars.leafToClaim = MerkleBuilder.computeLeaf( - vars.indexes[params.posBeforeSort], - vars.recipients[params.posBeforeSort], - vars.amounts[params.posBeforeSort] - ); - vars.leafPos = Arrays.findUpperBound(leaves, vars.leafToClaim); - - vars.expectedStreamId = lockup.nextStreamId(); - - vm.expectEmit({ emitter: address(vars.merkleLL) }); - emit ISablierMerkleLL.Claim( - vars.indexes[params.posBeforeSort], - vars.recipients[params.posBeforeSort], - vars.amounts[params.posBeforeSort], - vars.expectedStreamId - ); - - // Compute the Merkle proof. - if (leaves.length == 1) { - // If there is only one leaf, the Merkle proof should be an empty array as no proof is needed because the - // leaf is the root. - } else { - vars.merkleProof = getProof(leaves.toBytes32(), vars.leafPos); - } - - expectCallToClaimWithData({ - merkleLockup: address(vars.merkleLL), - sablierFee: sablierFee, - index: vars.indexes[params.posBeforeSort], - recipient: vars.recipients[params.posBeforeSort], - amount: vars.amounts[params.posBeforeSort], - merkleProof: vars.merkleProof - }); - - vars.merkleLL.claim{ value: sablierFee }({ - index: vars.indexes[params.posBeforeSort], - recipient: vars.recipients[params.posBeforeSort], - amount: vars.amounts[params.posBeforeSort], - merkleProof: vars.merkleProof - }); - - // Assert that the stream has been created successfully. - assertEq( - lockup.getDepositedAmount(vars.expectedStreamId), vars.amounts[params.posBeforeSort], "deposited amount" - ); - assertEq(lockup.getRefundedAmount(vars.expectedStreamId), 0, "refunded amount"); - assertEq(lockup.getWithdrawnAmount(vars.expectedStreamId), 0, "withdrawn amount"); - assertEq(lockup.getAsset(vars.expectedStreamId), FORK_ASSET, "asset"); - assertEq( - lockup.getCliffTime(vars.expectedStreamId), getBlockTimestamp() + defaults.CLIFF_DURATION(), "cliff time" - ); - assertEq(lockup.getEndTime(vars.expectedStreamId), getBlockTimestamp() + defaults.TOTAL_DURATION(), "end time"); - assertEq(lockup.isCancelable(vars.expectedStreamId), defaults.CANCELABLE(), "is cancelable"); - assertEq(lockup.isDepleted(vars.expectedStreamId), false, "is depleted"); - assertEq(lockup.isStream(vars.expectedStreamId), true, "is stream"); - assertEq(lockup.isTransferable(vars.expectedStreamId), defaults.TRANSFERABLE(), "is transferable"); - assertEq(lockup.getRecipient(vars.expectedStreamId), vars.recipients[params.posBeforeSort], "recipient"); - assertEq(lockup.getSender(vars.expectedStreamId), params.campaignOwner, "sender"); - assertEq(lockup.getStartTime(vars.expectedStreamId), getBlockTimestamp(), "start time"); - assertEq(lockup.wasCanceled(vars.expectedStreamId), false, "was canceled"); - assertEq(lockup.getUnlockAmounts(vars.expectedStreamId).start, defaults.START_AMOUNT(), "unlock amounts start"); - assertEq(lockup.getUnlockAmounts(vars.expectedStreamId).cliff, defaults.CLIFF_AMOUNT(), "unlock amounts cliff"); - - assertTrue(vars.merkleLL.hasClaimed(vars.indexes[params.posBeforeSort])); - - /*////////////////////////////////////////////////////////////////////////// - CLAWBACK - //////////////////////////////////////////////////////////////////////////*/ - - // Make the campaign owner as the caller. - resetPrank({ msgSender: params.campaignOwner }); - - if (params.expiration > 0) { - vars.clawbackAmount = uint128(FORK_ASSET.balanceOf(address(vars.merkleLL))); - vm.warp({ newTimestamp: uint256(params.expiration) + 1 seconds }); - - expectCallToTransfer({ asset: FORK_ASSET, to: params.campaignOwner, value: vars.clawbackAmount }); - vm.expectEmit({ emitter: address(vars.merkleLL) }); - emit ISablierMerkleBase.Clawback({ - to: params.campaignOwner, - admin: params.campaignOwner, - amount: vars.clawbackAmount - }); - vars.merkleLL.clawback({ to: params.campaignOwner, amount: vars.clawbackAmount }); - } - - /*////////////////////////////////////////////////////////////////////////// - WITHDRAW-FEE - //////////////////////////////////////////////////////////////////////////*/ - - // Make the factory admin as the caller. - resetPrank({ msgSender: users.admin }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.WithdrawSablierFees({ - admin: users.admin, - merkleBase: vars.merkleLL, - to: users.admin, - sablierFees: sablierFee - }); - merkleFactory.withdrawFees({ to: payable(users.admin), merkleBase: vars.merkleLL }); - - assertEq(address(vars.merkleLL).balance, 0, "merkle lockup ether balance"); - assertEq(users.admin.balance, sablierFee, "admin ether balance"); - } -} diff --git a/test/periphery/fork/merkle-campaign/MerkleLT.t.sol b/test/periphery/fork/merkle-campaign/MerkleLT.t.sol deleted file mode 100644 index 2dfc1ad3c..000000000 --- a/test/periphery/fork/merkle-campaign/MerkleLT.t.sol +++ /dev/null @@ -1,267 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Arrays } from "@openzeppelin/contracts/utils/Arrays.sol"; - -import { LockupTranched } from "src/core/types/DataTypes.sol"; -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleBase, ISablierMerkleLT } from "src/periphery/interfaces/ISablierMerkleLT.sol"; -import { MerkleBase } from "src/periphery/types/DataTypes.sol"; - -import { MerkleBuilder } from "./../../../utils/MerkleBuilder.sol"; -import { Fork_Test } from "./../Fork.t.sol"; - -abstract contract MerkleLT_Fork_Test is Fork_Test { - using MerkleBuilder for uint256[]; - - constructor(IERC20 asset_) Fork_Test(asset_) { } - - /// @dev Encapsulates the data needed to compute a Merkle tree leaf. - struct LeafData { - uint256 index; - uint256 recipientSeed; - uint128 amount; - } - - struct Params { - address campaignOwner; - uint40 expiration; - LeafData[] leafData; - uint256 posBeforeSort; - } - - struct Vars { - LockupTranched.Tranche[] actualTranches; - uint256 aggregateAmount; - uint128[] amounts; - MerkleBase.ConstructorParams baseParams; - uint128 clawbackAmount; - address expectedLT; - uint256 expectedStreamId; - uint256[] indexes; - uint256 leafPos; - uint256 leafToClaim; - ISablierMerkleLT merkleLT; - bytes32[] merkleProof; - bytes32 merkleRoot; - address[] recipients; - uint256 recipientCount; - } - - // We need the leaves as a storage variable so that we can use OpenZeppelin's {Arrays.findUpperBound}. - uint256[] public leaves; - - function testForkFuzz_MerkleLT(Params memory params) external { - vm.assume(params.campaignOwner != address(0) && params.campaignOwner != users.campaignOwner); - vm.assume(params.leafData.length > 0); - assumeNoBlacklisted({ token: address(FORK_ASSET), addr: params.campaignOwner }); - params.posBeforeSort = _bound(params.posBeforeSort, 0, params.leafData.length - 1); - - // The expiration must be either zero or greater than the block timestamp. - if (params.expiration != 0) { - params.expiration = boundUint40(params.expiration, getBlockTimestamp() + 1 seconds, MAX_UNIX_TIMESTAMP); - } - - /*////////////////////////////////////////////////////////////////////////// - CREATE - //////////////////////////////////////////////////////////////////////////*/ - - Vars memory vars; - vars.recipientCount = params.leafData.length; - vars.amounts = new uint128[](vars.recipientCount); - vars.indexes = new uint256[](vars.recipientCount); - vars.recipients = new address[](vars.recipientCount); - for (uint256 i = 0; i < vars.recipientCount; ++i) { - vars.indexes[i] = params.leafData[i].index; - - // Bound each leaf amount so that `aggregateAmount` does not overflow. - vars.amounts[i] = boundUint128(params.leafData[i].amount, 1, uint128(MAX_UINT128 / vars.recipientCount - 1)); - vars.aggregateAmount += vars.amounts[i]; - - // Avoid zero recipient addresses. - uint256 boundedRecipientSeed = _bound(params.leafData[i].recipientSeed, 1, type(uint160).max); - vars.recipients[i] = address(uint160(boundedRecipientSeed)); - } - - leaves = new uint256[](vars.recipientCount); - leaves = MerkleBuilder.computeLeaves(vars.indexes, vars.recipients, vars.amounts); - - // Sort the leaves in ascending order to match the production environment. - MerkleBuilder.sortLeaves(leaves); - - // Compute the Merkle root. - if (leaves.length == 1) { - // If there is only one leaf, the Merkle root is the hash of the leaf itself. - vars.merkleRoot = bytes32(leaves[0]); - } else { - vars.merkleRoot = getRoot(leaves.toBytes32()); - } - - // Make the campaign owner as the caller. - resetPrank({ msgSender: params.campaignOwner }); - - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - - vars.expectedLT = computeMerkleLTAddress( - params.campaignOwner, params.campaignOwner, FORK_ASSET, vars.merkleRoot, params.expiration, sablierFee - ); - - vars.baseParams = defaults.baseParams({ - campaignOwner: params.campaignOwner, - asset_: FORK_ASSET, - merkleRoot: vars.merkleRoot, - expiration: params.expiration - }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleLT({ - merkleLT: ISablierMerkleLT(vars.expectedLT), - baseParams: vars.baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - streamStartTime: defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages: defaults.tranchesWithPercentages(), - totalDuration: defaults.TOTAL_DURATION(), - aggregateAmount: vars.aggregateAmount, - recipientCount: vars.recipientCount, - sablierFee: sablierFee - }); - - vars.merkleLT = merkleFactory.createMerkleLT({ - baseParams: vars.baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - streamStartTime: defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages: defaults.tranchesWithPercentages(), - aggregateAmount: vars.aggregateAmount, - recipientCount: vars.recipientCount - }); - - // Fund the MerkleLT contract. - deal({ token: address(FORK_ASSET), to: address(vars.merkleLT), give: vars.aggregateAmount }); - - assertGt(address(vars.merkleLT).code.length, 0, "MerkleLT contract not created"); - assertEq(address(vars.merkleLT), vars.expectedLT, "MerkleLT contract does not match computed address"); - - /*////////////////////////////////////////////////////////////////////////// - CLAIM - //////////////////////////////////////////////////////////////////////////*/ - - // Make the recipient as the caller. - resetPrank({ msgSender: vars.recipients[params.posBeforeSort] }); - vm.deal(vars.recipients[params.posBeforeSort], 1 ether); - - assertFalse(vars.merkleLT.hasClaimed(vars.indexes[params.posBeforeSort])); - - vars.leafToClaim = MerkleBuilder.computeLeaf( - vars.indexes[params.posBeforeSort], - vars.recipients[params.posBeforeSort], - vars.amounts[params.posBeforeSort] - ); - vars.leafPos = Arrays.findUpperBound(leaves, vars.leafToClaim); - - vars.expectedStreamId = lockup.nextStreamId(); - vm.expectEmit({ emitter: address(vars.merkleLT) }); - emit ISablierMerkleLT.Claim( - vars.indexes[params.posBeforeSort], - vars.recipients[params.posBeforeSort], - vars.amounts[params.posBeforeSort], - vars.expectedStreamId - ); - - // Compute the Merkle proof. - if (leaves.length == 1) { - // If there is only one leaf, the Merkle proof should be an empty array as no proof is needed because the - // leaf is the root. - } else { - vars.merkleProof = getProof(leaves.toBytes32(), vars.leafPos); - } - - expectCallToClaimWithData({ - merkleLockup: address(vars.merkleLT), - sablierFee: sablierFee, - index: vars.indexes[params.posBeforeSort], - recipient: vars.recipients[params.posBeforeSort], - amount: vars.amounts[params.posBeforeSort], - merkleProof: vars.merkleProof - }); - - vars.merkleLT.claim{ value: sablierFee }({ - index: vars.indexes[params.posBeforeSort], - recipient: vars.recipients[params.posBeforeSort], - amount: vars.amounts[params.posBeforeSort], - merkleProof: vars.merkleProof - }); - - // Assert that the stream has been creatUSDT_MerkleLL_Fork_Tested successfully. - assertEq( - lockup.getDepositedAmount(vars.expectedStreamId), vars.amounts[params.posBeforeSort], "deposited amount" - ); - assertEq(lockup.getRefundedAmount(vars.expectedStreamId), 0, "refunded amount"); - assertEq(lockup.getWithdrawnAmount(vars.expectedStreamId), 0, "withdrawn amount"); - assertEq(lockup.getAsset(vars.expectedStreamId), FORK_ASSET, "asset"); - assertEq(lockup.getEndTime(vars.expectedStreamId), getBlockTimestamp() + defaults.TOTAL_DURATION(), "end time"); - assertEq(lockup.isCancelable(vars.expectedStreamId), defaults.CANCELABLE(), "is cancelable"); - assertEq(lockup.isDepleted(vars.expectedStreamId), false, "is depleted"); - assertEq(lockup.isStream(vars.expectedStreamId), true, "is stream"); - assertEq(lockup.isTransferable(vars.expectedStreamId), defaults.TRANSFERABLE(), "is transferable"); - assertEq(lockup.getRecipient(vars.expectedStreamId), vars.recipients[params.posBeforeSort], "recipient"); - assertEq(lockup.getSender(vars.expectedStreamId), params.campaignOwner, "sender"); - assertEq(lockup.getStartTime(vars.expectedStreamId), getBlockTimestamp(), "start time"); - assertEq(lockup.wasCanceled(vars.expectedStreamId), false, "was canceled"); - assertEq( - lockup.getTranches(vars.expectedStreamId), - defaults.tranchesMerkleLT({ - streamStartTime: defaults.STREAM_START_TIME_ZERO(), - totalAmount: vars.amounts[params.posBeforeSort] - }), - "tranches" - ); - - assertTrue(vars.merkleLT.hasClaimed(vars.indexes[params.posBeforeSort])); - - /*////////////////////////////////////////////////////////////////////////// - CLAWBACK - //////////////////////////////////////////////////////////////////////////*/ - - // Make the campaign owner as the caller. - resetPrank({ msgSender: params.campaignOwner }); - - if (params.expiration > 0) { - vars.clawbackAmount = uint128(FORK_ASSET.balanceOf(address(vars.merkleLT))); - vm.warp({ newTimestamp: uint256(params.expiration) + 1 seconds }); - - resetPrank({ msgSender: params.campaignOwner }); - expectCallToTransfer({ asset: FORK_ASSET, to: params.campaignOwner, value: vars.clawbackAmount }); - vm.expectEmit({ emitter: address(vars.merkleLT) }); - emit ISablierMerkleBase.Clawback({ - to: params.campaignOwner, - admin: params.campaignOwner, - amount: vars.clawbackAmount - }); - vars.merkleLT.clawback({ to: params.campaignOwner, amount: vars.clawbackAmount }); - } - - /*////////////////////////////////////////////////////////////////////////// - WITHDRAW-FEE - //////////////////////////////////////////////////////////////////////////*/ - - // Make the factory admin as the caller. - resetPrank({ msgSender: users.admin }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.WithdrawSablierFees({ - admin: users.admin, - merkleBase: vars.merkleLT, - to: users.admin, - sablierFees: sablierFee - }); - merkleFactory.withdrawFees({ to: payable(users.admin), merkleBase: vars.merkleLT }); - - assertEq(address(vars.merkleLT).balance, 0, "merkle lockup ether balance"); - assertEq(users.admin.balance, sablierFee, "admin ether balance"); - } -} diff --git a/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol b/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol deleted file mode 100644 index 85dedf95f..000000000 --- a/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol +++ /dev/null @@ -1,290 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22; - -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { ISablierMerkleInstant } from "src/periphery/interfaces/ISablierMerkleInstant.sol"; -import { ISablierMerkleLL } from "src/periphery/interfaces/ISablierMerkleLL.sol"; -import { ISablierMerkleLT } from "src/periphery/interfaces/ISablierMerkleLT.sol"; - -import { Periphery_Test } from "../../Periphery.t.sol"; - -abstract contract MerkleCampaign_Integration_Test is Periphery_Test { - /// @dev A test contract meant to be overridden by the implementing contract, which will be either - /// {SablierMerkleLL}, {SablierMerkleLT} or {SablierMerkleInstant}. - ISablierMerkleBase internal merkleBase; - - /*////////////////////////////////////////////////////////////////////////// - SET-UP FUNCTION - //////////////////////////////////////////////////////////////////////////*/ - - function setUp() public virtual override { - Periphery_Test.setUp(); - - // Make campaign owner the caller. - resetPrank(users.campaignOwner); - - // Create the default Merkle contracts. - merkleInstant = createMerkleInstant(); - merkleLL = createMerkleLL(); - merkleLT = createMerkleLT(); - - // Fund the contracts. - deal({ token: address(dai), to: address(merkleInstant), give: defaults.AGGREGATE_AMOUNT() }); - deal({ token: address(dai), to: address(merkleLL), give: defaults.AGGREGATE_AMOUNT() }); - deal({ token: address(dai), to: address(merkleLT), give: defaults.AGGREGATE_AMOUNT() }); - } - - /*////////////////////////////////////////////////////////////////////////// - HELPERS - //////////////////////////////////////////////////////////////////////////*/ - - function claim() internal { - merkleBase.claim{ value: defaults.DEFAULT_SABLIER_FEE() }({ - index: defaults.INDEX1(), - recipient: users.recipient1, - amount: defaults.CLAIM_AMOUNT(), - merkleProof: defaults.index1Proof() - }); - } - - /*////////////////////////////////////////////////////////////////////////// - MERKLE-INSTANT - //////////////////////////////////////////////////////////////////////////*/ - - function computeMerkleInstantAddress() internal view returns (address) { - return computeMerkleInstantAddress( - users.campaignOwner, defaults.MERKLE_ROOT(), defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleInstantAddress(address campaignOwner) internal view returns (address) { - return computeMerkleInstantAddress( - campaignOwner, defaults.MERKLE_ROOT(), defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleInstantAddress(address campaignOwner, uint40 expiration) internal view returns (address) { - return computeMerkleInstantAddress( - campaignOwner, defaults.MERKLE_ROOT(), expiration, defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleInstantAddress( - address campaignOwner, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - return computeMerkleInstantAddress(campaignOwner, defaults.MERKLE_ROOT(), expiration, sablierFee); - } - - function computeMerkleInstantAddress(address campaignOwner, bytes32 merkleRoot) internal view returns (address) { - return computeMerkleInstantAddress( - campaignOwner, merkleRoot, defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleInstantAddress( - address campaignOwner, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - return computeMerkleInstantAddress({ - caller: users.campaignOwner, - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: merkleRoot, - expiration: expiration, - sablierFee: sablierFee - }); - } - - function createMerkleInstant() internal returns (ISablierMerkleInstant) { - return createMerkleInstant(users.campaignOwner, defaults.EXPIRATION()); - } - - function createMerkleInstant(address campaignOwner) internal returns (ISablierMerkleInstant) { - return createMerkleInstant(campaignOwner, defaults.EXPIRATION()); - } - - function createMerkleInstant(uint40 expiration) internal returns (ISablierMerkleInstant) { - return createMerkleInstant(users.campaignOwner, expiration); - } - - function createMerkleInstant(address campaignOwner, uint40 expiration) internal returns (ISablierMerkleInstant) { - return merkleFactory.createMerkleInstant({ - baseParams: defaults.baseParams(campaignOwner, dai, expiration, defaults.MERKLE_ROOT()), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT() - }); - } - - /*////////////////////////////////////////////////////////////////////////// - MERKLE-LL - //////////////////////////////////////////////////////////////////////////*/ - - function computeMerkleLLAddress() internal view returns (address) { - return computeMerkleLLAddress( - users.campaignOwner, defaults.MERKLE_ROOT(), defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleLLAddress(address campaignOwner) internal view returns (address) { - return computeMerkleLLAddress( - campaignOwner, defaults.MERKLE_ROOT(), defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleLLAddress(address campaignOwner, uint40 expiration) internal view returns (address) { - return computeMerkleLLAddress(campaignOwner, defaults.MERKLE_ROOT(), expiration, defaults.DEFAULT_SABLIER_FEE()); - } - - function computeMerkleLLAddress( - address campaignOwner, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - return computeMerkleLLAddress(campaignOwner, defaults.MERKLE_ROOT(), expiration, sablierFee); - } - - function computeMerkleLLAddress(address campaignOwner, bytes32 merkleRoot) internal view returns (address) { - return computeMerkleLLAddress(campaignOwner, merkleRoot, defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE()); - } - - function computeMerkleLLAddress( - address campaignOwner, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - return computeMerkleLLAddress({ - caller: users.campaignOwner, - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: merkleRoot, - expiration: expiration, - sablierFee: sablierFee - }); - } - - function createMerkleLL() internal returns (ISablierMerkleLL) { - return createMerkleLL(users.campaignOwner, defaults.EXPIRATION()); - } - - function createMerkleLL(address campaignOwner) internal returns (ISablierMerkleLL) { - return createMerkleLL(campaignOwner, defaults.EXPIRATION()); - } - - function createMerkleLL(uint40 expiration) internal returns (ISablierMerkleLL) { - return createMerkleLL(users.campaignOwner, expiration); - } - - function createMerkleLL(address campaignOwner, uint40 expiration) internal returns (ISablierMerkleLL) { - return merkleFactory.createMerkleLL({ - baseParams: defaults.baseParams(campaignOwner, dai, expiration, defaults.MERKLE_ROOT()), - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: defaults.schedule(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT() - }); - } - - /*////////////////////////////////////////////////////////////////////////// - MERKLE-LT - //////////////////////////////////////////////////////////////////////////*/ - - function computeMerkleLTAddress() internal view returns (address) { - return computeMerkleLTAddress( - users.campaignOwner, defaults.MERKLE_ROOT(), defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleLTAddress(address campaignOwner) internal view returns (address) { - return computeMerkleLTAddress( - campaignOwner, defaults.MERKLE_ROOT(), defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE() - ); - } - - function computeMerkleLTAddress(address campaignOwner, uint40 expiration) internal view returns (address) { - return computeMerkleLTAddress(campaignOwner, defaults.MERKLE_ROOT(), expiration, defaults.DEFAULT_SABLIER_FEE()); - } - - function computeMerkleLTAddress( - address campaignOwner, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - return computeMerkleLTAddress(campaignOwner, defaults.MERKLE_ROOT(), expiration, sablierFee); - } - - function computeMerkleLTAddress(address campaignOwner, bytes32 merkleRoot) internal view returns (address) { - return computeMerkleLTAddress(campaignOwner, merkleRoot, defaults.EXPIRATION(), defaults.DEFAULT_SABLIER_FEE()); - } - - function computeMerkleLTAddress( - address campaignOwner, - bytes32 merkleRoot, - uint40 expiration, - uint256 sablierFee - ) - internal - view - returns (address) - { - return computeMerkleLTAddress({ - caller: users.campaignOwner, - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: merkleRoot, - expiration: expiration, - sablierFee: sablierFee - }); - } - - function createMerkleLT() internal returns (ISablierMerkleLT) { - return createMerkleLT(users.campaignOwner, defaults.EXPIRATION()); - } - - function createMerkleLT(address campaignOwner) internal returns (ISablierMerkleLT) { - return createMerkleLT(campaignOwner, defaults.EXPIRATION()); - } - - function createMerkleLT(uint40 expiration) internal returns (ISablierMerkleLT) { - return createMerkleLT(users.campaignOwner, expiration); - } - - function createMerkleLT(address campaignOwner, uint40 expiration) internal returns (ISablierMerkleLT) { - return merkleFactory.createMerkleLT({ - baseParams: defaults.baseParams(campaignOwner, dai, expiration, defaults.MERKLE_ROOT()), - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - streamStartTime: defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages: defaults.tranchesWithPercentages(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT() - }); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/constructor.t.sol b/test/periphery/integration/merkle-campaign/factory/constructor.t.sol deleted file mode 100644 index 3d9a58029..000000000 --- a/test/periphery/integration/merkle-campaign/factory/constructor.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { SablierMerkleFactory } from "src/periphery/SablierMerkleFactory.sol"; - -import { MerkleCampaign_Integration_Test } from "../MerkleCampaign.t.sol"; - -contract Constructor_MerkleFactory_Integration_Test is MerkleCampaign_Integration_Test { - function test_Constructor() external { - SablierMerkleFactory constructedFactory = new SablierMerkleFactory(users.admin); - - address actualAdmin = constructedFactory.admin(); - assertEq(actualAdmin, users.admin, "factory admin"); - - uint256 actualDefaultSablierFee = constructedFactory.defaultSablierFee(); - assertEq(actualDefaultSablierFee, 0, "default sablier fee"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.t.sol b/test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.t.sol deleted file mode 100644 index 73242a459..000000000 --- a/test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.t.sol +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleInstant } from "src/periphery/interfaces/ISablierMerkleInstant.sol"; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { MerkleBase } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract CreateMerkleInstant_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_NameTooLong() external { - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams(); - uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT(); - uint256 recipientCount = defaults.RECIPIENT_COUNT(); - - baseParams.name = "this string is longer than 32 characters"; - - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_CampaignNameTooLong.selector, bytes(baseParams.name).length, 32 - ) - ); - - merkleFactory.createMerkleInstant({ - baseParams: baseParams, - aggregateAmount: aggregateAmount, - recipientCount: recipientCount - }); - } - - /// @dev This test works because a default MerkleInstant contract is deployed in {Integration_Test.setUp} - function test_RevertGiven_CampaignAlreadyExists() external whenNameNotTooLong { - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams(); - uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT(); - uint256 recipientCount = defaults.RECIPIENT_COUNT(); - - // Expect a revert due to CREATE2. - vm.expectRevert(); - merkleFactory.createMerkleInstant({ - baseParams: baseParams, - aggregateAmount: aggregateAmount, - recipientCount: recipientCount - }); - } - - function test_GivenCustomFeeSet( - address campaignOwner, - uint40 expiration, - uint256 customFee - ) - external - whenNameNotTooLong - givenCampaignNotExists - { - // Set the Sablier fee to 0 for this test. - resetPrank(users.admin); - merkleFactory.setSablierFeeByUser(users.campaignOwner, customFee); - - resetPrank(users.campaignOwner); - address expectedMerkleInstant = computeMerkleInstantAddress(campaignOwner, expiration, customFee); - - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams({ - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: defaults.MERKLE_ROOT(), - expiration: expiration - }); - - // It should emit a {CreateMerkleInstant} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleInstant({ - merkleInstant: ISablierMerkleInstant(expectedMerkleInstant), - baseParams: baseParams, - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT(), - sablierFee: customFee - }); - - ISablierMerkleInstant actualInstant = createMerkleInstant(campaignOwner, expiration); - assertGt(address(actualInstant).code.length, 0, "MerkleInstant contract not created"); - assertEq( - address(actualInstant), expectedMerkleInstant, "MerkleInstant contract does not match computed address" - ); - - // It should create the campaign with custom fee. - assertEq(actualInstant.SABLIER_FEE(), customFee, "sablier fee"); - - // It should set the current factory address. - assertEq(actualInstant.FACTORY(), address(merkleFactory), "factory"); - } - - function test_GivenCustomFeeNotSet( - address campaignOwner, - uint40 expiration - ) - external - whenNameNotTooLong - givenCampaignNotExists - { - address expectedMerkleInstant = computeMerkleInstantAddress(campaignOwner, expiration); - - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams({ - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: defaults.MERKLE_ROOT(), - expiration: expiration - }); - - // It should emit a {CreateMerkleInstant} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleInstant({ - merkleInstant: ISablierMerkleInstant(expectedMerkleInstant), - baseParams: baseParams, - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT(), - sablierFee: defaults.DEFAULT_SABLIER_FEE() - }); - - ISablierMerkleInstant actualInstant = createMerkleInstant(campaignOwner, expiration); - assertGt(address(actualInstant).code.length, 0, "MerkleInstant contract not created"); - assertEq( - address(actualInstant), expectedMerkleInstant, "MerkleInstant contract does not match computed address" - ); - - // It should create the campaign with custom fee. - assertEq(actualInstant.SABLIER_FEE(), defaults.DEFAULT_SABLIER_FEE(), "default sablier fee"); - - // It should set the current factory address. - assertEq(actualInstant.FACTORY(), address(merkleFactory), "factory"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.tree b/test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.tree deleted file mode 100644 index 7ccf9b6af..000000000 --- a/test/periphery/integration/merkle-campaign/factory/create-merkle-instant/createMerkleInstant.tree +++ /dev/null @@ -1,15 +0,0 @@ -CreateMerkleInstant_Integration_Test -├── when name too long -│ └── it should revert -└── when name not too long - ├── given campaign already exists - │ └── it should revert - └── given campaign not exists - ├── given custom fee set - │ ├── it should create the campaign with custom fee - │ ├── it should set the current factory address - │ └── it should emit a {CreateMerkleInstant} event - └── given custom fee not set - ├── it should create the campaign with default fee - ├── it should set the current factory address - └── it should emit a {CreateMerkleInstant} event diff --git a/test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.t.sol b/test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.t.sol deleted file mode 100644 index 3ec8b3710..000000000 --- a/test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.t.sol +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleLL } from "src/periphery/interfaces/ISablierMerkleLL.sol"; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { MerkleBase, MerkleLL } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract CreateMerkleLL_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_NameTooLong() external { - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams(); - bool cancelable = defaults.CANCELABLE(); - bool transferable = defaults.TRANSFERABLE(); - MerkleLL.Schedule memory schedule = defaults.schedule(); - uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT(); - uint256 recipientCount = defaults.RECIPIENT_COUNT(); - - baseParams.name = "this string is longer than 32 characters"; - - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_CampaignNameTooLong.selector, bytes(baseParams.name).length, 32 - ) - ); - - merkleFactory.createMerkleLL({ - baseParams: baseParams, - lockup: lockup, - cancelable: cancelable, - transferable: transferable, - schedule: schedule, - aggregateAmount: aggregateAmount, - recipientCount: recipientCount - }); - } - - /// @dev This test works because a default MerkleLL contract is deployed in {Integration_Test.setUp} - function test_RevertGiven_CampaignAlreadyExists() external whenNameNotTooLong { - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams(); - bool cancelable = defaults.CANCELABLE(); - bool transferable = defaults.TRANSFERABLE(); - MerkleLL.Schedule memory schedule = defaults.schedule(); - uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT(); - uint256 recipientCount = defaults.RECIPIENT_COUNT(); - - // Expect a revert due to CREATE2. - vm.expectRevert(); - merkleFactory.createMerkleLL({ - baseParams: baseParams, - lockup: lockup, - cancelable: cancelable, - transferable: transferable, - schedule: schedule, - aggregateAmount: aggregateAmount, - recipientCount: recipientCount - }); - } - - function test_GivenCustomFeeSet( - address campaignOwner, - uint40 expiration, - uint256 customFee - ) - external - whenNameNotTooLong - givenCampaignNotExists - { - // Set the Sablier fee to 0 for this test. - resetPrank(users.admin); - merkleFactory.setSablierFeeByUser(users.campaignOwner, customFee); - - resetPrank(users.campaignOwner); - address expectedLL = computeMerkleLLAddress(campaignOwner, expiration, customFee); - - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams({ - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: defaults.MERKLE_ROOT(), - expiration: expiration - }); - - // It should emit a {CreateMerkleLL} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleLL({ - merkleLL: ISablierMerkleLL(expectedLL), - baseParams: baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: defaults.schedule(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT(), - sablierFee: customFee - }); - - ISablierMerkleLL actualLL = createMerkleLL(campaignOwner, expiration); - assertGt(address(actualLL).code.length, 0, "MerkleLL contract not created"); - assertEq(address(actualLL), expectedLL, "MerkleLL contract does not match computed address"); - - // It should create the campaign with custom fee. - assertEq(actualLL.SABLIER_FEE(), customFee, "sablier fee"); - - // It should set the current factory address. - assertEq(actualLL.FACTORY(), address(merkleFactory), "factory"); - } - - function test_GivenCustomFeeNotSet( - address campaignOwner, - uint40 expiration - ) - external - whenNameNotTooLong - givenCampaignNotExists - { - address expectedLL = computeMerkleLLAddress(campaignOwner, expiration); - - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams({ - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: defaults.MERKLE_ROOT(), - expiration: expiration - }); - - // It should emit a {CreateMerkleInstant} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleLL({ - merkleLL: ISablierMerkleLL(expectedLL), - baseParams: baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: defaults.schedule(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT(), - sablierFee: defaults.DEFAULT_SABLIER_FEE() - }); - - ISablierMerkleLL actualLL = createMerkleLL(campaignOwner, expiration); - assertGt(address(actualLL).code.length, 0, "MerkleLL contract not created"); - assertEq(address(actualLL), expectedLL, "MerkleLL contract does not match computed address"); - - // It should create the campaign with custom fee. - assertEq(actualLL.SABLIER_FEE(), defaults.DEFAULT_SABLIER_FEE(), "default sablier fee"); - - // It should set the current factory address. - assertEq(actualLL.FACTORY(), address(merkleFactory), "factory"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.tree b/test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.tree deleted file mode 100644 index e6350cf9d..000000000 --- a/test/periphery/integration/merkle-campaign/factory/create-merkle-ll/createMerkleLL.tree +++ /dev/null @@ -1,15 +0,0 @@ -CreateMerkleLL_Integration_Test -├── when name too long -│ └── it should revert -└── when name not too long - ├── given campaign already exists - │ └── it should revert - └── given campaign not exists - ├── given custom fee set - │ ├── it should create the campaign with custom fee - │ ├── it should set the current factory address - │ └── it should emit a {CreateMerkleLL} event - └── given custom fee not set - ├── it should create the campaign with default fee - ├── it should set the current factory address - └── it should emit a {CreateMerkleLL} event diff --git a/test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.t.sol b/test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.t.sol deleted file mode 100644 index 71a88e301..000000000 --- a/test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.t.sol +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { ISablierMerkleLT } from "src/periphery/interfaces/ISablierMerkleLT.sol"; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { MerkleBase, MerkleLT } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract CreateMerkleLT_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_NameTooLong() external { - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams(); - bool cancelable = defaults.CANCELABLE(); - bool transferable = defaults.TRANSFERABLE(); - uint40 streamStartTime = defaults.STREAM_START_TIME_ZERO(); - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages(); - uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT(); - uint256 recipientCount = defaults.RECIPIENT_COUNT(); - - baseParams.name = "this string is longer than 32 characters"; - - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_CampaignNameTooLong.selector, bytes(baseParams.name).length, 32 - ) - ); - - merkleFactory.createMerkleLT( - baseParams, - lockup, - cancelable, - transferable, - streamStartTime, - tranchesWithPercentages, - aggregateAmount, - recipientCount - ); - } - - /// @dev This test works because a default MerkleLT contract is deployed in {Integration_Test.setUp} - function test_RevertGiven_CampaignAlreadyExists() external whenNameNotTooLong { - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams(); - bool cancelable = defaults.CANCELABLE(); - bool transferable = defaults.TRANSFERABLE(); - uint40 streamStartTime = defaults.STREAM_START_TIME_ZERO(); - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages(); - uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT(); - uint256 recipientCount = defaults.RECIPIENT_COUNT(); - - // Expect a revert due to CREATE2. - vm.expectRevert(); - merkleFactory.createMerkleLT( - baseParams, - lockup, - cancelable, - transferable, - streamStartTime, - tranchesWithPercentages, - aggregateAmount, - recipientCount - ); - } - - function test_GivenCustomFeeSet( - address campaignOwner, - uint40 expiration, - uint256 customFee - ) - external - whenNameNotTooLong - givenCampaignNotExists - { - // Set the Sablier fee to 0 for this test. - resetPrank(users.admin); - merkleFactory.setSablierFeeByUser(users.campaignOwner, customFee); - - resetPrank(users.campaignOwner); - address expectedLT = computeMerkleLTAddress(campaignOwner, expiration, customFee); - - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams({ - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: defaults.MERKLE_ROOT(), - expiration: expiration - }); - - // It should emit a {CreateMerkleLT} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleLT({ - merkleLT: ISablierMerkleLT(expectedLT), - baseParams: baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - streamStartTime: defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages: defaults.tranchesWithPercentages(), - totalDuration: defaults.TOTAL_DURATION(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT(), - sablierFee: customFee - }); - - ISablierMerkleLT actualLT = createMerkleLT(campaignOwner, expiration); - assertGt(address(actualLT).code.length, 0, "MerkleLT contract not created"); - assertEq(address(actualLT), expectedLT, "MerkleLT contract does not match computed address"); - - // It should create the campaign with custom fee. - assertEq(actualLT.SABLIER_FEE(), customFee, "sablier fee"); - // It should set the current factory address. - assertEq(actualLT.FACTORY(), address(merkleFactory), "factory"); - } - - function test_GivenCustomFeeNotSet( - address campaignOwner, - uint40 expiration - ) - external - whenNameNotTooLong - givenCampaignNotExists - { - address expectedLT = computeMerkleLTAddress(campaignOwner, expiration); - - MerkleBase.ConstructorParams memory baseParams = defaults.baseParams({ - campaignOwner: campaignOwner, - asset_: dai, - merkleRoot: defaults.MERKLE_ROOT(), - expiration: expiration - }); - - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.CreateMerkleLT({ - merkleLT: ISablierMerkleLT(expectedLT), - baseParams: baseParams, - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - streamStartTime: defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages: defaults.tranchesWithPercentages(), - totalDuration: defaults.TOTAL_DURATION(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT(), - sablierFee: defaults.DEFAULT_SABLIER_FEE() - }); - - ISablierMerkleLT actualLT = createMerkleLT(campaignOwner, expiration); - assertGt(address(actualLT).code.length, 0, "MerkleLT contract not created"); - assertEq(address(actualLT), expectedLT, "MerkleLT contract does not match computed address"); - - // It should create the campaign with custom fee. - assertEq(actualLT.SABLIER_FEE(), defaults.DEFAULT_SABLIER_FEE(), "default sablier fee"); - // It should set the current factory address. - assertEq(actualLT.FACTORY(), address(merkleFactory), "factory"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.tree b/test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.tree deleted file mode 100644 index 9ccdea759..000000000 --- a/test/periphery/integration/merkle-campaign/factory/create-merkle-lt/createMerkleLT.tree +++ /dev/null @@ -1,15 +0,0 @@ -CreateMerkleLT_Integration_Test -├── when name too long -│ └── it should revert -└── when name not too long - ├── given campaign already exists - │ └── it should revert - └── given campaign not exists - ├── given custom fee set - │ ├── it should create the campaign with custom fee - │ ├── it should set the current factory address - │ └── it should emit a {CreateMerkleLT} event - └── given custom fee not set - ├── it should create the campaign with default fee - ├── it should set the current factory address - └── it should emit a {CreateMerkleLT} event diff --git a/test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.t.sol b/test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.t.sol deleted file mode 100644 index 507a6525a..000000000 --- a/test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { MAX_UD2x18, ud2x18 } from "@prb/math/src/UD2x18.sol"; - -import { MerkleLT } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract IsPercentagesSum100_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_PercentagesSumOverflows() public { - MerkleLT.TrancheWithPercentage[] memory tranches = defaults.tranchesWithPercentages(); - tranches[0].unlockPercentage = MAX_UD2x18; - - vm.expectRevert(); - merkleFactory.isPercentagesSum100(tranches); - } - - function test_WhenPercentagesSumLessThan100Pct() - external - view - whenPercentagesSumNotOverflow - whenPercentagesSumNot100Pct - { - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages(); - tranchesWithPercentages[0].unlockPercentage = ud2x18(0.05e18); - tranchesWithPercentages[1].unlockPercentage = ud2x18(0.2e18); - - assertFalse(merkleFactory.isPercentagesSum100(tranchesWithPercentages), "isPercentagesSum100"); - } - - function test_WhenPercentagesSumGreaterThan100Pct() - external - view - whenPercentagesSumNotOverflow - whenPercentagesSumNot100Pct - { - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages(); - tranchesWithPercentages[0].unlockPercentage = ud2x18(0.5e18); - tranchesWithPercentages[1].unlockPercentage = ud2x18(0.6e18); - - assertFalse(merkleFactory.isPercentagesSum100(tranchesWithPercentages), "isPercentagesSum100"); - } - - function test_WhenPercentagesSum100Pct() external view whenPercentagesSumNotOverflow { - assertTrue(merkleFactory.isPercentagesSum100(defaults.tranchesWithPercentages()), "isPercentagesSum100"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.tree b/test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.tree deleted file mode 100644 index e9771a341..000000000 --- a/test/periphery/integration/merkle-campaign/factory/is-percentages-sum-100/isPercentagesSum100.tree +++ /dev/null @@ -1,11 +0,0 @@ -IsPercentagesSum100_Integration_Test -├── when percentages sum overflows -│ └── it should revert -└── when percentages sum not overflow - ├── when percentages sum not 100 pct - │ ├── when percentages sum less than 100 pct - │ │ └── it should return false - │ └── when percentages sum greater than 100 pct - │ └── it should return false - └── when percentages sum 100 pct - └── it should return true diff --git a/test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.t.sol b/test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.t.sol deleted file mode 100644 index 283f329e8..000000000 --- a/test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.t.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors as CoreErrors } from "src/core/libraries/Errors.sol"; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { MerkleFactory } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract ResetSablierFeeByUser_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_CallerNotAdmin() external { - resetPrank({ msgSender: users.eve }); - vm.expectRevert(abi.encodeWithSelector(CoreErrors.CallerNotAdmin.selector, users.admin, users.eve)); - merkleFactory.resetSablierFeeByUser({ campaignCreator: users.campaignOwner }); - } - - function test_WhenNotEnabled() external whenCallerAdmin { - // It should emit a {ResetSablierFee} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.ResetSablierFee({ admin: users.admin, campaignCreator: users.campaignOwner }); - - // Reset the Sablier fee. - merkleFactory.resetSablierFeeByUser({ campaignCreator: users.campaignOwner }); - - MerkleFactory.SablierFeeByUser memory sablierFee = merkleFactory.sablierFeeByUser(users.campaignOwner); - - // It should return false. - assertFalse(sablierFee.enabled, "enabled"); - - // It should return 0 for the Sablier fee. - assertEq(sablierFee.fee, 0, "fee"); - } - - function test_WhenEnabled() external whenCallerAdmin { - // Enable the Sablier fee. - merkleFactory.setSablierFeeByUser({ campaignCreator: users.campaignOwner, fee: 1 ether }); - - // Check that its enabled. - MerkleFactory.SablierFeeByUser memory sablierFee = merkleFactory.sablierFeeByUser(users.campaignOwner); - - assertTrue(sablierFee.enabled, "enabled"); - assertEq(sablierFee.fee, 1 ether, "fee"); - - // It should emit a {ResetSablierFee} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.ResetSablierFee({ admin: users.admin, campaignCreator: users.campaignOwner }); - - // Reset the Sablier fee. - merkleFactory.resetSablierFeeByUser({ campaignCreator: users.campaignOwner }); - - sablierFee = merkleFactory.sablierFeeByUser(users.campaignOwner); - - // It should disable the Sablier fee - assertFalse(sablierFee.enabled, "enabled"); - - // It should set the Sablier fee to 0 - assertEq(sablierFee.fee, 0, "fee"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.tree b/test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.tree deleted file mode 100644 index 623e29345..000000000 --- a/test/periphery/integration/merkle-campaign/factory/reset-fee-by-user/resetSablierFeeByUser.tree +++ /dev/null @@ -1,12 +0,0 @@ -ResetSablierFeeByUser_Integration_Test -├── when caller not admin -│ └── it should revert -└── when caller admin - ├── when not enabled - │ ├── it should return false - │ ├── it should return 0 for the Sablier fee - │ └── it should emit a {ResetSablierFee} event - └── when enabled - ├── it should disable the Sablier fee - ├── it should set the Sablier fee to 0 - └── it should emit a {ResetSablierFee} event diff --git a/test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.t.sol b/test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.t.sol deleted file mode 100644 index 2b8edced8..000000000 --- a/test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.t.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors as CoreErrors } from "src/core/libraries/Errors.sol"; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract SetDefaultSablierFee_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_CallerNotAdmin() external { - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - resetPrank({ msgSender: users.eve }); - vm.expectRevert(abi.encodeWithSelector(CoreErrors.CallerNotAdmin.selector, users.admin, users.eve)); - merkleFactory.setDefaultSablierFee({ defaultFee: sablierFee }); - } - - function test_WhenCallerAdmin() external { - resetPrank({ msgSender: users.admin }); - - // It should emit a {SetDefaultSablierFee} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.SetDefaultSablierFee({ - admin: users.admin, - defaultSablierFee: defaults.DEFAULT_SABLIER_FEE() - }); - - merkleFactory.setDefaultSablierFee({ defaultFee: defaults.DEFAULT_SABLIER_FEE() }); - - // It should set the default Sablier fee. - assertEq(merkleFactory.defaultSablierFee(), defaults.DEFAULT_SABLIER_FEE(), "sablier fee"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.tree b/test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.tree deleted file mode 100644 index 5c7a8d5f8..000000000 --- a/test/periphery/integration/merkle-campaign/factory/set-default-sablier-fee/setDefaultSablierFee.tree +++ /dev/null @@ -1,6 +0,0 @@ -SetDefaultSablierFee_Integration_Test -├── when caller not admin -│ └── it should revert -└── when caller admin - ├── it should set the default Sablier fee - └── it should emit a {SetDefaultSablierFee} event diff --git a/test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.t.sol b/test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.t.sol deleted file mode 100644 index 6b34830a7..000000000 --- a/test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.t.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors as CoreErrors } from "src/core/libraries/Errors.sol"; - -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { MerkleFactory } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract SetSablierFeeByUser_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_CallerNotAdmin() external { - resetPrank({ msgSender: users.eve }); - vm.expectRevert(abi.encodeWithSelector(CoreErrors.CallerNotAdmin.selector, users.admin, users.eve)); - merkleFactory.setSablierFeeByUser({ campaignCreator: users.campaignOwner, fee: 0 }); - } - - function test_WhenNotEnabled() external whenCallerAdmin { - // It should emit a {SetSablierFee} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.SetSablierFeeForUser({ - admin: users.admin, - campaignCreator: users.campaignOwner, - sablierFee: 0 - }); - - // Set the Sablier fee. - merkleFactory.setSablierFeeByUser({ campaignCreator: users.campaignOwner, fee: 0 }); - - MerkleFactory.SablierFeeByUser memory sablierFee = merkleFactory.sablierFeeByUser(users.campaignOwner); - - // It should enable the Sablier fee. - assertTrue(sablierFee.enabled, "enabled"); - - // It should set the Sablier fee. - assertEq(sablierFee.fee, 0, "fee"); - } - - function test_WhenEnabled() external whenCallerAdmin { - // Enable the Sablier fee. - merkleFactory.setSablierFeeByUser({ campaignCreator: users.campaignOwner, fee: 0.001 ether }); - // Check that its enabled. - MerkleFactory.SablierFeeByUser memory sablierFee = merkleFactory.sablierFeeByUser(users.campaignOwner); - assertTrue(sablierFee.enabled, "enabled"); - assertEq(sablierFee.fee, 0.001 ether, "fee"); - - // It should emit a {SetSablierFee} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.SetSablierFeeForUser({ - admin: users.admin, - campaignCreator: users.campaignOwner, - sablierFee: 1 ether - }); - - // Now set it to another fee. - merkleFactory.setSablierFeeByUser({ campaignCreator: users.campaignOwner, fee: 1 ether }); - - sablierFee = merkleFactory.sablierFeeByUser(users.campaignOwner); - - // It should enable the Sablier fee. - assertTrue(sablierFee.enabled, "enabled"); - - // It should set the Sablier fee. - assertEq(sablierFee.fee, 1 ether, "fee"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.tree b/test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.tree deleted file mode 100644 index 9c29fd57c..000000000 --- a/test/periphery/integration/merkle-campaign/factory/set-fee-by-user/setSablierFeeByUser.tree +++ /dev/null @@ -1,11 +0,0 @@ -SetSablierFeeByUser_Integration_Test -├── when caller not admin -│ └── it should revert -└── when caller admin - ├── when not enabled - │ ├── it should enable the Sablier fee - │ ├── it should set the Sablier fee - │ └── it should emit a {SetSablierFee} event - └── when enabled - ├── it should set the Sablier fee - └── it should emit a {SetSablierFee} event diff --git a/test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.t.sol b/test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.t.sol deleted file mode 100644 index a8d961760..000000000 --- a/test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.t.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors as CoreErrors } from "src/core/libraries/Errors.sol"; - -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; -import { Errors } from "src/periphery/libraries/Errors.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -contract WithdrawFees_Integration_Test is MerkleCampaign_Integration_Test { - function setUp() public virtual override { - MerkleCampaign_Integration_Test.setUp(); - - // Set the `merkleBase` to the merkleLL contract to use it in the tests. - merkleBase = ISablierMerkleBase(merkleLL); - - // Claim to collect some fees. - resetPrank(users.recipient); - claim(); - } - - function test_RevertWhen_CallerNotAdmin() external { - resetPrank(users.eve); - - vm.expectRevert(abi.encodeWithSelector(CoreErrors.CallerNotAdmin.selector, users.admin, users.eve)); - merkleFactory.withdrawFees(users.eve, merkleBase); - } - - function test_RevertWhen_WithdrawalAddressZero() external whenCallerAdmin { - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleFactory_WithdrawToZeroAddress.selector)); - merkleFactory.withdrawFees(payable(address(0)), merkleBase); - } - - function test_RevertWhen_ProvidedMerkleLockupNotValid() external whenCallerAdmin whenWithdrawalAddressNotZero { - vm.expectRevert(); - merkleFactory.withdrawFees(users.eve, ISablierMerkleBase(users.eve)); - } - - function test_WhenProvidedAddressNotContract() external whenCallerAdmin whenProvidedMerkleLockupValid { - uint256 previousToBalance = users.eve.balance; - - // It should emit {WithdrawSablierFees} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.WithdrawSablierFees({ - admin: users.admin, - merkleBase: merkleBase, - to: users.eve, - sablierFees: defaults.DEFAULT_SABLIER_FEE() - }); - - merkleFactory.withdrawFees(users.eve, merkleBase); - - // It should set the ETH balance to 0. - assertEq(address(merkleBase).balance, 0, "merkle lockup eth balance"); - // It should transfer fee collected in ETH to the provided address. - assertEq(users.eve.balance, previousToBalance + defaults.DEFAULT_SABLIER_FEE(), "eth balance"); - } - - function test_RevertWhen_ProvidedAddressNotImplementReceiveEth() - external - whenCallerAdmin - whenProvidedMerkleLockupValid - whenProvidedAddressContract - { - address payable noReceiveEth = payable(address(contractWithoutReceiveEth)); - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_FeeWithdrawFailed.selector, noReceiveEth, address(merkleBase).balance - ) - ); - merkleFactory.withdrawFees(noReceiveEth, merkleBase); - } - - function test_WhenProvidedAddressImplementReceiveEth() - external - whenCallerAdmin - whenProvidedMerkleLockupValid - whenProvidedAddressContract - { - address payable receiveEth = payable(address(contractWithReceiveEth)); - - // It should emit {WithdrawSablierFees} event. - vm.expectEmit({ emitter: address(merkleFactory) }); - emit ISablierMerkleFactory.WithdrawSablierFees({ - admin: users.admin, - merkleBase: merkleBase, - to: receiveEth, - sablierFees: defaults.DEFAULT_SABLIER_FEE() - }); - - merkleFactory.withdrawFees(receiveEth, merkleBase); - - // It should set the ETH balance to 0. - assertEq(address(merkleBase).balance, 0, "merkle lockup eth balance"); - // It should transfer fee collected in ETH to the provided address. - assertEq(receiveEth.balance, defaults.DEFAULT_SABLIER_FEE(), "eth balance"); - } -} diff --git a/test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.tree b/test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.tree deleted file mode 100644 index e07cc3fba..000000000 --- a/test/periphery/integration/merkle-campaign/factory/withdraw-fees/withdrawFees.tree +++ /dev/null @@ -1,21 +0,0 @@ -WithdrawFees_Integration_Test -├── when caller not admin -│ └── it should revert -└── when caller admin - ├── when withdrawal address zero - │ └── it should revert - └── when withdrawal address not zero - ├── when provided merkle lockup not valid - │ └── it should revert - └── when provided merkle lockup valid - ├── when provided address not contract - │ ├── it should transfer fee collected in ETH to the provided address - │ ├── it should set the ETH balance to 0 - │ └── it should emit {WithdrawSablierFees} event - └── when provided address contract - ├── when provided address not implement receive eth - │ └── it should revert - └── when provided address implement receive eth - ├── it should transfer fee collected in ETH to the provided address - ├── it should set the ETH balance to 0 - └── it should emit {WithdrawSablierFees} event diff --git a/test/periphery/integration/merkle-campaign/instant/MerkleInstant.t.sol b/test/periphery/integration/merkle-campaign/instant/MerkleInstant.t.sol deleted file mode 100644 index f032fda98..000000000 --- a/test/periphery/integration/merkle-campaign/instant/MerkleInstant.t.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { MerkleCampaign_Integration_Test } from "./../MerkleCampaign.t.sol"; -import { Clawback_Integration_Test } from "./../shared/clawback/clawback.t.sol"; -import { GetFirstClaimTime_Integration_Test } from "./../shared/get-first-claim-time/getFirstClaimTime.t.sol"; -import { HasClaimed_Integration_Test } from "./../shared/has-claimed/hasClaimed.t.sol"; -import { HasExpired_Integration_Test } from "./../shared/has-expired/hasExpired.t.sol"; -import { WithdrawFees_Integration_Test } from "./../shared/withdraw-fees/withdrawFees.t.sol"; - -/*////////////////////////////////////////////////////////////////////////// - NON-SHARED TESTS -//////////////////////////////////////////////////////////////////////////*/ - -abstract contract MerkleInstant_Integration_Shared_Test is MerkleCampaign_Integration_Test { - function setUp() public virtual override { - MerkleCampaign_Integration_Test.setUp(); - - // Cast the {merkleInstant} contract as {ISablierMerkleBase} - merkleBase = ISablierMerkleBase(merkleInstant); - } -} - -/*////////////////////////////////////////////////////////////////////////// - SHARED TESTS -//////////////////////////////////////////////////////////////////////////*/ - -contract Clawback_MerkleInstant_Integration_Test is MerkleInstant_Integration_Shared_Test, Clawback_Integration_Test { - function setUp() public override(MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleInstant_Integration_Shared_Test.setUp(); - } -} - -contract GetFirstClaimTime_MerkleInstant_Integration_Test is - MerkleInstant_Integration_Shared_Test, - GetFirstClaimTime_Integration_Test -{ - function setUp() public override(MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleInstant_Integration_Shared_Test.setUp(); - } -} - -contract HasClaimed_MerkleInstant_Integration_Test is - MerkleInstant_Integration_Shared_Test, - HasClaimed_Integration_Test -{ - function setUp() public override(MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleInstant_Integration_Shared_Test.setUp(); - } -} - -contract HasExpired_MerkleInstant_Integration_Test is - MerkleInstant_Integration_Shared_Test, - HasExpired_Integration_Test -{ - function setUp() public override(MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleInstant_Integration_Shared_Test.setUp(); - } -} - -contract WithdrawFees_MerkleInstant_Integration_Test is - MerkleInstant_Integration_Shared_Test, - WithdrawFees_Integration_Test -{ - function setUp() public override(MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleInstant_Integration_Shared_Test.setUp(); - } -} diff --git a/test/periphery/integration/merkle-campaign/instant/claim/claim.t.sol b/test/periphery/integration/merkle-campaign/instant/claim/claim.t.sol deleted file mode 100644 index 9a60c983e..000000000 --- a/test/periphery/integration/merkle-campaign/instant/claim/claim.t.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleInstant } from "src/periphery/interfaces/ISablierMerkleInstant.sol"; - -import { Claim_Integration_Test } from "./../../shared/claim/claim.t.sol"; -import { MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test } from "./../MerkleInstant.t.sol"; - -contract Claim_MerkleInstant_Integration_Test is Claim_Integration_Test, MerkleInstant_Integration_Shared_Test { - function setUp() public virtual override(MerkleInstant_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleInstant_Integration_Shared_Test.setUp(); - } - - function test_Claim() - external - givenCampaignNotExpired - givenMsgValueNotLessThanSablierFee - givenRecipientNotClaimed - whenIndexValid - whenRecipientValid - whenAmountValid - whenMerkleProofValid - { - uint256 previousFeeAccrued = address(merkleInstant).balance; - - vm.expectEmit({ emitter: address(merkleInstant) }); - emit ISablierMerkleInstant.Claim(defaults.INDEX1(), users.recipient1, defaults.CLAIM_AMOUNT()); - - expectCallToTransfer({ to: users.recipient1, value: defaults.CLAIM_AMOUNT() }); - expectCallToClaimWithMsgValue(address(merkleInstant), defaults.DEFAULT_SABLIER_FEE()); - claim(); - - assertTrue(merkleInstant.hasClaimed(defaults.INDEX1()), "not claimed"); - - assertEq(address(merkleInstant).balance, previousFeeAccrued + defaults.DEFAULT_SABLIER_FEE(), "fee collected"); - } -} diff --git a/test/periphery/integration/merkle-campaign/instant/constructor.t.sol b/test/periphery/integration/merkle-campaign/instant/constructor.t.sol deleted file mode 100644 index c4917d854..000000000 --- a/test/periphery/integration/merkle-campaign/instant/constructor.t.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { SablierMerkleInstant } from "src/periphery/SablierMerkleInstant.sol"; - -import { MerkleCampaign_Integration_Test } from "../MerkleCampaign.t.sol"; - -contract Constructor_MerkleInstant_Integration_Test is MerkleCampaign_Integration_Test { - /// @dev Needed to prevent "Stack too deep" error - struct Vars { - address actualAdmin; - address actualAsset; - uint40 actualExpiration; - address actualFactory; - string actualIpfsCID; - bytes32 actualMerkleRoot; - string actualName; - uint256 actualSablierFee; - address expectedAdmin; - address expectedAsset; - uint40 expectedExpiration; - address expectedFactory; - string expectedIpfsCID; - bytes32 expectedMerkleRoot; - bytes32 expectedName; - uint256 expectedSablierFee; - } - - function test_Constructor() external { - // Make Factory the caller for the constructor test. - resetPrank(address(merkleFactory)); - - SablierMerkleInstant constructedInstant = - new SablierMerkleInstant(defaults.baseParams(), defaults.DEFAULT_SABLIER_FEE()); - - Vars memory vars; - - vars.actualAdmin = constructedInstant.admin(); - vars.expectedAdmin = users.campaignOwner; - assertEq(vars.actualAdmin, vars.expectedAdmin, "admin"); - - vars.actualAsset = address(constructedInstant.ASSET()); - vars.expectedAsset = address(dai); - assertEq(vars.actualAsset, vars.expectedAsset, "asset"); - - vars.actualExpiration = constructedInstant.EXPIRATION(); - vars.expectedExpiration = defaults.EXPIRATION(); - assertEq(vars.actualExpiration, vars.expectedExpiration, "expiration"); - - vars.actualFactory = constructedInstant.FACTORY(); - vars.expectedFactory = address(merkleFactory); - assertEq(vars.actualFactory, vars.expectedFactory, "factory"); - - vars.actualIpfsCID = constructedInstant.ipfsCID(); - vars.expectedIpfsCID = defaults.IPFS_CID(); - assertEq(vars.actualIpfsCID, vars.expectedIpfsCID, "ipfsCID"); - - vars.actualMerkleRoot = constructedInstant.MERKLE_ROOT(); - vars.expectedMerkleRoot = defaults.MERKLE_ROOT(); - assertEq(vars.actualMerkleRoot, vars.expectedMerkleRoot, "merkleRoot"); - - vars.actualName = constructedInstant.name(); - vars.expectedName = defaults.NAME_BYTES32(); - assertEq(bytes32(abi.encodePacked(vars.actualName)), vars.expectedName, "name"); - - vars.actualSablierFee = constructedInstant.SABLIER_FEE(); - vars.expectedSablierFee = defaults.DEFAULT_SABLIER_FEE(); - assertEq(vars.actualSablierFee, vars.expectedSablierFee, "sablierFee"); - } -} diff --git a/test/periphery/integration/merkle-campaign/ll/MerkleLL.t.sol b/test/periphery/integration/merkle-campaign/ll/MerkleLL.t.sol deleted file mode 100644 index 107750298..000000000 --- a/test/periphery/integration/merkle-campaign/ll/MerkleLL.t.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { MerkleCampaign_Integration_Test } from "./../MerkleCampaign.t.sol"; -import { Clawback_Integration_Test } from "./../shared/clawback/clawback.t.sol"; -import { GetFirstClaimTime_Integration_Test } from "./../shared/get-first-claim-time/getFirstClaimTime.t.sol"; -import { HasClaimed_Integration_Test } from "./../shared/has-claimed/hasClaimed.t.sol"; -import { HasExpired_Integration_Test } from "./../shared/has-expired/hasExpired.t.sol"; -import { WithdrawFees_Integration_Test } from "./../shared/withdraw-fees/withdrawFees.t.sol"; - -/*////////////////////////////////////////////////////////////////////////// - NON-SHARED TESTS -//////////////////////////////////////////////////////////////////////////*/ - -abstract contract MerkleLL_Integration_Shared_Test is MerkleCampaign_Integration_Test { - function setUp() public virtual override { - MerkleCampaign_Integration_Test.setUp(); - - // Cast the {MerkleLL} contract as {ISablierMerkleBase} - merkleBase = ISablierMerkleBase(merkleLL); - } -} - -/*////////////////////////////////////////////////////////////////////////// - SHARED TESTS -//////////////////////////////////////////////////////////////////////////*/ - -contract Clawback_MerkleLL_Integration_Test is MerkleLL_Integration_Shared_Test, Clawback_Integration_Test { - function setUp() public override(MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLL_Integration_Shared_Test.setUp(); - } -} - -contract GetFirstClaimTime_MerkleLL_Integration_Test is - MerkleLL_Integration_Shared_Test, - GetFirstClaimTime_Integration_Test -{ - function setUp() public override(MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLL_Integration_Shared_Test.setUp(); - } -} - -contract HasClaimed_MerkleLL_Integration_Test is MerkleLL_Integration_Shared_Test, HasClaimed_Integration_Test { - function setUp() public override(MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLL_Integration_Shared_Test.setUp(); - } -} - -contract HasExpired_MerkleLL_Integration_Test is MerkleLL_Integration_Shared_Test, HasExpired_Integration_Test { - function setUp() public override(MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLL_Integration_Shared_Test.setUp(); - } -} - -contract WithdrawFees_MerkleLL_Integration_Test is MerkleLL_Integration_Shared_Test, WithdrawFees_Integration_Test { - function setUp() public override(MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLL_Integration_Shared_Test.setUp(); - } -} diff --git a/test/periphery/integration/merkle-campaign/ll/claim/claim.t.sol b/test/periphery/integration/merkle-campaign/ll/claim/claim.t.sol deleted file mode 100644 index 62491f044..000000000 --- a/test/periphery/integration/merkle-campaign/ll/claim/claim.t.sol +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { LockupLinear } from "src/core/types/DataTypes.sol"; -import { ISablierMerkleLL } from "src/periphery/interfaces/ISablierMerkleLL.sol"; -import { MerkleLL } from "src/periphery/types/DataTypes.sol"; - -import { Claim_Integration_Test } from "../../shared/claim/claim.t.sol"; -import { MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test } from "../MerkleLL.t.sol"; - -contract Claim_MerkleLL_Integration_Test is Claim_Integration_Test, MerkleLL_Integration_Shared_Test { - MerkleLL.Schedule internal schedule; - - function setUp() public virtual override(MerkleLL_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLL_Integration_Shared_Test.setUp(); - schedule = defaults.schedule(); - } - - function test_WhenScheduledCliffDurationZero() external whenMerkleProofValid whenScheduledStartTimeZero { - schedule.cliffDuration = 0; - schedule.cliffAmount = 0; - - merkleLL = merkleFactory.createMerkleLL({ - baseParams: defaults.baseParams(), - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: schedule, - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT() - }); - - // It should create a stream with block.timestamp as start time. - // It should create a stream with cliff as zero. - _test_Claim({ startTime: getBlockTimestamp(), cliffTime: 0 }); - } - - function test_WhenScheduledCliffDurationNotZero() external whenMerkleProofValid whenScheduledStartTimeZero { - // It should create a stream with block.timestamp as start time. - // It should create a stream with cliff as start time + cliff duration. - _test_Claim({ startTime: getBlockTimestamp(), cliffTime: getBlockTimestamp() + defaults.CLIFF_DURATION() }); - } - - function test_WhenScheduledStartTimeNotZero() external whenMerkleProofValid { - schedule.startTime = defaults.STREAM_START_TIME_NON_ZERO(); - - merkleLL = merkleFactory.createMerkleLL({ - baseParams: defaults.baseParams(), - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - schedule: schedule, - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT() - }); - - // It should create a stream with scheduled start time as start time. - _test_Claim({ - startTime: defaults.STREAM_START_TIME_NON_ZERO(), - cliffTime: defaults.STREAM_START_TIME_NON_ZERO() + defaults.CLIFF_DURATION() - }); - } - - /// @dev Helper function to test claim. - function _test_Claim(uint40 startTime, uint40 cliffTime) private { - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - deal({ token: address(dai), to: address(merkleLL), give: defaults.AGGREGATE_AMOUNT() }); - - uint256 expectedStreamId = lockup.nextStreamId(); - uint256 previousFeeAccrued = address(merkleLL).balance; - - LockupLinear.UnlockAmounts memory unlockAmounts = - cliffTime > 0 ? defaults.unlockAmounts() : defaults.unlockAmountsZero(); - - // It should emit a {Claim} event. - vm.expectEmit({ emitter: address(merkleLL) }); - emit ISablierMerkleLL.Claim(defaults.INDEX1(), users.recipient1, defaults.CLAIM_AMOUNT(), expectedStreamId); - - expectCallToTransferFrom({ from: address(merkleLL), to: address(lockup), value: defaults.CLAIM_AMOUNT() }); - expectCallToClaimWithMsgValue(address(merkleLL), sablierFee); - - // Claim the airstream. - merkleLL.claim{ value: sablierFee }( - defaults.INDEX1(), users.recipient1, defaults.CLAIM_AMOUNT(), defaults.index1Proof() - ); - - // Assert that the stream has been created successfully. - assertEq(lockup.getDepositedAmount(expectedStreamId), defaults.CLAIM_AMOUNT(), "depositedAmount"); - assertEq(lockup.getAsset(expectedStreamId), dai, "asset"); - assertEq(lockup.getCliffTime(expectedStreamId), cliffTime, "cliff time"); - assertEq(lockup.getEndTime(expectedStreamId), startTime + defaults.TOTAL_DURATION(), "end time"); - assertEq(lockup.isCancelable(expectedStreamId), defaults.CANCELABLE(), "is cancelable"); - assertEq(lockup.isDepleted(expectedStreamId), false, "is depleted"); - assertEq(lockup.isStream(expectedStreamId), true, "is stream"); - assertEq(lockup.isTransferable(expectedStreamId), defaults.TRANSFERABLE(), "is transferable"); - assertEq(lockup.getRecipient(expectedStreamId), users.recipient1, "recipient"); - assertEq(lockup.getSender(expectedStreamId), users.campaignOwner, "sender"); - assertEq(lockup.getStartTime(expectedStreamId), startTime, "start time"); - assertEq(lockup.wasCanceled(expectedStreamId), false, "was canceled"); - assertEq(lockup.getUnlockAmounts(expectedStreamId).start, unlockAmounts.start, "unlock amount start"); - assertEq(lockup.getUnlockAmounts(expectedStreamId).cliff, unlockAmounts.cliff, "unlock amount cliff"); - - assertTrue(merkleLL.hasClaimed(defaults.INDEX1()), "not claimed"); - assertEq(address(merkleLL).balance, previousFeeAccrued + defaults.DEFAULT_SABLIER_FEE(), "fee collected"); - } -} diff --git a/test/periphery/integration/merkle-campaign/ll/claim/claim.tree b/test/periphery/integration/merkle-campaign/ll/claim/claim.tree deleted file mode 100644 index 3e2d183a8..000000000 --- a/test/periphery/integration/merkle-campaign/ll/claim/claim.tree +++ /dev/null @@ -1,14 +0,0 @@ -Claim_MerkleLL_Integration_Test -└── when Merkle proof valid - ├── when scheduled start time zero - │ ├── when scheduled cliff duration zero - │ │ ├── it should create a stream with block.timestamp as start time - │ │ ├── it should create a stream with cliff as zero - │ │ └── it should emit a {Claim} event - │ └── when scheduled cliff duration not zero - │ ├── it should create a stream with block.timestamp as start time - │ ├── it should create a stream with cliff as start time + cliff duration - │ └── it should emit a {Claim} event - └── when scheduled start time not zero - ├── it should create a stream with scheduled start time as start time - └── it should emit a {Claim} event diff --git a/test/periphery/integration/merkle-campaign/ll/constructor.t.sol b/test/periphery/integration/merkle-campaign/ll/constructor.t.sol deleted file mode 100644 index bca91849d..000000000 --- a/test/periphery/integration/merkle-campaign/ll/constructor.t.sol +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { SablierMerkleLL } from "src/periphery/SablierMerkleLL.sol"; -import { MerkleLL } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../MerkleCampaign.t.sol"; - -contract Constructor_MerkleLL_Integration_Test is MerkleCampaign_Integration_Test { - /// @dev Needed to prevent "Stack too deep" error - struct Vars { - address actualAdmin; - uint256 actualAllowance; - address actualAsset; - bool actualCancelable; - uint40 actualExpiration; - address actualFactory; - string actualIpfsCID; - address actualLockup; - bytes32 actualMerkleRoot; - string actualName; - uint256 actualSablierFee; - MerkleLL.Schedule actualSchedule; - bool actualTransferable; - address expectedAdmin; - uint256 expectedAllowance; - address expectedAsset; - bool expectedCancelable; - uint40 expectedExpiration; - address expectedFactory; - string expectedIpfsCID; - address expectedLockup; - bytes32 expectedMerkleRoot; - bytes32 expectedName; - uint256 expectedSablierFee; - MerkleLL.Schedule expectedSchedule; - bool expectedTransferable; - } - - function test_Constructor() external { - // Make Factory the caller for the constructor test. - resetPrank(address(merkleFactory)); - - SablierMerkleLL constructedLL = new SablierMerkleLL( - defaults.baseParams(), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.schedule(), - defaults.DEFAULT_SABLIER_FEE() - ); - - Vars memory vars; - - vars.actualAdmin = constructedLL.admin(); - vars.expectedAdmin = users.campaignOwner; - assertEq(vars.actualAdmin, vars.expectedAdmin, "admin"); - - vars.actualAllowance = dai.allowance(address(constructedLL), address(lockup)); - vars.expectedAllowance = MAX_UINT256; - assertEq(vars.actualAllowance, vars.expectedAllowance, "allowance"); - - vars.actualAsset = address(constructedLL.ASSET()); - vars.expectedAsset = address(dai); - assertEq(vars.actualAsset, vars.expectedAsset, "asset"); - - vars.actualCancelable = constructedLL.CANCELABLE(); - vars.expectedCancelable = defaults.CANCELABLE(); - assertEq(vars.actualCancelable, vars.expectedCancelable, "cancelable"); - - vars.actualExpiration = constructedLL.EXPIRATION(); - vars.expectedExpiration = defaults.EXPIRATION(); - assertEq(vars.actualExpiration, vars.expectedExpiration, "expiration"); - - vars.actualFactory = constructedLL.FACTORY(); - vars.expectedFactory = address(merkleFactory); - assertEq(vars.actualFactory, vars.expectedFactory, "factory"); - - vars.actualIpfsCID = constructedLL.ipfsCID(); - vars.expectedIpfsCID = defaults.IPFS_CID(); - assertEq(vars.actualIpfsCID, vars.expectedIpfsCID, "ipfsCID"); - - vars.actualLockup = address(constructedLL.LOCKUP()); - vars.expectedLockup = address(lockup); - assertEq(vars.actualLockup, vars.expectedLockup, "lockup"); - - vars.actualMerkleRoot = constructedLL.MERKLE_ROOT(); - vars.expectedMerkleRoot = defaults.MERKLE_ROOT(); - assertEq(vars.actualMerkleRoot, vars.expectedMerkleRoot, "merkleRoot"); - - vars.actualName = constructedLL.name(); - vars.expectedName = defaults.NAME_BYTES32(); - assertEq(bytes32(abi.encodePacked(vars.actualName)), vars.expectedName, "name"); - - ( - vars.actualSchedule.startTime, - vars.actualSchedule.startAmount, - vars.actualSchedule.cliffDuration, - vars.actualSchedule.cliffAmount, - vars.actualSchedule.totalDuration - ) = constructedLL.schedule(); - vars.expectedSchedule = defaults.schedule(); - assertEq(vars.actualSchedule.startTime, vars.expectedSchedule.startTime, "schedule.startTime"); - assertEq(vars.actualSchedule.startAmount, vars.expectedSchedule.startAmount, "schedule.startAmount"); - assertEq(vars.actualSchedule.cliffDuration, vars.expectedSchedule.cliffDuration, "schedule.cliffDuration"); - assertEq(vars.actualSchedule.cliffAmount, vars.expectedSchedule.cliffAmount, "schedule.cliffAmount"); - assertEq(vars.actualSchedule.totalDuration, vars.expectedSchedule.totalDuration, "schedule.totalDuration"); - - vars.actualTransferable = constructedLL.TRANSFERABLE(); - vars.expectedTransferable = defaults.TRANSFERABLE(); - assertEq(vars.actualTransferable, vars.expectedTransferable, "transferable"); - - vars.actualSablierFee = constructedLL.SABLIER_FEE(); - vars.expectedSablierFee = defaults.DEFAULT_SABLIER_FEE(); - assertEq(vars.actualSablierFee, vars.expectedSablierFee, "sablierFee"); - } -} diff --git a/test/periphery/integration/merkle-campaign/lt/MerkleLT.t.sol b/test/periphery/integration/merkle-campaign/lt/MerkleLT.t.sol deleted file mode 100644 index bfd78d6c9..000000000 --- a/test/periphery/integration/merkle-campaign/lt/MerkleLT.t.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { MerkleCampaign_Integration_Test } from "./../MerkleCampaign.t.sol"; -import { Clawback_Integration_Test } from "./../shared/clawback/clawback.t.sol"; -import { GetFirstClaimTime_Integration_Test } from "./../shared/get-first-claim-time/getFirstClaimTime.t.sol"; -import { HasClaimed_Integration_Test } from "./../shared/has-claimed/hasClaimed.t.sol"; -import { HasExpired_Integration_Test } from "./../shared/has-expired/hasExpired.t.sol"; -import { WithdrawFees_Integration_Test } from "./../shared/withdraw-fees/withdrawFees.t.sol"; - -/*////////////////////////////////////////////////////////////////////////// - NON-SHARED TESTS -//////////////////////////////////////////////////////////////////////////*/ - -abstract contract MerkleLT_Integration_Shared_Test is MerkleCampaign_Integration_Test { - function setUp() public virtual override { - MerkleCampaign_Integration_Test.setUp(); - - // Cast the {MerkleLT} contract as {ISablierMerkleBase} - merkleBase = ISablierMerkleBase(merkleLT); - } -} - -/*////////////////////////////////////////////////////////////////////////// - SHARED TESTS -//////////////////////////////////////////////////////////////////////////*/ - -contract Clawback_MerkleLT_Integration_Test is MerkleLT_Integration_Shared_Test, Clawback_Integration_Test { - function setUp() public override(MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLT_Integration_Shared_Test.setUp(); - } -} - -contract GetFirstClaimTime_MerkleLT_Integration_Test is - MerkleLT_Integration_Shared_Test, - GetFirstClaimTime_Integration_Test -{ - function setUp() public override(MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLT_Integration_Shared_Test.setUp(); - } -} - -contract HasClaimed_MerkleLT_Integration_Test is MerkleLT_Integration_Shared_Test, HasClaimed_Integration_Test { - function setUp() public override(MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLT_Integration_Shared_Test.setUp(); - } -} - -contract HasExpired_MerkleLT_Integration_Test is MerkleLT_Integration_Shared_Test, HasExpired_Integration_Test { - function setUp() public override(MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLT_Integration_Shared_Test.setUp(); - } -} - -contract WithdrawFees_MerkleLT_Integration_Test is MerkleLT_Integration_Shared_Test, WithdrawFees_Integration_Test { - function setUp() public override(MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLT_Integration_Shared_Test.setUp(); - } -} diff --git a/test/periphery/integration/merkle-campaign/lt/claim/claim.t.sol b/test/periphery/integration/merkle-campaign/lt/claim/claim.t.sol deleted file mode 100644 index 981878010..000000000 --- a/test/periphery/integration/merkle-campaign/lt/claim/claim.t.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ud2x18 } from "@prb/math/src/UD2x18.sol"; - -import { ISablierMerkleLT } from "src/periphery/interfaces/ISablierMerkleLT.sol"; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { MerkleLT } from "src/periphery/types/DataTypes.sol"; - -import { Claim_Integration_Test } from "../../shared/claim/claim.t.sol"; -import { MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test } from "../MerkleLT.t.sol"; - -contract Claim_MerkleLT_Integration_Test is Claim_Integration_Test, MerkleLT_Integration_Shared_Test { - function setUp() public virtual override(MerkleLT_Integration_Shared_Test, MerkleCampaign_Integration_Test) { - MerkleLT_Integration_Shared_Test.setUp(); - } - - function test_RevertWhen_TotalPercentageLessThan100() external whenMerkleProofValid whenTotalPercentageNot100 { - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - - // Create a MerkleLT campaign with a total percentage less than 100. - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages(); - tranchesWithPercentages[0].unlockPercentage = ud2x18(0.05e18); - tranchesWithPercentages[1].unlockPercentage = ud2x18(0.2e18); - - merkleLT = merkleFactory.createMerkleLT( - defaults.baseParams(), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages, - defaults.AGGREGATE_AMOUNT(), - defaults.RECIPIENT_COUNT() - ); - - uint64 totalPercentage = - tranchesWithPercentages[0].unlockPercentage.unwrap() + tranchesWithPercentages[1].unlockPercentage.unwrap(); - - // Claim an airstream. - bytes32[] memory merkleProof = defaults.index1Proof(); - - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierMerkleLT_TotalPercentageNotOneHundred.selector, totalPercentage) - ); - - merkleLT.claim{ value: sablierFee }({ - index: 1, - recipient: users.recipient1, - amount: 10_000e18, - merkleProof: merkleProof - }); - } - - function test_RevertWhen_TotalPercentageGreaterThan100() external whenMerkleProofValid whenTotalPercentageNot100 { - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - // Create a MerkleLT campaign with a total percentage less than 100. - MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages(); - tranchesWithPercentages[0].unlockPercentage = ud2x18(0.75e18); - tranchesWithPercentages[1].unlockPercentage = ud2x18(0.8e18); - - merkleLT = merkleFactory.createMerkleLT( - defaults.baseParams(), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.STREAM_START_TIME_ZERO(), - tranchesWithPercentages, - defaults.AGGREGATE_AMOUNT(), - defaults.RECIPIENT_COUNT() - ); - - uint64 totalPercentage = - tranchesWithPercentages[0].unlockPercentage.unwrap() + tranchesWithPercentages[1].unlockPercentage.unwrap(); - - // Claim an airstream. - bytes32[] memory merkleProof = defaults.index1Proof(); - - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierMerkleLT_TotalPercentageNotOneHundred.selector, totalPercentage) - ); - - merkleLT.claim{ value: sablierFee }({ - index: 1, - recipient: users.recipient1, - amount: 10_000e18, - merkleProof: merkleProof - }); - } - - function test_WhenStreamStartTimeZero() external whenMerkleProofValid whenTotalPercentage100 { - // It should create a stream with block.timestamp as start time. - _test_Claim({ streamStartTime: 0, startTime: getBlockTimestamp() }); - } - - function test_WhenStreamStartTimeNotZero() external whenMerkleProofValid whenTotalPercentage100 { - merkleLT = merkleFactory.createMerkleLT({ - baseParams: defaults.baseParams(), - lockup: lockup, - cancelable: defaults.CANCELABLE(), - transferable: defaults.TRANSFERABLE(), - streamStartTime: defaults.STREAM_START_TIME_NON_ZERO(), - tranchesWithPercentages: defaults.tranchesWithPercentages(), - aggregateAmount: defaults.AGGREGATE_AMOUNT(), - recipientCount: defaults.RECIPIENT_COUNT() - }); - - // It should create a stream with `STREAM_START_TIME` as start time. - _test_Claim({ - streamStartTime: defaults.STREAM_START_TIME_NON_ZERO(), - startTime: defaults.STREAM_START_TIME_NON_ZERO() - }); - } - - /// @dev Helper function to test claim. - function _test_Claim(uint40 streamStartTime, uint40 startTime) private { - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - - deal({ token: address(dai), to: address(merkleLT), give: defaults.AGGREGATE_AMOUNT() }); - - uint256 expectedStreamId = lockup.nextStreamId(); - uint256 previousFeeAccrued = address(merkleLL).balance; - - // It should emit a {Claim} event. - vm.expectEmit({ emitter: address(merkleLT) }); - emit ISablierMerkleLT.Claim(defaults.INDEX1(), users.recipient1, defaults.CLAIM_AMOUNT(), expectedStreamId); - - expectCallToTransferFrom({ from: address(merkleLT), to: address(lockup), value: defaults.CLAIM_AMOUNT() }); - expectCallToClaimWithMsgValue(address(merkleLT), sablierFee); - - // Claim the airstream. - merkleLT.claim{ value: sablierFee }( - defaults.INDEX1(), users.recipient1, defaults.CLAIM_AMOUNT(), defaults.index1Proof() - ); - - // Assert that the stream has been created successfully. - assertEq(lockup.getDepositedAmount(expectedStreamId), defaults.CLAIM_AMOUNT(), "depositedAmount"); - assertEq(lockup.getAsset(expectedStreamId), dai, "asset"); - assertEq(lockup.getEndTime(expectedStreamId), startTime + defaults.TOTAL_DURATION(), "end time"); - assertEq(lockup.isCancelable(expectedStreamId), defaults.CANCELABLE(), "is cancelable"); - assertEq(lockup.isDepleted(expectedStreamId), false, "is depleted"); - assertEq(lockup.isStream(expectedStreamId), true, "is stream"); - assertEq(lockup.isTransferable(expectedStreamId), defaults.TRANSFERABLE(), "is transferable"); - assertEq(lockup.getRecipient(expectedStreamId), users.recipient1, "recipient"); - assertEq(lockup.getSender(expectedStreamId), users.campaignOwner, "sender"); - assertEq(lockup.getStartTime(expectedStreamId), startTime, "start time"); - assertEq(lockup.wasCanceled(expectedStreamId), false, "was canceled"); - // It should create a stream with `STREAM_START_TIME` as start time. - assertEq( - lockup.getTranches(expectedStreamId), - defaults.tranchesMerkleLT({ streamStartTime: streamStartTime, totalAmount: defaults.CLAIM_AMOUNT() }), - "tranches" - ); - - assertTrue(merkleLT.hasClaimed(defaults.INDEX1()), "not claimed"); - - assertEq(address(merkleLT).balance, previousFeeAccrued + defaults.DEFAULT_SABLIER_FEE(), "fee collected"); - } -} diff --git a/test/periphery/integration/merkle-campaign/lt/claim/claim.tree b/test/periphery/integration/merkle-campaign/lt/claim/claim.tree deleted file mode 100644 index 7b5229a62..000000000 --- a/test/periphery/integration/merkle-campaign/lt/claim/claim.tree +++ /dev/null @@ -1,14 +0,0 @@ -Claim_MerkleLT_Integration_Test -└── when Merkle proof valid - ├── when total percentage not 100 - │ ├── when total percentage less than 100 - │ │ └── it should revert - │ └── when total percentage greater than 100 - │ └── it should revert - └── when total percentage 100 - ├── when stream start time zero - │ ├── it should create a stream with block.timestamp as start time - │ └── it should emit a {Claim} event - └── when stream start time not zero - ├── it should create a stream with `STREAM_START_TIME` as start time - └── it should emit a {Claim} event diff --git a/test/periphery/integration/merkle-campaign/lt/constructor.t.sol b/test/periphery/integration/merkle-campaign/lt/constructor.t.sol deleted file mode 100644 index e07e3b274..000000000 --- a/test/periphery/integration/merkle-campaign/lt/constructor.t.sol +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { SablierMerkleLT } from "src/periphery/SablierMerkleLT.sol"; -import { MerkleLT } from "src/periphery/types/DataTypes.sol"; - -import { MerkleCampaign_Integration_Test } from "../MerkleCampaign.t.sol"; - -contract Constructor_MerkleLT_Integration_Test is MerkleCampaign_Integration_Test { - /// @dev Needed to prevent "Stack too deep" error - struct Vars { - address actualAdmin; - uint256 actualAllowance; - address actualAsset; - bool actualCancelable; - uint40 actualExpiration; - address actualFactory; - string actualIpfsCID; - address actualLockup; - bytes32 actualMerkleRoot; - string actualName; - uint256 actualSablierFee; - uint40 actualStreamStartTime; - uint64 actualTotalPercentage; - MerkleLT.TrancheWithPercentage[] actualTranchesWithPercentages; - bool actualTransferable; - address expectedAdmin; - uint256 expectedAllowance; - address expectedAsset; - bool expectedCancelable; - uint40 expectedExpiration; - address expectedFactory; - string expectedIpfsCID; - address expectedLockup; - bytes32 expectedMerkleRoot; - bytes32 expectedName; - uint256 expectedSablierFee; - uint40 expectedStreamStartTime; - uint64 expectedTotalPercentage; - MerkleLT.TrancheWithPercentage[] expectedTranchesWithPercentages; - bool expectedTransferable; - } - - function test_Constructor() external { - // Make Factory the caller for the constructor test. - resetPrank(address(merkleFactory)); - - SablierMerkleLT constructedLT = new SablierMerkleLT( - defaults.baseParams(), - lockup, - defaults.CANCELABLE(), - defaults.TRANSFERABLE(), - defaults.STREAM_START_TIME_ZERO(), - defaults.tranchesWithPercentages(), - defaults.DEFAULT_SABLIER_FEE() - ); - - Vars memory vars; - - vars.actualAdmin = constructedLT.admin(); - vars.expectedAdmin = users.campaignOwner; - assertEq(vars.actualAdmin, vars.expectedAdmin, "admin"); - - vars.actualAllowance = dai.allowance(address(constructedLT), address(lockup)); - vars.expectedAllowance = MAX_UINT256; - assertEq(vars.actualAllowance, vars.expectedAllowance, "allowance"); - - vars.actualAsset = address(constructedLT.ASSET()); - vars.expectedAsset = address(dai); - assertEq(vars.actualAsset, vars.expectedAsset, "asset"); - - vars.actualCancelable = constructedLT.CANCELABLE(); - vars.expectedCancelable = defaults.CANCELABLE(); - assertEq(vars.actualCancelable, vars.expectedCancelable, "cancelable"); - - vars.actualExpiration = constructedLT.EXPIRATION(); - vars.expectedExpiration = defaults.EXPIRATION(); - assertEq(vars.actualExpiration, vars.expectedExpiration, "expiration"); - - vars.actualFactory = constructedLT.FACTORY(); - vars.expectedFactory = address(merkleFactory); - assertEq(vars.actualFactory, vars.expectedFactory, "factory"); - - vars.actualIpfsCID = constructedLT.ipfsCID(); - vars.expectedIpfsCID = defaults.IPFS_CID(); - assertEq(vars.actualIpfsCID, vars.expectedIpfsCID, "ipfsCID"); - - vars.actualLockup = address(constructedLT.LOCKUP()); - vars.expectedLockup = address(lockup); - assertEq(vars.actualLockup, vars.expectedLockup, "lockup"); - - vars.actualMerkleRoot = constructedLT.MERKLE_ROOT(); - vars.expectedMerkleRoot = defaults.MERKLE_ROOT(); - assertEq(vars.actualMerkleRoot, vars.expectedMerkleRoot, "merkleRoot"); - - vars.actualName = constructedLT.name(); - vars.expectedName = defaults.NAME_BYTES32(); - assertEq(bytes32(abi.encodePacked(vars.actualName)), vars.expectedName, "name"); - - vars.actualSablierFee = constructedLT.SABLIER_FEE(); - vars.expectedSablierFee = defaults.DEFAULT_SABLIER_FEE(); - assertEq(vars.actualSablierFee, vars.expectedSablierFee, "sablierFee"); - - vars.actualStreamStartTime = constructedLT.STREAM_START_TIME(); - vars.expectedStreamStartTime = defaults.STREAM_START_TIME_ZERO(); - assertEq(vars.actualStreamStartTime, vars.expectedStreamStartTime, "streamStartTime"); - - vars.actualTotalPercentage = constructedLT.TOTAL_PERCENTAGE(); - vars.expectedTotalPercentage = defaults.TOTAL_PERCENTAGE(); - assertEq(vars.actualTotalPercentage, vars.expectedTotalPercentage, "totalPercentage"); - - vars.actualTransferable = constructedLT.TRANSFERABLE(); - vars.expectedTransferable = defaults.TRANSFERABLE(); - assertEq(vars.actualTransferable, vars.expectedTransferable, "transferable"); - - vars.actualTranchesWithPercentages = constructedLT.getTranchesWithPercentages(); - vars.expectedTranchesWithPercentages = defaults.tranchesWithPercentages(); - assertEq(vars.actualTranchesWithPercentages, vars.expectedTranchesWithPercentages, "tranchesWithPercentages"); - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/claim/claim.t.sol b/test/periphery/integration/merkle-campaign/shared/claim/claim.t.sol deleted file mode 100644 index c267ee7d8..000000000 --- a/test/periphery/integration/merkle-campaign/shared/claim/claim.t.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors } from "src/periphery/libraries/Errors.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -abstract contract Claim_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertGiven_CampaignExpired() external { - uint40 expiration = defaults.EXPIRATION(); - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - uint256 warpTime = expiration + 1 seconds; - bytes32[] memory merkleProof; - vm.warp({ newTimestamp: warpTime }); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_CampaignExpired.selector, warpTime, expiration)); - merkleBase.claim{ value: sablierFee }({ - index: 1, - recipient: users.recipient1, - amount: 1, - merkleProof: merkleProof - }); - } - - function test_RevertGiven_MsgValueLessThanSablierFee() external givenCampaignNotExpired { - uint256 index1 = defaults.INDEX1(); - uint128 amount = defaults.CLAIM_AMOUNT(); - bytes32[] memory merkleProof = defaults.index1Proof(); - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_InsufficientFeePayment.selector, 0, sablierFee)); - merkleBase.claim{ value: 0 }(index1, users.recipient1, amount, merkleProof); - } - - function test_RevertGiven_RecipientClaimed() external givenCampaignNotExpired givenMsgValueNotLessThanSablierFee { - claim(); - uint256 index1 = defaults.INDEX1(); - uint128 amount = defaults.CLAIM_AMOUNT(); - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - bytes32[] memory merkleProof = defaults.index1Proof(); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_StreamClaimed.selector, index1)); - merkleBase.claim{ value: sablierFee }(index1, users.recipient1, amount, merkleProof); - } - - function test_RevertWhen_IndexNotValid() - external - givenCampaignNotExpired - givenMsgValueNotLessThanSablierFee - givenRecipientNotClaimed - { - uint256 invalidIndex = 1337; - uint128 amount = defaults.CLAIM_AMOUNT(); - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - bytes32[] memory merkleProof = defaults.index1Proof(); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_InvalidProof.selector)); - merkleBase.claim{ value: sablierFee }(invalidIndex, users.recipient1, amount, merkleProof); - } - - function test_RevertWhen_RecipientNotValid() - external - givenCampaignNotExpired - givenMsgValueNotLessThanSablierFee - givenRecipientNotClaimed - whenIndexValid - { - uint256 index1 = defaults.INDEX1(); - address invalidRecipient = address(1337); - uint128 amount = defaults.CLAIM_AMOUNT(); - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - bytes32[] memory merkleProof = defaults.index1Proof(); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_InvalidProof.selector)); - merkleBase.claim{ value: sablierFee }(index1, invalidRecipient, amount, merkleProof); - } - - function test_RevertWhen_AmountNotValid() - external - givenCampaignNotExpired - givenMsgValueNotLessThanSablierFee - givenRecipientNotClaimed - whenIndexValid - whenRecipientValid - { - uint256 index1 = defaults.INDEX1(); - uint128 invalidAmount = 1337; - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - bytes32[] memory merkleProof = defaults.index1Proof(); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_InvalidProof.selector)); - merkleBase.claim{ value: sablierFee }(index1, users.recipient1, invalidAmount, merkleProof); - } - - function test_RevertWhen_MerkleProofNotValid() - external - givenCampaignNotExpired - givenMsgValueNotLessThanSablierFee - givenRecipientNotClaimed - whenIndexValid - whenRecipientValid - whenAmountValid - { - uint256 index1 = defaults.INDEX1(); - uint128 amount = defaults.CLAIM_AMOUNT(); - uint256 sablierFee = defaults.DEFAULT_SABLIER_FEE(); - bytes32[] memory invalidMerkleProof = defaults.index2Proof(); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierMerkleBase_InvalidProof.selector)); - merkleBase.claim{ value: sablierFee }(index1, users.recipient1, amount, invalidMerkleProof); - } - - /// @dev Since the implementation of `_claim()` differs in each Merkle campaign, we declare this dummy test and - /// the Child contracts implement the actual claim test functions. - function test_WhenMerkleProofValid() - external - givenCampaignNotExpired - givenMsgValueNotLessThanSablierFee - givenRecipientNotClaimed - whenIndexValid - whenRecipientValid - whenAmountValid - { - // The child contract must check that the claim event is emitted. - // It should mark the index as claimed. - // It should transfer the sablier fee from the caller address to the merkle lockup. - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/claim/claim.tree b/test/periphery/integration/merkle-campaign/shared/claim/claim.tree deleted file mode 100644 index c93188b3d..000000000 --- a/test/periphery/integration/merkle-campaign/shared/claim/claim.tree +++ /dev/null @@ -1,25 +0,0 @@ -Claim_Integration_Test -├── given campaign expired -│ └── it should revert -└── given campaign not expired - ├── given msg value less than Sablier fee - │ └── it should revert - └── given msg value not less than Sablier fee - ├── given recipient claimed - │ └── it should revert - └── given recipient not claimed - ├── when index not valid - │ └── it should revert - └── when index valid - ├── when recipient not valid - │ └── it should revert - └── when recipient valid - ├── when amount not valid - │ └── it should revert - └── when amount valid - ├── when Merkle proof not valid - │ └── it should revert - └── when Merkle proof valid - ├── it should mark the index as Claimed - ├── it should transfer the ETH to the merkle lockup - └── it should emit {Claim} event diff --git a/test/periphery/integration/merkle-campaign/shared/clawback/clawback.t.sol b/test/periphery/integration/merkle-campaign/shared/clawback/clawback.t.sol deleted file mode 100644 index 190fbce6b..000000000 --- a/test/periphery/integration/merkle-campaign/shared/clawback/clawback.t.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors as CoreErrors } from "src/core/libraries/Errors.sol"; -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; -import { Errors } from "src/periphery/libraries/Errors.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -abstract contract Clawback_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_CallerNotCampaignOwner() external { - resetPrank({ msgSender: users.eve }); - vm.expectRevert(abi.encodeWithSelector(CoreErrors.CallerNotAdmin.selector, users.campaignOwner, users.eve)); - merkleBase.clawback({ to: users.eve, amount: 1 }); - } - - function test_WhenFirstClaimNotMade() external whenCallerCampaignOwner { - test_Clawback(users.campaignOwner); - } - - modifier whenFirstClaimMade() { - // Make the first claim to set `_firstClaimTime`. - claim(); - - // Reset the prank back to the campaign owner. - resetPrank(users.campaignOwner); - _; - } - - function test_GivenSevenDaysNotPassed() external whenCallerCampaignOwner whenFirstClaimMade { - vm.warp({ newTimestamp: getBlockTimestamp() + 6 days }); - test_Clawback(users.campaignOwner); - } - - function test_RevertGiven_CampaignNotExpired() - external - whenCallerCampaignOwner - whenFirstClaimMade - givenSevenDaysPassed - { - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_ClawbackNotAllowed.selector, - getBlockTimestamp(), - defaults.EXPIRATION(), - defaults.FIRST_CLAIM_TIME() - ) - ); - merkleBase.clawback({ to: users.campaignOwner, amount: 1 }); - } - - function test_GivenCampaignExpired(address to) - external - whenCallerCampaignOwner - whenFirstClaimMade - givenSevenDaysPassed - { - vm.warp({ newTimestamp: defaults.EXPIRATION() + 1 seconds }); - vm.assume(to != address(0)); - test_Clawback(to); - } - - function test_Clawback(address to) internal { - uint128 clawbackAmount = uint128(dai.balanceOf(address(merkleBase))); - // It should perform the ERC-20 transfer. - expectCallToTransfer({ to: to, value: clawbackAmount }); - // It should emit a {Clawback} event. - vm.expectEmit({ emitter: address(merkleBase) }); - emit ISablierMerkleBase.Clawback({ admin: users.campaignOwner, to: to, amount: clawbackAmount }); - merkleBase.clawback({ to: to, amount: clawbackAmount }); - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/clawback/clawback.tree b/test/periphery/integration/merkle-campaign/shared/clawback/clawback.tree deleted file mode 100644 index 92db26f83..000000000 --- a/test/periphery/integration/merkle-campaign/shared/clawback/clawback.tree +++ /dev/null @@ -1,17 +0,0 @@ -Clawback_Integration_Test -├── when caller not campaign owner -│ └── it should revert -└── when caller campaig owner - ├── when first claim not made - │ ├── it should perform the ERC-20 transfer - │ └── it should emit a {Clawback} event - └── when first claim made - ├── given seven days not passed - │ ├── it should perform the ERC-20 transfer - │ └── it should emit a {Clawback} event - └── given seven days passed - ├── given campaign not expired - │ └── it should revert - └── given campaign expired - ├── it should perform the ERC-20 transfer - └── it should emit a {Clawback} event diff --git a/test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.t.sol b/test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.t.sol deleted file mode 100644 index d88ed4a93..000000000 --- a/test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -abstract contract GetFirstClaimTime_Integration_Test is MerkleCampaign_Integration_Test { - function test_WhenFirstClaimNotMade() external view { - // It should return 0. - uint256 firstClaimTime = merkleBase.getFirstClaimTime(); - assertEq(firstClaimTime, 0); - } - - function test_WhenFirstClaimMade() external { - // Make the first claim to set `_firstClaimTime`. - claim(); - - // It should return the time of the first claim. - uint256 firstClaimTime = merkleBase.getFirstClaimTime(); - assertEq(firstClaimTime, getBlockTimestamp()); - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.tree b/test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.tree deleted file mode 100644 index 3c5f9f964..000000000 --- a/test/periphery/integration/merkle-campaign/shared/get-first-claim-time/getFirstClaimTime.tree +++ /dev/null @@ -1,5 +0,0 @@ -GetFirstClaimTime_Integration_Test -├── when first claim not made -│ └── it should return 0 -└── when first claim made - └── it should return the time of the first claim diff --git a/test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.t.sol b/test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.t.sol deleted file mode 100644 index 92f5c49e4..000000000 --- a/test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -abstract contract HasClaimed_Integration_Test is MerkleCampaign_Integration_Test { - function test_WhenIndexNotInMerkleTree() external { - uint256 indexNotInTree = 1337e18; - assertFalse(merkleBase.hasClaimed(indexNotInTree), "claimed"); - } - - function test_GivenRecipientNotClaimed() external whenIndexInMerkleTree { - // It should return false. - assertFalse(merkleBase.hasClaimed(defaults.INDEX1()), "claimed"); - } - - function test_GivenRecipientClaimed() external whenIndexInMerkleTree { - // Make the first claim to set `_firstClaimTime`. - claim(); - - // It should return true. - assertTrue(merkleBase.hasClaimed(defaults.INDEX1()), "not claimed"); - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.tree b/test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.tree deleted file mode 100644 index b7b6d2312..000000000 --- a/test/periphery/integration/merkle-campaign/shared/has-claimed/hasClaimed.tree +++ /dev/null @@ -1,8 +0,0 @@ -HasClaimed_Integration_Test -├── when index not in Merkle tree -│ └── it should return false -└── when index in Merkle tree - ├── given recipient not claimed - │ └── it should return false - └── given recipient claimed - └── it should return true diff --git a/test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.t.sol b/test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.t.sol deleted file mode 100644 index fde935fe7..000000000 --- a/test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.t.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -abstract contract HasExpired_Integration_Test is MerkleCampaign_Integration_Test { - function test_WhenExpirationZero() external { - ISablierMerkleBase campaignWithZeroExpiry = ISablierMerkleBase(createMerkleLT({ expiration: 0 })); - assertFalse(campaignWithZeroExpiry.hasExpired(), "campaign expired"); - } - - function test_WhenExpirationInPast() external view whenExpirationNotZero { - assertFalse(merkleBase.hasExpired(), "campaign expired"); - } - - function test_WhenTheExpirationInPresent() external whenExpirationNotZero { - vm.warp({ newTimestamp: defaults.EXPIRATION() }); - assertTrue(merkleBase.hasExpired(), "campaign not expired"); - } - - function test_WhenTheExpirationInFuture() external whenExpirationNotZero { - vm.warp({ newTimestamp: defaults.EXPIRATION() + 1 seconds }); - assertTrue(merkleBase.hasExpired(), "campaign not expired"); - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.tree b/test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.tree deleted file mode 100644 index 1b03f4229..000000000 --- a/test/periphery/integration/merkle-campaign/shared/has-expired/hasExpired.tree +++ /dev/null @@ -1,10 +0,0 @@ -HasExpired_Integration_Test -├── when expiration zero -│ └── it should return false -└── when expiration not zero - ├── when expiration in past - │ └── it should return false - ├── when the expiration in present - │ └── it should return true - └── when the expiration in future - └── it should return true diff --git a/test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.t.sol b/test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.t.sol deleted file mode 100644 index 7ebb77a6e..000000000 --- a/test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.t.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.22 <0.9.0; - -import { Errors } from "src/periphery/libraries/Errors.sol"; - -import { MerkleCampaign_Integration_Test } from "../../MerkleCampaign.t.sol"; - -abstract contract WithdrawFees_Integration_Test is MerkleCampaign_Integration_Test { - function test_RevertWhen_CallerNotFactory() external { - // Set the caller to anything other than the factory. - resetPrank(users.admin); - - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_CallerNotFactory.selector, address(merkleFactory), users.admin - ) - ); - merkleBase.withdrawFees(users.admin); - } - - modifier whenCallerFactory() { - // Claim to collect some fees. - claim(); - - resetPrank(address(merkleFactory)); - _; - } - - function test_WhenProvidedAddressNotContract() external whenCallerFactory { - uint256 previousToBalance = users.admin.balance; - - merkleBase.withdrawFees(users.admin); - - // It should set the ETH balance to 0. - assertEq(address(merkleBase).balance, 0, "merkle lockup eth balance"); - // It should transfer fee collected in ETH to the provided address. - assertEq(users.admin.balance, previousToBalance + defaults.DEFAULT_SABLIER_FEE(), "eth balance"); - } - - function test_RevertWhen_ProvidedAddressNotImplementReceiveEth() - external - whenCallerFactory - whenProvidedAddressContract - { - address payable noReceiveEth = payable(address(contractWithoutReceiveEth)); - vm.expectRevert( - abi.encodeWithSelector( - Errors.SablierMerkleBase_FeeWithdrawFailed.selector, noReceiveEth, address(merkleBase).balance - ) - ); - merkleBase.withdrawFees(noReceiveEth); - } - - function test_WhenProvidedAddressImplementReceiveEth() external whenCallerFactory whenProvidedAddressContract { - address payable receiveEth = payable(address(contractWithReceiveEth)); - - merkleBase.withdrawFees(receiveEth); - - // It should set the ETH balance to 0. - assertEq(address(merkleBase).balance, 0, "merkle lockup eth balance"); - // It should transfer fee collected in ETH to the provided address. - assertEq(receiveEth.balance, defaults.DEFAULT_SABLIER_FEE(), "eth balance"); - } -} diff --git a/test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.tree b/test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.tree deleted file mode 100644 index b5839e6ac..000000000 --- a/test/periphery/integration/merkle-campaign/shared/withdraw-fees/withdrawFees.tree +++ /dev/null @@ -1,13 +0,0 @@ -WithdrawFees_Integration_Test -├── when caller not factory -│ └── it should revert -└── when caller factory - ├── when provided address not contract - │ ├── it should transfer fee collected in ETH to the provided address - │ └── it should set the ETH balance to 0 - └── when provided address contract - ├── when provided address not implement receive eth - │ └── it should revert - └── when provided address implement receive eth - ├── it should transfer fee collected in ETH to the provided address - └── it should set the ETH balance to 0 diff --git a/test/core/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol b/test/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol similarity index 94% rename from test/core/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol rename to test/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol index fb0ac695f..f058a2aac 100644 --- a/test/core/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol +++ b/test/unit/concrete/adminable/transfer-admin/transferAdmin.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { IAdminable } from "src/core/interfaces/IAdminable.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { IAdminable } from "src/interfaces/IAdminable.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Adminable_Unit_Shared_Test } from "../../../shared/Adminable.t.sol"; diff --git a/test/core/unit/concrete/adminable/transfer-admin/transferAdmin.tree b/test/unit/concrete/adminable/transfer-admin/transferAdmin.tree similarity index 100% rename from test/core/unit/concrete/adminable/transfer-admin/transferAdmin.tree rename to test/unit/concrete/adminable/transfer-admin/transferAdmin.tree diff --git a/test/core/unit/concrete/nft-descriptor/abbreviateAmount.t.sol b/test/unit/concrete/nft-descriptor/abbreviateAmount.t.sol similarity index 98% rename from test/core/unit/concrete/nft-descriptor/abbreviateAmount.t.sol rename to test/unit/concrete/nft-descriptor/abbreviateAmount.t.sol index f7f2947ee..fc8855706 100644 --- a/test/core/unit/concrete/nft-descriptor/abbreviateAmount.t.sol +++ b/test/unit/concrete/nft-descriptor/abbreviateAmount.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { SVGElements } from "src/core/libraries/SVGElements.sol"; +import { SVGElements } from "src/libraries/SVGElements.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol b/test/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol similarity index 97% rename from test/core/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol rename to test/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol index 9aba6aa21..0dbf04b4d 100644 --- a/test/core/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol +++ b/test/unit/concrete/nft-descriptor/calculateDurationInDays.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { SVGElements } from "src/core/libraries/SVGElements.sol"; +import { SVGElements } from "src/libraries/SVGElements.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/unit/concrete/nft-descriptor/calculatePixelWidth.t.sol b/test/unit/concrete/nft-descriptor/calculatePixelWidth.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/calculatePixelWidth.t.sol rename to test/unit/concrete/nft-descriptor/calculatePixelWidth.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/calculateStreamedPercentage.t.sol b/test/unit/concrete/nft-descriptor/calculateStreamedPercentage.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/calculateStreamedPercentage.t.sol rename to test/unit/concrete/nft-descriptor/calculateStreamedPercentage.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/generateAttributes.t.sol b/test/unit/concrete/nft-descriptor/generateAttributes.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/generateAttributes.t.sol rename to test/unit/concrete/nft-descriptor/generateAttributes.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/generateDescription.t.sol b/test/unit/concrete/nft-descriptor/generateDescription.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/generateDescription.t.sol rename to test/unit/concrete/nft-descriptor/generateDescription.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/generateName.t.sol b/test/unit/concrete/nft-descriptor/generateName.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/generateName.t.sol rename to test/unit/concrete/nft-descriptor/generateName.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/generateSVG.t.sol b/test/unit/concrete/nft-descriptor/generateSVG.t.sol similarity index 99% rename from test/core/unit/concrete/nft-descriptor/generateSVG.t.sol rename to test/unit/concrete/nft-descriptor/generateSVG.t.sol index d2da3edf6..451e564e8 100644 --- a/test/core/unit/concrete/nft-descriptor/generateSVG.t.sol +++ b/test/unit/concrete/nft-descriptor/generateSVG.t.sol @@ -2,8 +2,8 @@ // solhint-disable max-line-length pragma solidity >=0.8.22 <0.9.0; -import { NFTSVG } from "src/core/libraries/NFTSVG.sol"; -import { SVGElements } from "src/core/libraries/SVGElements.sol"; +import { NFTSVG } from "src/libraries/NFTSVG.sol"; +import { SVGElements } from "src/libraries/SVGElements.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/unit/concrete/nft-descriptor/hourglass.t.sol b/test/unit/concrete/nft-descriptor/hourglass.t.sol similarity index 96% rename from test/core/unit/concrete/nft-descriptor/hourglass.t.sol rename to test/unit/concrete/nft-descriptor/hourglass.t.sol index 383dbf39f..184859180 100644 --- a/test/core/unit/concrete/nft-descriptor/hourglass.t.sol +++ b/test/unit/concrete/nft-descriptor/hourglass.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { LibString } from "solady/src/utils/LibString.sol"; -import { SVGElements } from "src/core/libraries/SVGElements.sol"; +import { SVGElements } from "src/libraries/SVGElements.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/unit/concrete/nft-descriptor/stringifyCardType.t.sol b/test/unit/concrete/nft-descriptor/stringifyCardType.t.sol similarity index 90% rename from test/core/unit/concrete/nft-descriptor/stringifyCardType.t.sol rename to test/unit/concrete/nft-descriptor/stringifyCardType.t.sol index be2e10f7c..ad3e21634 100644 --- a/test/core/unit/concrete/nft-descriptor/stringifyCardType.t.sol +++ b/test/unit/concrete/nft-descriptor/stringifyCardType.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { SVGElements } from "src/core/libraries/SVGElements.sol"; +import { SVGElements } from "src/libraries/SVGElements.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/unit/concrete/nft-descriptor/stringifyFractionalAmount.t.sol b/test/unit/concrete/nft-descriptor/stringifyFractionalAmount.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/stringifyFractionalAmount.t.sol rename to test/unit/concrete/nft-descriptor/stringifyFractionalAmount.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/stringifyPercentage.t.sol b/test/unit/concrete/nft-descriptor/stringifyPercentage.t.sol similarity index 100% rename from test/core/unit/concrete/nft-descriptor/stringifyPercentage.t.sol rename to test/unit/concrete/nft-descriptor/stringifyPercentage.t.sol diff --git a/test/core/unit/concrete/nft-descriptor/stringifyStatus.t.sol b/test/unit/concrete/nft-descriptor/stringifyStatus.t.sol similarity index 93% rename from test/core/unit/concrete/nft-descriptor/stringifyStatus.t.sol rename to test/unit/concrete/nft-descriptor/stringifyStatus.t.sol index 36e7786f8..5bbf16c48 100644 --- a/test/core/unit/concrete/nft-descriptor/stringifyStatus.t.sol +++ b/test/unit/concrete/nft-descriptor/stringifyStatus.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Lockup } from "src/core/types/DataTypes.sol"; +import { Lockup } from "src/types/DataTypes.sol"; import { Base_Test } from "test/Base.t.sol"; diff --git a/test/core/unit/fuzz/transferAdmin.t.sol b/test/unit/fuzz/transferAdmin.t.sol similarity index 91% rename from test/core/unit/fuzz/transferAdmin.t.sol rename to test/unit/fuzz/transferAdmin.t.sol index 491888c8e..89d82d5ad 100644 --- a/test/core/unit/fuzz/transferAdmin.t.sol +++ b/test/unit/fuzz/transferAdmin.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { IAdminable } from "src/core/interfaces/IAdminable.sol"; -import { Errors } from "src/core/libraries/Errors.sol"; +import { IAdminable } from "src/interfaces/IAdminable.sol"; +import { Errors } from "src/libraries/Errors.sol"; import { Adminable_Unit_Shared_Test } from "../shared/Adminable.t.sol"; diff --git a/test/core/unit/shared/Adminable.t.sol b/test/unit/shared/Adminable.t.sol similarity index 88% rename from test/core/unit/shared/Adminable.t.sol rename to test/unit/shared/Adminable.t.sol index c78a4f94b..9a0ffe2b8 100644 --- a/test/core/unit/shared/Adminable.t.sol +++ b/test/unit/shared/Adminable.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Base_Test } from "../../../Base.t.sol"; -import { AdminableMock } from "../../../mocks/AdminableMock.sol"; +import { Base_Test } from "../../Base.t.sol"; +import { AdminableMock } from "../../mocks/AdminableMock.sol"; abstract contract Adminable_Unit_Shared_Test is Base_Test { AdminableMock internal adminableMock; diff --git a/test/utils/Assertions.sol b/test/utils/Assertions.sol index e9339d7f1..f137a52c0 100644 --- a/test/utils/Assertions.sol +++ b/test/utils/Assertions.sol @@ -5,8 +5,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { PRBMathAssertions } from "@prb/math/test/utils/Assertions.sol"; -import { Lockup, LockupDynamic, LockupTranched } from "../../src/core/types/DataTypes.sol"; -import { MerkleLT } from "../../src/periphery/types/DataTypes.sol"; +import { Lockup, LockupDynamic, LockupTranched } from "../../src/types/DataTypes.sol"; abstract contract Assertions is PRBMathAssertions { /*////////////////////////////////////////////////////////////////////////// @@ -17,14 +16,12 @@ abstract contract Assertions is PRBMathAssertions { event log_named_array(string key, LockupTranched.Tranche[] tranches); - event log_named_array(string key, MerkleLT.TrancheWithPercentage[] tranchesWithPercentages); - event log_named_uint128(string key, uint128 value); event log_named_uint40(string key, uint40 value); /*////////////////////////////////////////////////////////////////////////// - CORE + FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @dev Compares two {Lockup.Amounts} struct entities. @@ -152,32 +149,4 @@ abstract contract Assertions is PRBMathAssertions { function assertNotEq(Lockup.Status a, Lockup.Status b, string memory err) internal pure { assertNotEq(uint256(a), uint256(b), err); } - - /*////////////////////////////////////////////////////////////////////////// - PERIPHERY - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Compares two {MerkleLT.TrancheWithPercentage} arrays. - function assertEq(MerkleLT.TrancheWithPercentage[] memory a, MerkleLT.TrancheWithPercentage[] memory b) internal { - if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { - emit log("Error: a == b not satisfied [MerkleLT.TrancheWithPercentage[]]"); - emit log_named_array(" Left", a); - emit log_named_array(" Right", b); - fail(); - } - } - - /// @dev Compares two {MerkleLT.TrancheWithPercentage} arrays. - function assertEq( - MerkleLT.TrancheWithPercentage[] memory a, - MerkleLT.TrancheWithPercentage[] memory b, - string memory err - ) - internal - { - if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { - emit log_named_string("Error", err); - assertEq(a, b); - } - } } diff --git a/test/utils/BatchLockupBuilder.sol b/test/utils/BatchLockupBuilder.sol index fc46aa48f..a09e14151 100644 --- a/test/utils/BatchLockupBuilder.sol +++ b/test/utils/BatchLockupBuilder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22; -import { BatchLockup, Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.sol"; +import { BatchLockup, Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/types/DataTypes.sol"; library BatchLockupBuilder { /// @notice Generates an array containing `batchSize` copies of `batchSingle`. diff --git a/test/utils/Calculations.sol b/test/utils/Calculations.sol index 4b18f72f1..618878a10 100644 --- a/test/utils/Calculations.sol +++ b/test/utils/Calculations.sol @@ -6,7 +6,7 @@ import { PRBMathCastingUint40 as CastingUint40 } from "@prb/math/src/casting/Uin import { SD59x18 } from "@prb/math/src/SD59x18.sol"; import { UD60x18, ud } from "@prb/math/src/UD60x18.sol"; -import { LockupDynamic, LockupLinear, LockupTranched } from "../../src/core/types/DataTypes.sol"; +import { LockupDynamic, LockupLinear, LockupTranched } from "../../src/types/DataTypes.sol"; abstract contract Calculations { using CastingUint128 for uint128; diff --git a/test/utils/Defaults.sol b/test/utils/Defaults.sol index 40cb03bda..517af1a16 100644 --- a/test/utils/Defaults.sol +++ b/test/utils/Defaults.sol @@ -2,31 +2,18 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Arrays } from "@openzeppelin/contracts/utils/Arrays.sol"; -import { ud2x18, uUNIT } from "@prb/math/src/UD2x18.sol"; -import { UD60x18, ud, ZERO } from "@prb/math/src/UD60x18.sol"; - -import { - Broker, - BatchLockup, - Lockup, - LockupDynamic, - LockupLinear, - LockupTranched -} from "../../src/core/types/DataTypes.sol"; -import { MerkleBase, MerkleLL, MerkleLT } from "../../src/periphery/types/DataTypes.sol"; +import { ud2x18 } from "@prb/math/src/UD2x18.sol"; +import { UD60x18, ZERO } from "@prb/math/src/UD60x18.sol"; + +import { BatchLockup, Broker, Lockup, LockupDynamic, LockupLinear, LockupTranched } from "../../src/types/DataTypes.sol"; import { ArrayBuilder } from "./ArrayBuilder.sol"; import { BatchLockupBuilder } from "./BatchLockupBuilder.sol"; import { Constants } from "./Constants.sol"; -import { MerkleBuilder } from "./MerkleBuilder.sol"; -import { Merkle } from "./Murky.sol"; import { Users } from "./Types.sol"; /// @notice Contract with default values used throughout the tests. -contract Defaults is Constants, Merkle { - using MerkleBuilder for uint256[]; - +contract Defaults is Constants { /*////////////////////////////////////////////////////////////////////////// GENERICS //////////////////////////////////////////////////////////////////////////*/ @@ -55,31 +42,6 @@ contract Defaults is Constants, Merkle { uint40 public immutable WARP_26_PERCENT; uint40 public immutable WARP_26_PERCENT_DURATION = 2600 seconds; // 26% of the way through the stream - /*////////////////////////////////////////////////////////////////////////// - MERKLE-LOCKUP - //////////////////////////////////////////////////////////////////////////*/ - - uint256 public constant AGGREGATE_AMOUNT = CLAIM_AMOUNT * RECIPIENT_COUNT; - bool public constant CANCELABLE = false; - uint128 public constant CLAIM_AMOUNT = 10_000e18; - uint256 public constant DEFAULT_SABLIER_FEE = 0.005e18; - uint40 public immutable EXPIRATION; - uint40 public constant FIRST_CLAIM_TIME = JULY_1_2024; - uint256 public constant INDEX1 = 1; - uint256 public constant INDEX2 = 2; - uint256 public constant INDEX3 = 3; - uint256 public constant INDEX4 = 4; - string public constant IPFS_CID = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"; - uint256[] public LEAVES = new uint256[](RECIPIENT_COUNT); - uint256 public constant RECIPIENT_COUNT = 4; - bytes32 public MERKLE_ROOT; - string public constant NAME = "Airdrop Campaign"; - bytes32 public constant NAME_BYTES32 = bytes32(abi.encodePacked("Airdrop Campaign")); - uint40 public immutable STREAM_START_TIME_NON_ZERO = JULY_1_2024 - 2 days; - uint40 public immutable STREAM_START_TIME_ZERO = 0; - uint64 public constant TOTAL_PERCENTAGE = uUNIT; - bool public constant TRANSFERABLE = false; - /*////////////////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////////////////*/ @@ -95,7 +57,6 @@ contract Defaults is Constants, Merkle { START_TIME = JULY_1_2024 + 2 days; CLIFF_TIME = START_TIME + CLIFF_DURATION; END_TIME = START_TIME + TOTAL_DURATION; - EXPIRATION = JULY_1_2024 + 12 weeks; MAX_SEGMENT_DURATION = TOTAL_DURATION / uint40(MAX_COUNT); WARP_26_PERCENT = START_TIME + WARP_26_PERCENT_DURATION; } @@ -104,17 +65,6 @@ contract Defaults is Constants, Merkle { HELPERS //////////////////////////////////////////////////////////////////////////*/ - /// @dev We need a separate function to initialize the Merkle tree because, at the construction time, the users are - /// not yet set. - function initMerkleTree() public { - LEAVES[0] = MerkleBuilder.computeLeaf(INDEX1, users.recipient1, CLAIM_AMOUNT); - LEAVES[1] = MerkleBuilder.computeLeaf(INDEX2, users.recipient2, CLAIM_AMOUNT); - LEAVES[2] = MerkleBuilder.computeLeaf(INDEX3, users.recipient3, CLAIM_AMOUNT); - LEAVES[3] = MerkleBuilder.computeLeaf(INDEX4, users.recipient4, CLAIM_AMOUNT); - MerkleBuilder.sortLeaves(LEAVES); - MERKLE_ROOT = getRoot(LEAVES.toBytes32()); - } - function setAsset(IERC20 asset_) public { asset = asset_; } @@ -302,8 +252,8 @@ contract Defaults is Constants, Merkle { BATCH-LOCKUP //////////////////////////////////////////////////////////////////////////*/ - function incrementalStreamIds() public pure returns (uint256[] memory streamIds) { - return ArrayBuilder.fillStreamIds({ firstStreamId: 1, batchSize: BATCH_SIZE }); + function incrementalStreamIds(uint256 firstStreamId) public pure returns (uint256[] memory streamIds) { + return ArrayBuilder.fillStreamIds({ firstStreamId: firstStreamId, batchSize: BATCH_SIZE }); } /// @dev Returns a default-size batch of {BatchLockup.CreateWithDurationsLD} parameters. @@ -362,111 +312,4 @@ contract Defaults is Constants, Merkle { { batch = BatchLockupBuilder.fillBatch(createWithTimestampsBrokerNull(), tranches(), batchSize); } - - /*////////////////////////////////////////////////////////////////////////// - MERKLE-LOCKUP - //////////////////////////////////////////////////////////////////////////*/ - - function baseParams() public view returns (MerkleBase.ConstructorParams memory) { - return baseParams(users.campaignOwner, asset, EXPIRATION, MERKLE_ROOT); - } - - function baseParams( - address campaignOwner, - IERC20 asset_, - uint40 expiration, - bytes32 merkleRoot - ) - public - pure - returns (MerkleBase.ConstructorParams memory) - { - return MerkleBase.ConstructorParams({ - asset: asset_, - expiration: expiration, - initialAdmin: campaignOwner, - ipfsCID: IPFS_CID, - merkleRoot: merkleRoot, - name: NAME - }); - } - - function index1Proof() public view returns (bytes32[] memory) { - uint256 leaf = MerkleBuilder.computeLeaf(INDEX1, users.recipient1, CLAIM_AMOUNT); - uint256 pos = Arrays.findUpperBound(LEAVES, leaf); - return getProof(LEAVES.toBytes32(), pos); - } - - function index2Proof() public view returns (bytes32[] memory) { - uint256 leaf = MerkleBuilder.computeLeaf(INDEX2, users.recipient2, CLAIM_AMOUNT); - uint256 pos = Arrays.findUpperBound(LEAVES, leaf); - return getProof(LEAVES.toBytes32(), pos); - } - - function index3Proof() public view returns (bytes32[] memory) { - uint256 leaf = MerkleBuilder.computeLeaf(INDEX3, users.recipient3, CLAIM_AMOUNT); - uint256 pos = Arrays.findUpperBound(LEAVES, leaf); - return getProof(LEAVES.toBytes32(), pos); - } - - function index4Proof() public view returns (bytes32[] memory) { - uint256 leaf = MerkleBuilder.computeLeaf(INDEX4, users.recipient4, CLAIM_AMOUNT); - uint256 pos = Arrays.findUpperBound(LEAVES, leaf); - return getProof(LEAVES.toBytes32(), pos); - } - - function getLeaves() public view returns (uint256[] memory) { - return LEAVES; - } - - function schedule() public pure returns (MerkleLL.Schedule memory schedule_) { - schedule_.startTime = STREAM_START_TIME_ZERO; - schedule_.startAmount = START_AMOUNT; - schedule_.cliffDuration = CLIFF_DURATION; - schedule_.cliffAmount = CLIFF_AMOUNT; - schedule_.totalDuration = TOTAL_DURATION; - } - - /// @dev Mirros the logic from {SablierMerkleLT._calculateStartTimeAndTranches}. - function tranchesMerkleLT( - uint40 streamStartTime, - uint128 totalAmount - ) - public - view - returns (LockupTranched.Tranche[] memory tranches_) - { - tranches_ = new LockupTranched.Tranche[](2); - if (streamStartTime == 0) { - tranches_[0].timestamp = uint40(block.timestamp) + WARP_26_PERCENT_DURATION; - tranches_[1].timestamp = uint40(block.timestamp) + TOTAL_DURATION; - } else { - tranches_[0].timestamp = streamStartTime + WARP_26_PERCENT_DURATION; - tranches_[1].timestamp = streamStartTime + TOTAL_DURATION; - } - - uint128 amount0 = ud(totalAmount).mul(tranchesWithPercentages()[0].unlockPercentage.intoUD60x18()).intoUint128(); - uint128 amount1 = ud(totalAmount).mul(tranchesWithPercentages()[1].unlockPercentage.intoUD60x18()).intoUint128(); - - tranches_[0].amount = amount0; - tranches_[1].amount = amount1; - - uint128 amountsSum = amount0 + amount1; - - if (amountsSum != totalAmount) { - tranches_[1].amount += totalAmount - amountsSum; - } - } - - function tranchesWithPercentages() - public - pure - returns (MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages_) - { - tranchesWithPercentages_ = new MerkleLT.TrancheWithPercentage[](2); - tranchesWithPercentages_[0] = - MerkleLT.TrancheWithPercentage({ unlockPercentage: ud2x18(0.26e18), duration: 2600 seconds }); - tranchesWithPercentages_[1] = - MerkleLT.TrancheWithPercentage({ unlockPercentage: ud2x18(0.74e18), duration: 7400 seconds }); - } } diff --git a/test/utils/DeployOptimized.sol b/test/utils/DeployOptimized.sol index 040599b89..cfd6256e9 100644 --- a/test/utils/DeployOptimized.sol +++ b/test/utils/DeployOptimized.sol @@ -3,16 +3,12 @@ pragma solidity >=0.8.22 <0.9.0; import { CommonBase } from "forge-std/src/Base.sol"; import { StdCheats } from "forge-std/src/StdCheats.sol"; -import { ILockupNFTDescriptor } from "./../../src/core/interfaces/ILockupNFTDescriptor.sol"; -import { ISablierBatchLockup } from "./../../src/core/interfaces/ISablierBatchLockup.sol"; -import { ISablierLockup } from "./../../src/core/interfaces/ISablierLockup.sol"; -import { ISablierMerkleFactory } from "./../../src/periphery/interfaces/ISablierMerkleFactory.sol"; -abstract contract DeployOptimized is StdCheats, CommonBase { - /*////////////////////////////////////////////////////////////////////////// - CORE - //////////////////////////////////////////////////////////////////////////*/ +import { ILockupNFTDescriptor } from "../../src/interfaces/ILockupNFTDescriptor.sol"; +import { ISablierBatchLockup } from "../../src/interfaces/ISablierBatchLockup.sol"; +import { ISablierLockup } from "../../src/interfaces/ISablierLockup.sol"; +abstract contract DeployOptimized is StdCheats, CommonBase { /// @dev Deploys {SablierBatchLockup} from an optimized source compiled with `--via-ir`. function deployOptimizedBatchLockup() internal returns (ISablierBatchLockup) { return ISablierBatchLockup(deployCode("out-optimized/SablierBatchLockup.sol/SablierBatchLockup.json")); @@ -52,12 +48,12 @@ abstract contract DeployOptimized is StdCheats, CommonBase { return ILockupNFTDescriptor(deployCode("out-optimized/LockupNFTDescriptor.sol/LockupNFTDescriptor.json")); } - /// @notice Deploys all Lockup contracts from an optimized source compiled with `--via-ir` in the following order: + /// @notice Deploys all contracts from an optimized source compiled with `--via-ir` in the following order: /// /// 1. {LockupNFTDescriptor} /// 2. {SablierLockup} /// 3. {SablierBatchLockup} - function deployOptimizedCore( + function deployOptimizedProtocol( address initialAdmin, uint256 maxCount ) @@ -68,41 +64,4 @@ abstract contract DeployOptimized is StdCheats, CommonBase { lockup_ = deployOptimizedLockup(initialAdmin, nftDescriptor_, maxCount); batchLockup_ = deployOptimizedBatchLockup(); } - - /*////////////////////////////////////////////////////////////////////////// - PERIPHERY - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Deploys {SablierMerkleFactory} from an optimized source compiled with `--via-ir`. - function deployOptimizedMerkleFactory(address initialAdmin) internal returns (ISablierMerkleFactory) { - return ISablierMerkleFactory( - deployCode("out-optimized/SablierMerkleFactory.sol/SablierMerkleFactory.json", abi.encode(initialAdmin)) - ); - } - - /*////////////////////////////////////////////////////////////////////////// - PROTOCOL - //////////////////////////////////////////////////////////////////////////*/ - - /// @notice Deploys all Lockup and Periphery contracts from an optimized source in the following order: - /// - /// 1. {LockupNFTDescriptor} - /// 2. {SablierLockup} - /// 5. {SablierBatchLockup} - /// 6. {SablierMerkleFactory} - function deployOptimizedProtocol( - address initialAdmin, - uint256 maxCount - ) - internal - returns ( - ILockupNFTDescriptor nftDescriptor_, - ISablierLockup lockup_, - ISablierBatchLockup batchLockup_, - ISablierMerkleFactory merkleFactory_ - ) - { - (nftDescriptor_, lockup_, batchLockup_) = deployOptimizedCore(initialAdmin, maxCount); - (merkleFactory_) = deployOptimizedMerkleFactory(initialAdmin); - } } diff --git a/test/utils/Fuzzers.sol b/test/utils/Fuzzers.sol index 3b2f30c9e..05ecf59b2 100644 --- a/test/utils/Fuzzers.sol +++ b/test/utils/Fuzzers.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22; import { PRBMathCastingUint128 as CastingUint128 } from "@prb/math/src/casting/Uint128.sol"; import { UD60x18, ud, uUNIT } from "@prb/math/src/UD60x18.sol"; -import { Lockup, LockupDynamic, LockupTranched } from "../../src/core/types/DataTypes.sol"; +import { Lockup, LockupDynamic, LockupTranched } from "../../src/types/DataTypes.sol"; import { Constants } from "./Constants.sol"; import { Utils } from "./Utils.sol"; diff --git a/test/utils/MerkleBuilder.sol b/test/utils/MerkleBuilder.sol deleted file mode 100644 index ad6bb0c20..000000000 --- a/test/utils/MerkleBuilder.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// solhint-disable reason-string -pragma solidity >=0.8.22; - -import { LibSort } from "solady/src/utils/LibSort.sol"; - -/// @dev A helper library for building Merkle leaves, roots, and proofs. -library MerkleBuilder { - /// @dev Function that double hashes the data needed for a Merkle tree leaf. - function computeLeaf(uint256 index, address recipient, uint128 amount) internal pure returns (uint256 leaf) { - leaf = uint256(keccak256(bytes.concat(keccak256(abi.encode(index, recipient, amount))))); - } - - /// @dev A batch function for `computeLeaf`. - function computeLeaves( - uint256[] memory indexes, - address[] memory recipient, - uint128[] memory amount - ) - internal - pure - returns (uint256[] memory leaves) - { - uint256 count = indexes.length; - require(count == recipient.length && count == amount.length, "Merkle leaves arrays must have the same length"); - leaves = new uint256[](count); - for (uint256 i = 0; i < count; ++i) { - leaves[i] = computeLeaf(indexes[i], recipient[i], amount[i]); - } - } - - /// @dev Function that convert a storage array to memory and sorts it in ascending order. We need this - /// because `LibSort` does not support storage arrays. - function sortLeaves(uint256[] storage leaves) internal { - uint256 leavesCount = leaves.length; - - // Declare the memory array. - uint256[] memory _leaves = new uint256[](leavesCount); - for (uint256 i = 0; i < leavesCount; ++i) { - _leaves[i] = leaves[i]; - } - - // Sort the memory array. - LibSort.sort(_leaves); - - // Copy the memory array back to storage. - for (uint256 i = 0; i < leavesCount; ++i) { - leaves[i] = _leaves[i]; - } - } - - /// @dev Function that converts an array of `uint256` to an array of `bytes32`. - function toBytes32(uint256[] storage arr_) internal view returns (bytes32[] memory arr) { - arr = new bytes32[](arr_.length); - for (uint256 i = 0; i < arr_.length; ++i) { - arr[i] = bytes32(arr_[i]); - } - } -} diff --git a/test/utils/MerkleBuilder.t.sol b/test/utils/MerkleBuilder.t.sol deleted file mode 100644 index ff6700857..000000000 --- a/test/utils/MerkleBuilder.t.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22; - -import { StdAssertions } from "forge-std/src/StdAssertions.sol"; -import { StdUtils } from "forge-std/src/StdUtils.sol"; - -import { MerkleBuilder } from "./MerkleBuilder.sol"; - -contract MerkleBuilder_Test is StdAssertions, StdUtils { - function testFuzz_ComputeLeaf(uint256 index, address recipient, uint128 amount) external pure { - uint256 actualLeaf = MerkleBuilder.computeLeaf(index, recipient, amount); - uint256 expectedLeaf = uint256(keccak256(bytes.concat(keccak256(abi.encode(index, recipient, amount))))); - assertEq(actualLeaf, expectedLeaf, "computeLeaf"); - } - - /// @dev We declare this struct so that we will not need cheatcodes in the `computeLeaves` test. - struct LeavesParams { - uint256 indexes; - address recipients; - uint128 amounts; - } - - function testFuzz_ComputeLeaves(LeavesParams[] memory params) external pure { - uint256 count = params.length; - - uint256[] memory indexes = new uint256[](count); - address[] memory recipients = new address[](count); - uint128[] memory amounts = new uint128[](count); - for (uint256 i = 0; i < count; ++i) { - indexes[i] = params[i].indexes; - recipients[i] = params[i].recipients; - amounts[i] = params[i].amounts; - } - - uint256[] memory actualLeaves = new uint256[](count); - actualLeaves = MerkleBuilder.computeLeaves(indexes, recipients, amounts); - - uint256[] memory expectedLeaves = new uint256[](count); - for (uint256 i = 0; i < count; ++i) { - expectedLeaves[i] = - uint256(keccak256(bytes.concat(keccak256(abi.encode(indexes[i], recipients[i], amounts[i]))))); - } - - assertEq(actualLeaves, expectedLeaves, "computeLeaves"); - } -} diff --git a/test/utils/Modifiers.sol b/test/utils/Modifiers.sol index 6c02edd18..3358310bc 100644 --- a/test/utils/Modifiers.sol +++ b/test/utils/Modifiers.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; import { Defaults } from "./Defaults.sol"; import { Fuzzers } from "./Fuzzers.sol"; @@ -147,80 +147,6 @@ abstract contract Modifiers is Fuzzers { _; } - /*////////////////////////////////////////////////////////////////////////// - CAMPAIGN-COMMON - //////////////////////////////////////////////////////////////////////////*/ - - modifier givenCampaignNotExpired() { - _; - } - - modifier givenMsgValueNotLessThanSablierFee() { - _; - } - - modifier givenRecipientNotClaimed() { - _; - } - - modifier givenSevenDaysPassed() { - vm.warp({ newTimestamp: getBlockTimestamp() + 8 days }); - _; - } - - modifier whenAmountValid() { - _; - } - - modifier whenCallerCampaignOwner() { - resetPrank({ msgSender: users.campaignOwner }); - _; - } - - modifier whenExpirationNotZero() { - _; - } - - modifier whenIndexInMerkleTree() { - _; - } - - modifier whenIndexValid() { - _; - } - - modifier whenMerkleProofValid() { - _; - } - - modifier whenPercentagesSumNot100Pct() { - _; - } - - modifier whenPercentagesSumNotOverflow() { - _; - } - - modifier whenProvidedMerkleLockupValid() { - _; - } - - modifier whenRecipientValid() { - _; - } - - modifier whenScheduledStartTimeZero() { - _; - } - - modifier whenTotalPercentage100() { - _; - } - - modifier whenTotalPercentageNot100() { - _; - } - /*////////////////////////////////////////////////////////////////////////// CANCEL //////////////////////////////////////////////////////////////////////////*/ @@ -357,18 +283,6 @@ abstract contract Modifiers is Fuzzers { _; } - /*////////////////////////////////////////////////////////////////////////// - CREATE-MERKLE - //////////////////////////////////////////////////////////////////////////*/ - - modifier givenCampaignNotExists() { - _; - } - - modifier whenNameNotTooLong() { - _; - } - /*////////////////////////////////////////////////////////////////////////// CREATE-WITH-DURATION //////////////////////////////////////////////////////////////////////////*/ diff --git a/test/utils/Murky.sol b/test/utils/Murky.sol deleted file mode 100644 index df29f9a4f..000000000 --- a/test/utils/Murky.sol +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable code-complexity,no-inline-assembly,reason-string -pragma solidity >=0.8.22; - -/// @dev Credits to https://github.com/dmfxyz/murky -abstract contract MurkyBase { - /** - * - * CONSTRUCTOR * - * - */ - constructor() { } - - /** - * - * VIRTUAL HASHING FUNCTIONS * - * - */ - function hashLeafPairs(bytes32 left, bytes32 right) public pure virtual returns (bytes32 _hash); - - /** - * - * PROOF VERIFICATION * - * - */ - function verifyProof(bytes32 root, bytes32[] memory proof, bytes32 valueToProve) external pure returns (bool) { - // proof length must be less than max array size - bytes32 rollingHash = valueToProve; - uint256 length = proof.length; - unchecked { - for (uint256 i = 0; i < length; ++i) { - rollingHash = hashLeafPairs(rollingHash, proof[i]); - } - } - return root == rollingHash; - } - - /** - * - * PROOF GENERATION * - * - */ - function getRoot(bytes32[] memory data) public pure returns (bytes32) { - require(data.length > 1, "won't generate root for single leaf"); - while (data.length > 1) { - data = hashLevel(data); - } - return data[0]; - } - - function getProof(bytes32[] memory data, uint256 node) public pure returns (bytes32[] memory) { - require(data.length > 1, "won't generate proof for single leaf"); - // The size of the proof is equal to the ceiling of log2(numLeaves) - bytes32[] memory result = new bytes32[](log2ceilBitMagic(data.length)); - uint256 pos = 0; - - // Two overflow risks: node, pos - // node: max array size is 2**256-1. Largest index in the array will be 1 less than that. Also, - // for dynamic arrays, size is limited to 2**64-1 - // pos: pos is bounded by log2(data.length), which should be less than type(uint256).max - while (data.length > 1) { - unchecked { - if (node & 0x1 == 1) { - result[pos] = data[node - 1]; - } else if (node + 1 == data.length) { - result[pos] = bytes32(0); - } else { - result[pos] = data[node + 1]; - } - ++pos; - node /= 2; - } - data = hashLevel(data); - } - return result; - } - - ///@dev function is private to prevent unsafe data from being passed - function hashLevel(bytes32[] memory data) private pure returns (bytes32[] memory) { - bytes32[] memory result; - - // Function is private, and all internal callers check that data.length >=2. - // Underflow is not possible as lowest possible value for data/result index is 1 - // overflow should be safe as length is / 2 always. - unchecked { - uint256 length = data.length; - if (length & 0x1 == 1) { - result = new bytes32[](length / 2 + 1); - result[result.length - 1] = hashLeafPairs(data[length - 1], bytes32(0)); - } else { - result = new bytes32[](length / 2); - } - // pos is upper bounded by data.length / 2, so safe even if array is at max size - uint256 pos = 0; - for (uint256 i = 0; i < length - 1; i += 2) { - result[pos] = hashLeafPairs(data[i], data[i + 1]); - ++pos; - } - } - return result; - } - - /** - * - * MATH "LIBRARY" * - * - */ - - /// @dev Note that x is assumed > 0 - function log2ceil(uint256 x) public pure returns (uint256) { - uint256 ceil = 0; - uint256 pOf2; - // If x is a power of 2, then this function will return a ceiling - // that is 1 greater than the actual ceiling. So we need to check if - // x is a power of 2, and subtract one from ceil if so. - assembly { - // we check by seeing if x == (~x + 1) & x. This applies a mask - // to find the lowest set bit of x and then checks it for equality - // with x. If they are equal, then x is a power of 2. - - /* Example - x has single bit set - x := 0000_1000 - (~x + 1) = (1111_0111) + 1 = 1111_1000 - (1111_1000 & 0000_1000) = 0000_1000 == x - - x has multiple bits set - x := 1001_0010 - (~x + 1) = (0110_1101 + 1) = 0110_1110 - (0110_1110 & x) = 0000_0010 != x - */ - - // we do some assembly magic to treat the bool as an integer later on - pOf2 := eq(and(add(not(x), 1), x), x) - } - - // if x == type(uint256).max, than ceil is capped at 256 - // if x == 0, then pO2 == 0, so ceil won't underflow - unchecked { - while (x > 0) { - x >>= 1; - ceil++; - } - ceil -= pOf2; // see above - } - return ceil; - } - - /// Original bitmagic adapted from https://github.com/paulrberg/prb-math/blob/main/contracts/PRBMath.sol - /// @dev Note that x assumed > 1 - function log2ceilBitMagic(uint256 x) public pure returns (uint256) { - if (x <= 1) { - return 0; - } - uint256 msb = 0; - uint256 _x = x; - if (x >= 2 ** 128) { - x >>= 128; - msb += 128; - } - if (x >= 2 ** 64) { - x >>= 64; - msb += 64; - } - if (x >= 2 ** 32) { - x >>= 32; - msb += 32; - } - if (x >= 2 ** 16) { - x >>= 16; - msb += 16; - } - if (x >= 2 ** 8) { - x >>= 8; - msb += 8; - } - if (x >= 2 ** 4) { - x >>= 4; - msb += 4; - } - if (x >= 2 ** 2) { - x >>= 2; - msb += 2; - } - if (x >= 2 ** 1) { - msb += 1; - } - - uint256 lsb = (~_x + 1) & _x; - if ((lsb == _x) && (msb > 0)) { - return msb; - } else { - return msb + 1; - } - } -} - -/// @notice Nascent, simple, kinda efficient (and improving!) Merkle proof generator and verifier -/// @author dmfxyz -/// @dev Note Generic Merkle Tree -contract Merkle is MurkyBase { - /** - * - * HASHING FUNCTION * - * - */ - - /// ascending sort and concat prior to hashing - function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32 _hash) { - assembly { - switch lt(left, right) - case 0 { - mstore(0x0, right) - mstore(0x20, left) - } - default { - mstore(0x0, left) - mstore(0x20, right) - } - _hash := keccak256(0x0, 0x40) - } - } -} diff --git a/test/utils/Precompiles.t.sol b/test/utils/Precompiles.t.sol index d0dd63a29..731ce4a4d 100644 --- a/test/utils/Precompiles.t.sol +++ b/test/utils/Precompiles.t.sol @@ -4,11 +4,9 @@ pragma solidity >=0.8.22 <0.9.0; import { Precompiles } from "precompiles/Precompiles.sol"; import { LibString } from "solady/src/utils/LibString.sol"; -import { ILockupNFTDescriptor } from "src/core/interfaces/ILockupNFTDescriptor.sol"; -import { ISablierBatchLockup } from "src/core/interfaces/ISablierBatchLockup.sol"; -import { ISablierLockup } from "src/core/interfaces/ISablierLockup.sol"; -import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; - +import { ILockupNFTDescriptor } from "src/interfaces/ILockupNFTDescriptor.sol"; +import { ISablierBatchLockup } from "src/interfaces/ISablierBatchLockup.sol"; +import { ISablierLockup } from "src/interfaces/ISablierLockup.sol"; import { Base_Test } from "./../Base.t.sol"; contract Precompiles_Test is Base_Test { @@ -22,10 +20,6 @@ contract Precompiles_Test is Base_Test { } } - /*////////////////////////////////////////////////////////////////////////// - CORE - //////////////////////////////////////////////////////////////////////////*/ - function test_DeployBatchLockup() external onlyTestOptimizedProfile { address actualBatchLockup = address(precompiles.deployBatchLockup()); address expectedBatchLockup = address(deployOptimizedBatchLockup()); @@ -45,15 +39,15 @@ contract Precompiles_Test is Base_Test { assertEq(actualNFTDescriptor.code, expectedNFTDescriptor.code, "bytecodes mismatch"); } - function test_DeployCore() external onlyTestOptimizedProfile { + function test_DeployProtocol() external onlyTestOptimizedProfile { (ILockupNFTDescriptor actualNFTDescriptor, ISablierLockup actualLockup, ISablierBatchLockup actualBatchLockup) = - precompiles.deployCore(users.admin); + precompiles.deployProtocol(users.admin); ( ILockupNFTDescriptor expectedNFTDescriptor, ISablierLockup expectedLockup, ISablierBatchLockup expectedBatchLockup - ) = deployOptimizedCore(users.admin, precompiles.MAX_COUNT()); + ) = deployOptimizedProtocol(users.admin, precompiles.MAX_COUNT()); bytes memory expectedLockupCode = adjustBytecode(address(expectedLockup).code, address(expectedLockup), address(actualLockup)); @@ -63,16 +57,6 @@ contract Precompiles_Test is Base_Test { assertEq(address(actualBatchLockup).code, address(expectedBatchLockup).code, "bytecodes mismatch"); } - /*////////////////////////////////////////////////////////////////////////// - PERIPHERY - //////////////////////////////////////////////////////////////////////////*/ - - function test_DeployMerkleFactory() external onlyTestOptimizedProfile { - address actualFactory = address(precompiles.deployMerkleFactory(users.admin)); - address expectedFactory = address(deployOptimizedMerkleFactory(users.admin)); - assertEq(actualFactory.code, expectedFactory.code, "bytecodes mismatch"); - } - /*////////////////////////////////////////////////////////////////////////// HELPERS //////////////////////////////////////////////////////////////////////////*/ diff --git a/test/utils/Types.sol b/test/utils/Types.sol index f30f7348f..c638a23f9 100644 --- a/test/utils/Types.sol +++ b/test/utils/Types.sol @@ -8,19 +8,12 @@ struct Users { address payable alice; // Default stream broker. address payable broker; - // Default campaign owner. - address payable campaignOwner; // Malicious user. address payable eve; // Default NFT operator. address payable operator; // Default stream recipient. address payable recipient; - // Other recipients. - address payable recipient1; - address payable recipient2; - address payable recipient3; - address payable recipient4; // Default stream sender. address payable sender; } diff --git a/test/utils/Utils.sol b/test/utils/Utils.sol index 95164243d..578299e1f 100644 --- a/test/utils/Utils.sol +++ b/test/utils/Utils.sol @@ -5,7 +5,7 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { PRBMathUtils } from "@prb/math/test/utils/Utils.sol"; import { CommonBase } from "forge-std/src/Base.sol"; -import { LockupDynamic, LockupTranched } from "../../src/core/types/DataTypes.sol"; +import { LockupDynamic, LockupTranched } from "../../src/types/DataTypes.sol"; abstract contract Utils is CommonBase, PRBMathUtils { /// @dev Bounds a `uint128` number.