From 3813020e4f31227fee49f65499c18873d6996083 Mon Sep 17 00:00:00 2001 From: andreivladbrg Date: Tue, 12 Nov 2024 18:38:22 +0200 Subject: [PATCH] refactor: move batch lockup contract in core refactor: remove deploy periphery scripts refactor: update scripts accordingly chore: add SALT as immutable in BaseScript test: move batch lockup tests in core --- precompiles/Precompiles.sol | 57 +++++----- script/Base.s.sol | 9 +- .../DeployBatchLockup.t.sol | 2 +- script/core/DeployCore.s.sol | 4 +- .../core/DeployDeterministicBatchLockup.t.sol | 13 +++ script/core/DeployDeterministicCore.s.sol | 9 +- script/core/DeployDeterministicLockup.s.sol | 3 +- .../DeployDeterministicNFTDescriptor.s.sol | 3 +- .../DeployDeterministicBatchLockup.s.sol | 16 --- .../DeployDeterministicMerkleFactory.s.sol | 15 +++ .../DeployDeterministicPeriphery.s.sol | 27 ----- script/periphery/DeployPeriphery.s.sol | 23 ---- .../DeployDeterministicProtocol.s.sol | 19 ++-- script/protocol/DeployProtocol.s.sol | 12 +- script/protocol/DeploymentLogger.s.sol | 14 +-- .../SablierBatchLockup.sol | 6 +- .../interfaces/ISablierBatchLockup.sol | 0 src/core/libraries/Errors.sol | 6 + src/core/types/DataTypes.sol | 75 +++++++++++++ src/periphery/libraries/Errors.sol | 6 - src/periphery/types/DataTypes.sol | 75 ------------- test/Base.t.sol | 105 +++++++++++++++++- .../createWithDurationsLD.t.sol | 10 +- .../createWithDurationsLD.tree | 0 .../createWithDurationsLL.t.sol | 10 +- .../createWithDurationsLL.tree | 0 .../createWithDurationsLT.t.sol | 10 +- .../createWithDurationsLT.tree | 0 .../createWithTimestampsLD.t.sol | 10 +- .../createWithTimestampsLD.tree | 0 .../createWithTimestamps.t.sol | 10 +- .../createWithTimestamps.tree | 0 .../createWithTimestampsLT.t.sol | 10 +- .../createWithTimestampsLT.tree | 0 .../fuzz/lockup-linear/streamedAmountOf.t.sol | 2 +- test/periphery/Periphery.t.sol | 102 +---------------- .../batch-lockup/createWithTimestampsLD.t.sol | 3 +- .../batch-lockup/createWithTimestampsLL.t.sol | 3 +- .../batch-lockup/createWithTimestampsLT.t.sol | 3 +- .../merkle-campaign/MerkleCampaign.t.sol | 2 - test/utils/BatchLockupBuilder.sol | 4 +- test/utils/Defaults.sol | 11 +- test/utils/DeployOptimized.sol | 38 +++---- test/utils/Precompiles.t.sol | 38 +++---- 44 files changed, 352 insertions(+), 413 deletions(-) rename script/{periphery => core}/DeployBatchLockup.t.sol (80%) create mode 100644 script/core/DeployDeterministicBatchLockup.t.sol delete mode 100644 script/periphery/DeployDeterministicBatchLockup.s.sol create mode 100644 script/periphery/DeployDeterministicMerkleFactory.s.sol delete mode 100644 script/periphery/DeployDeterministicPeriphery.s.sol delete mode 100644 script/periphery/DeployPeriphery.s.sol rename src/{periphery => core}/SablierBatchLockup.sol (98%) rename src/{periphery => core}/interfaces/ISablierBatchLockup.sol (100%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol (85%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree (100%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol (86%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree (100%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol (85%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree (100%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol (85%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree (100%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol (86%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree (100%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol (85%) rename test/{periphery/integration => core/integration/concrete}/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree (100%) diff --git a/precompiles/Precompiles.sol b/precompiles/Precompiles.sol index 455cad283..bed370067 100644 --- a/precompiles/Precompiles.sol +++ b/precompiles/Precompiles.sol @@ -3,9 +3,9 @@ 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 { ISablierBatchLockup } from "./../src/periphery/interfaces/ISablierBatchLockup.sol"; import { ISablierMerkleFactory } from "./../src/periphery/interfaces/ISablierMerkleFactory.sol"; /// @notice This is useful for external integrations seeking to test against the exact deployed bytecode, as recompiling @@ -33,6 +33,25 @@ contract Precompiles { CORE //////////////////////////////////////////////////////////////////////////*/ + /// @notice Deploys {SablierBatchLockup} from precompiled bytecode. + function deployBatchLockup() public returns (ISablierBatchLockup batchLockup) { + bytes memory creationBytecode = BYTECODE_BATCH_LOCKUP; + assembly { + batchLockup := create(0, add(creationBytecode, 0x20), mload(creationBytecode)) + } + 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`. @@ -87,28 +106,10 @@ contract Precompiles { ); } - /// @notice Deploys all Core contracts. - function deployCore(address initialAdmin) - public - returns (ILockupNFTDescriptor nftDescriptor, ISablierLockup lockup) - { - nftDescriptor = deployNFTDescriptor(); - lockup = deployLockup(initialAdmin); - } - /*////////////////////////////////////////////////////////////////////////// PERIPHERY //////////////////////////////////////////////////////////////////////////*/ - /// @notice Deploys {SablierBatchLockup} from precompiled bytecode. - function deployBatchLockup() public returns (ISablierBatchLockup batchLockup) { - bytes memory creationBytecode = BYTECODE_BATCH_LOCKUP; - assembly { - batchLockup := create(0, add(creationBytecode, 0x20), mload(creationBytecode)) - } - require(address(batchLockup) != address(0), "Lockup Precompiles: deployment failed for BatchLockup contract"); - } - /// @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)); @@ -118,17 +119,9 @@ contract Precompiles { require(address(factory) != address(0), "Lockup Precompiles: deployment failed for MerkleFactory contract"); } - /// @notice Deploys all Periphery contracts in the following order: - /// - /// 1. {SablierBatchLockup} - /// 2. {SablierMerkleFactory} - function deployPeriphery(address initialAdmin) - public - returns (ISablierBatchLockup batchLockup, ISablierMerkleFactory merkleFactory) - { - batchLockup = deployBatchLockup(); - merkleFactory = deployMerkleFactory(initialAdmin); - } + /*////////////////////////////////////////////////////////////////////////// + PROTOCOL + //////////////////////////////////////////////////////////////////////////*/ /// @notice Deploys the entire Lockup Protocol from precompiled bytecode. /// @@ -146,9 +139,9 @@ contract Precompiles { ) { // Deploy Core. - (nftDescriptor, lockup) = deployCore(initialAdmin); + (nftDescriptor, lockup, batchLockup) = deployCore(initialAdmin); // Deploy Periphery. - (batchLockup, merkleFactory) = deployPeriphery(initialAdmin); + merkleFactory = deployMerkleFactory(initialAdmin); } } diff --git a/script/Base.s.sol b/script/Base.s.sol index 0c0e40857..90eea5da7 100644 --- a/script/Base.s.sol +++ b/script/Base.s.sol @@ -15,12 +15,12 @@ contract BaseScript is Script { /// @dev The default value for `maxCountMap`. uint256 internal constant DEFAULT_MAX_COUNT = 500; + /// @dev The salt used for deterministic deployments. + bytes32 internal immutable SALT; + /// @dev Included to enable compilation of the script without a $MNEMONIC environment variable. string internal constant TEST_MNEMONIC = "test test test test test test test test test test test junk"; - /// @dev Needed for the deterministic deployments. - bytes32 internal constant ZERO_SALT = bytes32(0); - /// @dev The address of the transaction broadcaster. address internal broadcaster; @@ -46,6 +46,9 @@ contract BaseScript is Script { (broadcaster,) = deriveRememberKey({ mnemonic: mnemonic, index: 0 }); } + // Construct the salt for deterministic deployments. + SALT = constructCreate2Salt(); + // Populate the max count map for segments and tranches. populateMaxCountMap(); diff --git a/script/periphery/DeployBatchLockup.t.sol b/script/core/DeployBatchLockup.t.sol similarity index 80% rename from script/periphery/DeployBatchLockup.t.sol rename to script/core/DeployBatchLockup.t.sol index 188738fb5..15ffc50f6 100644 --- a/script/periphery/DeployBatchLockup.t.sol +++ b/script/core/DeployBatchLockup.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol"; +import { SablierBatchLockup } from "../../src/core/SablierBatchLockup.sol"; import { BaseScript } from "../Base.s.sol"; diff --git a/script/core/DeployCore.s.sol b/script/core/DeployCore.s.sol index cf5791f48..2795476bf 100644 --- a/script/core/DeployCore.s.sol +++ b/script/core/DeployCore.s.sol @@ -2,6 +2,7 @@ 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"; @@ -12,9 +13,10 @@ contract DeployCore is BaseScript { public virtual broadcast - returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup) + 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/DeployDeterministicBatchLockup.t.sol b/script/core/DeployDeterministicBatchLockup.t.sol new file mode 100644 index 000000000..d720b56fc --- /dev/null +++ b/script/core/DeployDeterministicBatchLockup.t.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.8.22 <0.9.0; + +import { SablierBatchLockup } from "../../src/core/SablierBatchLockup.sol"; + +import { BaseScript } from "../Base.s.sol"; + +contract DeployDeterministicBatchLockup is BaseScript { + /// @dev Deploy via Forge. + function run() public virtual broadcast returns (SablierBatchLockup batchLockup) { + batchLockup = new SablierBatchLockup(); + } +} diff --git a/script/core/DeployDeterministicCore.s.sol b/script/core/DeployDeterministicCore.s.sol index 8b88358c6..4eb7c981e 100644 --- a/script/core/DeployDeterministicCore.s.sol +++ b/script/core/DeployDeterministicCore.s.sol @@ -2,6 +2,7 @@ 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"; @@ -12,10 +13,10 @@ contract DeployDeterministicCore is BaseScript { public virtual broadcast - returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup) + returns (LockupNFTDescriptor nftDescriptor, SablierLockup lockup, SablierBatchLockup batchLockup) { - bytes32 salt = constructCreate2Salt(); - nftDescriptor = new LockupNFTDescriptor{ salt: salt }(); - lockup = new SablierLockup{ salt: salt }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + nftDescriptor = new LockupNFTDescriptor{ salt: SALT }(); + lockup = new SablierLockup{ salt: SALT }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + batchLockup = new SablierBatchLockup{ salt: SALT }(); } } diff --git a/script/core/DeployDeterministicLockup.s.sol b/script/core/DeployDeterministicLockup.s.sol index 00c60a440..cf9058486 100644 --- a/script/core/DeployDeterministicLockup.s.sol +++ b/script/core/DeployDeterministicLockup.s.sol @@ -17,7 +17,6 @@ contract DeployDeterministicLockup is BaseScript { broadcast returns (SablierLockup lockup) { - bytes32 salt = constructCreate2Salt(); - lockup = new SablierLockup{ salt: salt }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + lockup = new SablierLockup{ salt: SALT }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); } } diff --git a/script/core/DeployDeterministicNFTDescriptor.s.sol b/script/core/DeployDeterministicNFTDescriptor.s.sol index 4b8530117..74e3855b9 100644 --- a/script/core/DeployDeterministicNFTDescriptor.s.sol +++ b/script/core/DeployDeterministicNFTDescriptor.s.sol @@ -9,7 +9,6 @@ import { BaseScript } from "../Base.s.sol"; /// @dev Reverts if the contract has already been deployed. contract DeployDeterministicNFTDescriptor is BaseScript { function run() public virtual broadcast returns (LockupNFTDescriptor nftDescriptor) { - bytes32 salt = constructCreate2Salt(); - nftDescriptor = new LockupNFTDescriptor{ salt: salt }(); + nftDescriptor = new LockupNFTDescriptor{ salt: SALT }(); } } diff --git a/script/periphery/DeployDeterministicBatchLockup.s.sol b/script/periphery/DeployDeterministicBatchLockup.s.sol deleted file mode 100644 index 94e39e448..000000000 --- a/script/periphery/DeployDeterministicBatchLockup.s.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol"; - -import { BaseScript } from "../Base.s.sol"; - -/// @notice Deploys {SablierBatchLockup} at a deterministic address across chains. -/// @dev Reverts if the contract has already been deployed. -contract DeployDeterministicBatchLockup is BaseScript { - /// @dev Deploy via Forge. - function run() public virtual broadcast returns (SablierBatchLockup batchLockup) { - bytes32 salt = constructCreate2Salt(); - batchLockup = new SablierBatchLockup{ salt: salt }(); - } -} diff --git a/script/periphery/DeployDeterministicMerkleFactory.s.sol b/script/periphery/DeployDeterministicMerkleFactory.s.sol new file mode 100644 index 000000000..f63aaef87 --- /dev/null +++ b/script/periphery/DeployDeterministicMerkleFactory.s.sol @@ -0,0 +1,15 @@ +// 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"; + +/// @dev Deploys {SablierMerkleFactory} at a deterministic address across chains. +/// @dev Reverts if the contract has already been deployed. +contract DeployDeterministicMerkleFactory is BaseScript { + /// @dev Deploy via Forge. + function run(address initialAdmin) public virtual broadcast returns (SablierMerkleFactory merkleFactory) { + merkleFactory = new SablierMerkleFactory{ salt: SALT }(initialAdmin); + } +} diff --git a/script/periphery/DeployDeterministicPeriphery.s.sol b/script/periphery/DeployDeterministicPeriphery.s.sol deleted file mode 100644 index 79122e01d..000000000 --- a/script/periphery/DeployDeterministicPeriphery.s.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol"; -import { SablierMerkleFactory } from "../../src/periphery/SablierMerkleFactory.sol"; - -import { BaseScript } from "../Base.s.sol"; - -/// @notice Deploys all Periphery contracts at deterministic addresses across chains, in the following order: -/// -/// 1. {SablierBatchLockup} -/// 2. {SablierMerkleFactory} -/// -/// @dev Reverts if any contract has already been deployed. -contract DeployDeterministicPeriphery is BaseScript { - /// @dev Deploy via Forge. - function run(address initialAdmin) - public - virtual - broadcast - returns (SablierBatchLockup batchLockup, SablierMerkleFactory merkleFactory) - { - bytes32 salt = constructCreate2Salt(); - batchLockup = new SablierBatchLockup{ salt: salt }(); - merkleFactory = new SablierMerkleFactory{ salt: salt }(initialAdmin); - } -} diff --git a/script/periphery/DeployPeriphery.s.sol b/script/periphery/DeployPeriphery.s.sol deleted file mode 100644 index c2dfe9100..000000000 --- a/script/periphery/DeployPeriphery.s.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { SablierBatchLockup } from "./../../src/periphery/SablierBatchLockup.sol"; -import { SablierMerkleFactory } from "./../../src/periphery/SablierMerkleFactory.sol"; -import { BaseScript } from "./../Base.s.sol"; - -/// @notice Deploys all Periphery contract in the following order: -/// -/// 1. {SablierBatchLockup} -/// 2. {SablierMerkleFactory} -contract DeployPeriphery is BaseScript { - /// @dev Deploy via Forge. - function run(address initialAdmin) - public - virtual - broadcast - returns (SablierBatchLockup batchLockup, SablierMerkleFactory merkleFactory) - { - batchLockup = new SablierBatchLockup(); - merkleFactory = new SablierMerkleFactory(initialAdmin); - } -} diff --git a/script/protocol/DeployDeterministicProtocol.s.sol b/script/protocol/DeployDeterministicProtocol.s.sol index 0d2ffa0c1..2ce94952b 100644 --- a/script/protocol/DeployDeterministicProtocol.s.sol +++ b/script/protocol/DeployDeterministicProtocol.s.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { LockupNFTDescriptor } from "../../src/core/LockupNFTDescriptor.sol"; -import { SablierLockup } from "../../src/core/SablierLockup.sol"; -import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol"; -import { SablierMerkleFactory } from "../../src/periphery/SablierMerkleFactory.sol"; - +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. @@ -50,15 +49,13 @@ contract DeployDeterministicProtocol is DeploymentLogger("deterministic") { SablierMerkleFactory merkleLockupFactory ) { - bytes32 salt = constructCreate2Salt(); - // Deploy Core. - nftDescriptor = new LockupNFTDescriptor{ salt: salt }(); - lockup = new SablierLockup{ salt: salt }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + nftDescriptor = new LockupNFTDescriptor{ salt: SALT }(); + lockup = new SablierLockup{ salt: SALT }(initialAdmin, nftDescriptor, maxCountMap[block.chainid]); + batchLockup = new SablierBatchLockup{ salt: SALT }(); // Deploy Periphery. - batchLockup = new SablierBatchLockup{ salt: salt }(); - merkleLockupFactory = new SablierMerkleFactory{ salt: salt }(initialAdmin); + 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 index b5f58a622..d92e4e58c 100644 --- a/script/protocol/DeployProtocol.s.sol +++ b/script/protocol/DeployProtocol.s.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22 <0.9.0; -import { LockupNFTDescriptor } from "../../src/core/LockupNFTDescriptor.sol"; -import { SablierLockup } from "../../src/core/SablierLockup.sol"; -import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol"; -import { SablierMerkleFactory } from "../../src/periphery/SablierMerkleFactory.sol"; - +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. @@ -50,9 +49,12 @@ contract DeployProtocol is DeploymentLogger("non_deterministic") { 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( diff --git a/script/protocol/DeploymentLogger.s.sol b/script/protocol/DeploymentLogger.s.sol index 0fb49c7d2..d2baa29b0 100644 --- a/script/protocol/DeploymentLogger.s.sol +++ b/script/protocol/DeploymentLogger.s.sol @@ -74,6 +74,13 @@ abstract contract DeploymentLogger is BaseScript { string memory firstTwoLines = "| Contract | Address | Deployment |\n | :------- | :------ | :----------|"; _appendToFile(firstTwoLines); + string memory batchLockupLine = _getContractLine({ + contractName: "SablierBatchLockup", + contractAddress: batchLockup.toHexString(), + coreOrPeriphery: "core" + }); + _appendToFile(batchLockupLine); + string memory lockupLine = _getContractLine({ contractName: "SablierLockup", contractAddress: lockup.toHexString(), @@ -92,13 +99,6 @@ abstract contract DeploymentLogger is BaseScript { _appendToFile(peripheryTitle); _appendToFile(firstTwoLines); - string memory batchLockupLine = _getContractLine({ - contractName: "SablierBatchLockup", - contractAddress: batchLockup.toHexString(), - coreOrPeriphery: "periphery" - }); - _appendToFile(batchLockupLine); - string memory merkleFactoryLine = _getContractLine({ contractName: "MerkleFactory", contractAddress: merkleFactory.toHexString(), diff --git a/src/periphery/SablierBatchLockup.sol b/src/core/SablierBatchLockup.sol similarity index 98% rename from src/periphery/SablierBatchLockup.sol rename to src/core/SablierBatchLockup.sol index 274e0d2f3..da878fa17 100644 --- a/src/periphery/SablierBatchLockup.sol +++ b/src/core/SablierBatchLockup.sol @@ -4,12 +4,10 @@ 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 { ISablierLockup } from "../core/interfaces/ISablierLockup.sol"; -import { Lockup } from "../core/types/DataTypes.sol"; - import { ISablierBatchLockup } from "./interfaces/ISablierBatchLockup.sol"; +import { ISablierLockup } from "./interfaces/ISablierLockup.sol"; import { Errors } from "./libraries/Errors.sol"; -import { BatchLockup } from "./types/DataTypes.sol"; +import { BatchLockup, Lockup } from "./types/DataTypes.sol"; /// @title SablierBatchLockup /// @notice See the documentation in {ISablierBatchLockup}. diff --git a/src/periphery/interfaces/ISablierBatchLockup.sol b/src/core/interfaces/ISablierBatchLockup.sol similarity index 100% rename from src/periphery/interfaces/ISablierBatchLockup.sol rename to src/core/interfaces/ISablierBatchLockup.sol diff --git a/src/core/libraries/Errors.sol b/src/core/libraries/Errors.sol index 935b72609..19cbddc13 100644 --- a/src/core/libraries/Errors.sol +++ b/src/core/libraries/Errors.sol @@ -22,6 +22,12 @@ library Errors { /// @notice Thrown when trying to delegate call to a function that disallows delegate calls. error DelegateCall(); + /*////////////////////////////////////////////////////////////////////////// + SABLIER-BATCH-LOCKUP + //////////////////////////////////////////////////////////////////////////*/ + + error SablierBatchLockup_BatchSizeZero(); + /*////////////////////////////////////////////////////////////////////////// LOCKUP-NFT-DESCRIPTOR //////////////////////////////////////////////////////////////////////////*/ diff --git a/src/core/types/DataTypes.sol b/src/core/types/DataTypes.sol index 8e80e5ca2..31c00ea90 100644 --- a/src/core/types/DataTypes.sol +++ b/src/core/types/DataTypes.sol @@ -7,6 +7,7 @@ import { UD60x18 } from "@prb/math/src/UD60x18.sol"; // This file defines all structs used in Lockup, most of which are organized under three namespaces: // +// - BatchLockup // - Lockup // - LockupDynamic // - LockupLinear @@ -16,6 +17,80 @@ import { UD60x18 } from "@prb/math/src/UD60x18.sol"; // storage layout of the struct. It is more gas efficient to group small data types together so // that they fit in a single 32-byte slot. +/// @dev Namespace for the structs used in `BatchLockup` contract. +library BatchLockup { + /// @notice A struct encapsulating all parameters of {SablierLockup.createWithDurationsLD} except for the asset. + struct CreateWithDurationsLD { + address sender; + address recipient; + uint128 totalAmount; + bool cancelable; + bool transferable; + LockupDynamic.SegmentWithDuration[] segmentsWithDuration; + Broker broker; + } + + /// @notice A struct encapsulating all parameters of {SablierLockup.createWithDurationsLL} except for the asset. + struct CreateWithDurationsLL { + address sender; + address recipient; + uint128 totalAmount; + bool cancelable; + bool transferable; + LockupLinear.Durations durations; + LockupLinear.UnlockAmounts unlockAmounts; + Broker broker; + } + + /// @notice A struct encapsulating all parameters of {SablierLockup.createWithDurationsLT} except for the asset. + struct CreateWithDurationsLT { + address sender; + address recipient; + uint128 totalAmount; + bool cancelable; + bool transferable; + LockupTranched.TrancheWithDuration[] tranchesWithDuration; + Broker broker; + } + + /// @notice A struct encapsulating all parameters of {SablierLockup.createWithTimestampsLD} except for the asset. + struct CreateWithTimestampsLD { + address sender; + address recipient; + uint128 totalAmount; + bool cancelable; + bool transferable; + uint40 startTime; + LockupDynamic.Segment[] segments; + Broker broker; + } + + /// @notice A struct encapsulating all parameters of {SablierLockup.createWithTimestampsLL} except for the asset. + struct CreateWithTimestampsLL { + address sender; + address recipient; + uint128 totalAmount; + bool cancelable; + bool transferable; + Lockup.Timestamps timestamps; + uint40 cliffTime; + LockupLinear.UnlockAmounts unlockAmounts; + Broker broker; + } + + /// @notice A struct encapsulating all parameters of {SablierLockup.createWithTimestampsLT} except for the asset. + struct CreateWithTimestampsLT { + address sender; + address recipient; + uint128 totalAmount; + bool cancelable; + bool transferable; + uint40 startTime; + LockupTranched.Tranche[] tranches; + Broker broker; + } +} + /// @notice Struct encapsulating the broker parameters passed to the create functions. Both can be set to zero. /// @param account The address receiving the broker's fee. /// @param fee The broker's percentage fee from the total amount, denoted as a fixed-point number where 1e18 is 100%. diff --git a/src/periphery/libraries/Errors.sol b/src/periphery/libraries/Errors.sol index 813f4aed3..885135822 100644 --- a/src/periphery/libraries/Errors.sol +++ b/src/periphery/libraries/Errors.sol @@ -4,12 +4,6 @@ pragma solidity >=0.8.22; /// @title Errors /// @notice Library containing all custom errors the protocol may revert with. library Errors { - /*////////////////////////////////////////////////////////////////////////// - SABLIER-BATCH-LOCKUP - //////////////////////////////////////////////////////////////////////////*/ - - error SablierBatchLockup_BatchSizeZero(); - /*////////////////////////////////////////////////////////////////////////// SABLIER-MERKLE-FACTORY //////////////////////////////////////////////////////////////////////////*/ diff --git a/src/periphery/types/DataTypes.sol b/src/periphery/types/DataTypes.sol index c74084a2e..8969c2f4f 100644 --- a/src/periphery/types/DataTypes.sol +++ b/src/periphery/types/DataTypes.sol @@ -4,81 +4,6 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { UD2x18 } from "@prb/math/src/UD2x18.sol"; -import { Broker, Lockup, LockupDynamic, LockupLinear, LockupTranched } from "../../core/types/DataTypes.sol"; - -library BatchLockup { - /// @notice A struct encapsulating all parameters of {SablierLockup.createWithDurationsLD} except for the asset. - struct CreateWithDurationsLD { - address sender; - address recipient; - uint128 totalAmount; - bool cancelable; - bool transferable; - LockupDynamic.SegmentWithDuration[] segmentsWithDuration; - Broker broker; - } - - /// @notice A struct encapsulating all parameters of {SablierLockup.createWithDurationsLL} except for the asset. - struct CreateWithDurationsLL { - address sender; - address recipient; - uint128 totalAmount; - bool cancelable; - bool transferable; - LockupLinear.Durations durations; - LockupLinear.UnlockAmounts unlockAmounts; - Broker broker; - } - - /// @notice A struct encapsulating all parameters of {SablierLockup.createWithDurationsLT} except for the asset. - struct CreateWithDurationsLT { - address sender; - address recipient; - uint128 totalAmount; - bool cancelable; - bool transferable; - LockupTranched.TrancheWithDuration[] tranchesWithDuration; - Broker broker; - } - - /// @notice A struct encapsulating all parameters of {SablierLockup.createWithTimestampsLD} except for the asset. - struct CreateWithTimestampsLD { - address sender; - address recipient; - uint128 totalAmount; - bool cancelable; - bool transferable; - uint40 startTime; - LockupDynamic.Segment[] segments; - Broker broker; - } - - /// @notice A struct encapsulating all parameters of {SablierLockup.createWithTimestampsLL} except for the asset. - struct CreateWithTimestampsLL { - address sender; - address recipient; - uint128 totalAmount; - bool cancelable; - bool transferable; - Lockup.Timestamps timestamps; - uint40 cliffTime; - LockupLinear.UnlockAmounts unlockAmounts; - Broker broker; - } - - /// @notice A struct encapsulating all parameters of {SablierLockup.createWithTimestampsLT} except for the asset. - struct CreateWithTimestampsLT { - address sender; - address recipient; - uint128 totalAmount; - bool cancelable; - bool transferable; - uint40 startTime; - LockupTranched.Tranche[] tranches; - Broker broker; - } -} - 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. diff --git a/test/Base.t.sol b/test/Base.t.sol index cc2b780ff..a9855fc04 100644 --- a/test/Base.t.sol +++ b/test/Base.t.sol @@ -2,19 +2,18 @@ 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 { ISablierBatchLockup } from "src/periphery/interfaces/ISablierBatchLockup.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 { SablierBatchLockup } from "src/periphery/SablierBatchLockup.sol"; import { SablierMerkleFactory } from "src/periphery/SablierMerkleFactory.sol"; - import { ERC20MissingReturn } from "./mocks/erc20/ERC20MissingReturn.sol"; import { ERC20Mock } from "./mocks/erc20/ERC20Mock.sol"; import { RecipientGood } from "./mocks/Hooks.sol"; @@ -220,4 +219,102 @@ abstract contract Base_Test is Assertions, Calculations, DeployOptimized, Modifi data: abi.encodeCall(IERC20.transferFrom, (from, to, value)) }); } + + /*////////////////////////////////////////////////////////////////////////// + CALL EXPECTS - LOCKUP + //////////////////////////////////////////////////////////////////////////*/ + + /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLD}, each with the specified `params`. + function expectMultipleCallsToCreateWithDurationsLD( + uint64 count, + Lockup.CreateWithDurations memory params, + LockupDynamic.SegmentWithDuration[] memory segments + ) + internal + { + vm.expectCall({ + callee: address(lockup), + count: count, + data: abi.encodeCall(ISablierLockup.createWithDurationsLD, (params, segments)) + }); + } + + /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLL}, each with the specified `params`. + function expectMultipleCallsToCreateWithDurationsLL( + uint64 count, + Lockup.CreateWithDurations memory params, + LockupLinear.UnlockAmounts memory unlockAmounts, + LockupLinear.Durations memory durations + ) + internal + { + vm.expectCall({ + callee: address(lockup), + count: count, + data: abi.encodeCall(ISablierLockup.createWithDurationsLL, (params, unlockAmounts, durations)) + }); + } + + /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLT}, each with the specified `params`. + function expectMultipleCallsToCreateWithDurationsLT( + uint64 count, + Lockup.CreateWithDurations memory params, + LockupTranched.TrancheWithDuration[] memory tranches + ) + internal + { + vm.expectCall({ + callee: address(lockup), + count: count, + data: abi.encodeCall(ISablierLockup.createWithDurationsLT, (params, tranches)) + }); + } + + /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLD}, each with the specified `params`. + function expectMultipleCallsToCreateWithTimestampsLD( + uint64 count, + Lockup.CreateWithTimestamps memory params, + LockupDynamic.Segment[] memory segments + ) + internal + { + vm.expectCall({ + callee: address(lockup), + count: count, + data: abi.encodeCall(ISablierLockup.createWithTimestampsLD, (params, segments)) + }); + } + + /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLL}, each with the specified + /// `params`. + function expectMultipleCallsToCreateWithTimestampsLL( + uint64 count, + Lockup.CreateWithTimestamps memory params, + LockupLinear.UnlockAmounts memory unlockAmounts, + uint40 cliffTime + ) + internal + { + vm.expectCall({ + callee: address(lockup), + count: count, + data: abi.encodeCall(ISablierLockup.createWithTimestampsLL, (params, unlockAmounts, cliffTime)) + }); + } + + /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLT}, each with the specified + /// `params`. + function expectMultipleCallsToCreateWithTimestampsLT( + uint64 count, + Lockup.CreateWithTimestamps memory params, + LockupTranched.Tranche[] memory tranches + ) + internal + { + vm.expectCall({ + callee: address(lockup), + count: count, + data: abi.encodeCall(ISablierLockup.createWithTimestampsLT, (params, tranches)) + }); + } } diff --git a/test/periphery/integration/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol b/test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol similarity index 85% rename from test/periphery/integration/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol rename to test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol index e75f99091..895043314 100644 --- a/test/periphery/integration/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol +++ b/test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { Errors } from "src/core/libraries/Errors.sol"; +import { BatchLockup } from "src/core/types/DataTypes.sol"; -import { Periphery_Test } from "../../../Periphery.t.sol"; +import { Base_Test } from "test/Base.t.sol"; -contract CreateWithDurationsLD_Integration_Test is Periphery_Test { +contract CreateWithDurationsLD_Integration_Test is Base_Test { function setUp() public virtual override { - Periphery_Test.setUp(); + Base_Test.setUp(); resetPrank({ msgSender: users.sender }); } diff --git a/test/periphery/integration/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree b/test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree similarity index 100% rename from test/periphery/integration/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree rename to test/core/integration/concrete/batch-lockup/create-with-durations-ld/createWithDurationsLD.tree diff --git a/test/periphery/integration/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol b/test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol similarity index 86% rename from test/periphery/integration/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol rename to test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol index ef0662570..ae9e846e4 100644 --- a/test/periphery/integration/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol +++ b/test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { Errors } from "src/core/libraries/Errors.sol"; +import { BatchLockup } from "src/core/types/DataTypes.sol"; -import { Periphery_Test } from "../../../Periphery.t.sol"; +import { Base_Test } from "test/Base.t.sol"; -contract CreateWithDurationsLL_Integration_Test is Periphery_Test { +contract CreateWithDurationsLL_Integration_Test is Base_Test { function setUp() public virtual override { - Periphery_Test.setUp(); + Base_Test.setUp(); resetPrank({ msgSender: users.sender }); } diff --git a/test/periphery/integration/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree b/test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree similarity index 100% rename from test/periphery/integration/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree rename to test/core/integration/concrete/batch-lockup/create-with-durations-ll/createWithDurationsLL.tree diff --git a/test/periphery/integration/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol b/test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol similarity index 85% rename from test/periphery/integration/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol rename to test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol index b8ae540d5..a2f0172d3 100644 --- a/test/periphery/integration/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol +++ b/test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { Errors } from "src/core/libraries/Errors.sol"; +import { BatchLockup } from "src/core/types/DataTypes.sol"; -import { Periphery_Test } from "../../../Periphery.t.sol"; +import { Base_Test } from "test/Base.t.sol"; -contract CreateWithDurationsLT_Integration_Test is Periphery_Test { +contract CreateWithDurationsLT_Integration_Test is Base_Test { function setUp() public virtual override { - Periphery_Test.setUp(); + Base_Test.setUp(); resetPrank({ msgSender: users.sender }); } diff --git a/test/periphery/integration/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree b/test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree similarity index 100% rename from test/periphery/integration/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree rename to test/core/integration/concrete/batch-lockup/create-with-durations-lt/createWithDurationsLT.tree diff --git a/test/periphery/integration/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol b/test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol similarity index 85% rename from test/periphery/integration/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol rename to test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol index e4b024deb..b4478106d 100644 --- a/test/periphery/integration/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol +++ b/test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { Errors } from "src/core/libraries/Errors.sol"; +import { BatchLockup } from "src/core/types/DataTypes.sol"; -import { Periphery_Test } from "../../../Periphery.t.sol"; +import { Base_Test } from "test/Base.t.sol"; -contract CreateWithTimestampsLD_Integration_Test is Periphery_Test { +contract CreateWithTimestampsLD_Integration_Test is Base_Test { function setUp() public virtual override { - Periphery_Test.setUp(); + Base_Test.setUp(); resetPrank({ msgSender: users.sender }); } diff --git a/test/periphery/integration/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree b/test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree similarity index 100% rename from test/periphery/integration/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree rename to test/core/integration/concrete/batch-lockup/create-with-timestamps-ld/createWithTimestampsLD.tree diff --git a/test/periphery/integration/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol b/test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol similarity index 86% rename from test/periphery/integration/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol rename to test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol index 377977c28..673719c34 100644 --- a/test/periphery/integration/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol +++ b/test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { Errors } from "src/core/libraries/Errors.sol"; +import { BatchLockup } from "src/core/types/DataTypes.sol"; -import { Periphery_Test } from "../../../Periphery.t.sol"; +import { Base_Test } from "test/Base.t.sol"; -contract CreateWithTimestampsLL_Integration_Test is Periphery_Test { +contract CreateWithTimestampsLL_Integration_Test is Base_Test { function setUp() public virtual override { - Periphery_Test.setUp(); + Base_Test.setUp(); resetPrank({ msgSender: users.sender }); } diff --git a/test/periphery/integration/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree b/test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree similarity index 100% rename from test/periphery/integration/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree rename to test/core/integration/concrete/batch-lockup/create-with-timestamps-ll/createWithTimestamps.tree diff --git a/test/periphery/integration/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol b/test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol similarity index 85% rename from test/periphery/integration/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol rename to test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol index 5fd468265..c3fea43ef 100644 --- a/test/periphery/integration/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol +++ b/test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22 <0.9.0; -import { Errors } from "src/periphery/libraries/Errors.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { Errors } from "src/core/libraries/Errors.sol"; +import { BatchLockup } from "src/core/types/DataTypes.sol"; -import { Periphery_Test } from "../../../Periphery.t.sol"; +import { Base_Test } from "test/Base.t.sol"; -contract CreateWithTimestampsLT_Integration_Test is Periphery_Test { +contract CreateWithTimestampsLT_Integration_Test is Base_Test { function setUp() public virtual override { - Periphery_Test.setUp(); + Base_Test.setUp(); resetPrank({ msgSender: users.sender }); } diff --git a/test/periphery/integration/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree b/test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree similarity index 100% rename from test/periphery/integration/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree rename to test/core/integration/concrete/batch-lockup/create-with-timestamps-lt/createWithTimestampsLT.tree diff --git a/test/core/integration/fuzz/lockup-linear/streamedAmountOf.t.sol b/test/core/integration/fuzz/lockup-linear/streamedAmountOf.t.sol index 8fe1d231d..e3a7602d0 100644 --- a/test/core/integration/fuzz/lockup-linear/streamedAmountOf.t.sol +++ b/test/core/integration/fuzz/lockup-linear/streamedAmountOf.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 { LockupLinear } from "src/core/types/DataTypes.sol"; import { Lockup_Linear_Integration_Fuzz_Test } from "./LockupLinear.t.sol"; diff --git a/test/periphery/Periphery.t.sol b/test/periphery/Periphery.t.sol index 12fe839ce..ed9e5a4f7 100644 --- a/test/periphery/Periphery.t.sol +++ b/test/periphery/Periphery.t.sol @@ -3,9 +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 { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.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"; @@ -35,104 +33,6 @@ contract Periphery_Test is Base_Test { vm.label({ account: address(contractWithReceiveEth), newLabel: "Contract With Receive Eth" }); } - /*////////////////////////////////////////////////////////////////////////// - CALL EXPECTS - LOCKUP - //////////////////////////////////////////////////////////////////////////*/ - - /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLD}, each with the specified `params`. - function expectMultipleCallsToCreateWithDurationsLD( - uint64 count, - Lockup.CreateWithDurations memory params, - LockupDynamic.SegmentWithDuration[] memory segments - ) - internal - { - vm.expectCall({ - callee: address(lockup), - count: count, - data: abi.encodeCall(ISablierLockup.createWithDurationsLD, (params, segments)) - }); - } - - /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLL}, each with the specified `params`. - function expectMultipleCallsToCreateWithDurationsLL( - uint64 count, - Lockup.CreateWithDurations memory params, - LockupLinear.UnlockAmounts memory unlockAmounts, - LockupLinear.Durations memory durations - ) - internal - { - vm.expectCall({ - callee: address(lockup), - count: count, - data: abi.encodeCall(ISablierLockup.createWithDurationsLL, (params, unlockAmounts, durations)) - }); - } - - /// @dev Expects multiple calls to {ISablierLockup.createWithDurationsLT}, each with the specified `params`. - function expectMultipleCallsToCreateWithDurationsLT( - uint64 count, - Lockup.CreateWithDurations memory params, - LockupTranched.TrancheWithDuration[] memory tranches - ) - internal - { - vm.expectCall({ - callee: address(lockup), - count: count, - data: abi.encodeCall(ISablierLockup.createWithDurationsLT, (params, tranches)) - }); - } - - /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLD}, each with the specified `params`. - function expectMultipleCallsToCreateWithTimestampsLD( - uint64 count, - Lockup.CreateWithTimestamps memory params, - LockupDynamic.Segment[] memory segments - ) - internal - { - vm.expectCall({ - callee: address(lockup), - count: count, - data: abi.encodeCall(ISablierLockup.createWithTimestampsLD, (params, segments)) - }); - } - - /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLL}, each with the specified - /// `params`. - function expectMultipleCallsToCreateWithTimestampsLL( - uint64 count, - Lockup.CreateWithTimestamps memory params, - LockupLinear.UnlockAmounts memory unlockAmounts, - uint40 cliffTime - ) - internal - { - vm.expectCall({ - callee: address(lockup), - count: count, - data: abi.encodeCall(ISablierLockup.createWithTimestampsLL, (params, unlockAmounts, cliffTime)) - }); - } - - /// @dev Expects multiple calls to {ISablierLockup.createWithTimestampsLT}, each with the specified - /// `params`. - function expectMultipleCallsToCreateWithTimestampsLT( - uint64 count, - Lockup.CreateWithTimestamps memory params, - LockupTranched.Tranche[] memory tranches - ) - internal - { - vm.expectCall({ - callee: address(lockup), - count: count, - data: abi.encodeCall(ISablierLockup.createWithTimestampsLT, (params, tranches)) - }); - } - /*////////////////////////////////////////////////////////////////////////// CALL EXPECTS - MERKLE LOCKUP //////////////////////////////////////////////////////////////////////////*/ diff --git a/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol b/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol index 5d092cd6a..ac8f34983 100644 --- a/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol +++ b/test/periphery/fork/batch-lockup/createWithTimestampsLD.t.sol @@ -3,8 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { BatchLockup, Lockup, LockupDynamic } from "src/core/types/DataTypes.sol"; import { ArrayBuilder } from "../../../utils/ArrayBuilder.sol"; import { BatchLockupBuilder } from "../../../utils/BatchLockupBuilder.sol"; diff --git a/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol b/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol index 5798b7360..098befcf3 100644 --- a/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol +++ b/test/periphery/fork/batch-lockup/createWithTimestampsLL.t.sol @@ -3,8 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { BatchLockup, Lockup, LockupLinear } from "src/core/types/DataTypes.sol"; import { ArrayBuilder } from "../../../utils/ArrayBuilder.sol"; import { BatchLockupBuilder } from "../../../utils/BatchLockupBuilder.sol"; diff --git a/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol b/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol index a2abde40e..60184abf3 100644 --- a/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol +++ b/test/periphery/fork/batch-lockup/createWithTimestampsLT.t.sol @@ -3,8 +3,7 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { BatchLockup, Lockup, LockupTranched } from "src/core/types/DataTypes.sol"; import { ArrayBuilder } from "../../../utils/ArrayBuilder.sol"; import { BatchLockupBuilder } from "../../../utils/BatchLockupBuilder.sol"; diff --git a/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol b/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol index ac1a33b79..10b773151 100644 --- a/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol +++ b/test/periphery/integration/merkle-campaign/MerkleCampaign.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; -import { LockupLinear } from "src/core/types/DataTypes.sol"; - import { ISablierMerkleBase } from "src/periphery/interfaces/ISablierMerkleBase.sol"; import { ISablierMerkleInstant } from "src/periphery/interfaces/ISablierMerkleInstant.sol"; import { ISablierMerkleLL } from "src/periphery/interfaces/ISablierMerkleLL.sol"; diff --git a/test/utils/BatchLockupBuilder.sol b/test/utils/BatchLockupBuilder.sol index 51655ce35..fc46aa48f 100644 --- a/test/utils/BatchLockupBuilder.sol +++ b/test/utils/BatchLockupBuilder.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.22; -import { Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.sol"; - -import { BatchLockup } from "src/periphery/types/DataTypes.sol"; +import { BatchLockup, Lockup, LockupDynamic, LockupLinear, LockupTranched } from "src/core/types/DataTypes.sol"; library BatchLockupBuilder { /// @notice Generates an array containing `batchSize` copies of `batchSingle`. diff --git a/test/utils/Defaults.sol b/test/utils/Defaults.sol index fc303220e..7ede8e27c 100644 --- a/test/utils/Defaults.sol +++ b/test/utils/Defaults.sol @@ -6,8 +6,15 @@ 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, Lockup, LockupDynamic, LockupLinear, LockupTranched } from "../../src/core/types/DataTypes.sol"; -import { BatchLockup, MerkleBase, MerkleLL, MerkleLT } from "../../src/periphery/types/DataTypes.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 { ArrayBuilder } from "./ArrayBuilder.sol"; import { BatchLockupBuilder } from "./BatchLockupBuilder.sol"; diff --git a/test/utils/DeployOptimized.sol b/test/utils/DeployOptimized.sol index 199786cdf..040599b89 100644 --- a/test/utils/DeployOptimized.sol +++ b/test/utils/DeployOptimized.sol @@ -3,17 +3,21 @@ 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 { ISablierLockup } from "../../src/core/interfaces/ISablierLockup.sol"; -import { ISablierBatchLockup } from "../../src/periphery/interfaces/ISablierBatchLockup.sol"; -import { ISablierMerkleFactory } from "../../src/periphery/interfaces/ISablierMerkleFactory.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 //////////////////////////////////////////////////////////////////////////*/ + /// @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")); + } + /// @dev Deploys the optimized {Helpers} and {VestingMath} libraries and assign them to linked addresses. function deployOptimizedLibraries() internal { address helpers = deployCode("out-optimized/Helpers.sol/Helpers.json"); @@ -52,26 +56,23 @@ abstract contract DeployOptimized is StdCheats, CommonBase { /// /// 1. {LockupNFTDescriptor} /// 2. {SablierLockup} + /// 3. {SablierBatchLockup} function deployOptimizedCore( address initialAdmin, uint256 maxCount ) internal - returns (ILockupNFTDescriptor nftDescriptor_, ISablierLockup lockup_) + returns (ILockupNFTDescriptor nftDescriptor_, ISablierLockup lockup_, ISablierBatchLockup batchLockup_) { nftDescriptor_ = deployOptimizedNFTDescriptor(); lockup_ = deployOptimizedLockup(initialAdmin, nftDescriptor_, maxCount); + batchLockup_ = deployOptimizedBatchLockup(); } /*////////////////////////////////////////////////////////////////////////// PERIPHERY //////////////////////////////////////////////////////////////////////////*/ - /// @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")); - } - /// @dev Deploys {SablierMerkleFactory} from an optimized source compiled with `--via-ir`. function deployOptimizedMerkleFactory(address initialAdmin) internal returns (ISablierMerkleFactory) { return ISablierMerkleFactory( @@ -79,17 +80,6 @@ abstract contract DeployOptimized is StdCheats, CommonBase { ); } - /// @notice Deploys all Periphery contracts from an optimized source in the following order: - /// - /// 1. {SablierBatchLockup} - /// 2. {SablierMerkleFactory} - function deployOptimizedPeriphery(address initialAdmin) - internal - returns (ISablierBatchLockup, ISablierMerkleFactory) - { - return (deployOptimizedBatchLockup(), deployOptimizedMerkleFactory(initialAdmin)); - } - /*////////////////////////////////////////////////////////////////////////// PROTOCOL //////////////////////////////////////////////////////////////////////////*/ @@ -112,7 +102,7 @@ abstract contract DeployOptimized is StdCheats, CommonBase { ISablierMerkleFactory merkleFactory_ ) { - (nftDescriptor_, lockup_) = deployOptimizedCore(initialAdmin, maxCount); - (batchLockup_, merkleFactory_) = deployOptimizedPeriphery(initialAdmin); + (nftDescriptor_, lockup_, batchLockup_) = deployOptimizedCore(initialAdmin, maxCount); + (merkleFactory_) = deployOptimizedMerkleFactory(initialAdmin); } } diff --git a/test/utils/Precompiles.t.sol b/test/utils/Precompiles.t.sol index f4ed7e50a..d0dd63a29 100644 --- a/test/utils/Precompiles.t.sol +++ b/test/utils/Precompiles.t.sol @@ -3,10 +3,12 @@ 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 { ISablierBatchLockup } from "src/periphery/interfaces/ISablierBatchLockup.sol"; import { ISablierMerkleFactory } from "src/periphery/interfaces/ISablierMerkleFactory.sol"; + import { Base_Test } from "./../Base.t.sol"; contract Precompiles_Test is Base_Test { @@ -24,6 +26,12 @@ contract Precompiles_Test is Base_Test { CORE //////////////////////////////////////////////////////////////////////////*/ + function test_DeployBatchLockup() external onlyTestOptimizedProfile { + address actualBatchLockup = address(precompiles.deployBatchLockup()); + address expectedBatchLockup = address(deployOptimizedBatchLockup()); + assertEq(actualBatchLockup.code, expectedBatchLockup.code, "bytecodes mismatch"); + } + function test_DeployLockup() external onlyTestOptimizedProfile { address actualLockup = address(precompiles.deployLockup(users.admin, nftDescriptor)); address expectedLockup = address(deployOptimizedLockup(users.admin, nftDescriptor, precompiles.MAX_COUNT())); @@ -38,45 +46,33 @@ contract Precompiles_Test is Base_Test { } function test_DeployCore() external onlyTestOptimizedProfile { - (ILockupNFTDescriptor actualNFTDescriptor, ISablierLockup actualLockup) = precompiles.deployCore(users.admin); + (ILockupNFTDescriptor actualNFTDescriptor, ISablierLockup actualLockup, ISablierBatchLockup actualBatchLockup) = + precompiles.deployCore(users.admin); - (ILockupNFTDescriptor expectedNFTDescriptor, ISablierLockup expectedLockup) = - deployOptimizedCore(users.admin, precompiles.MAX_COUNT()); + ( + ILockupNFTDescriptor expectedNFTDescriptor, + ISablierLockup expectedLockup, + ISablierBatchLockup expectedBatchLockup + ) = deployOptimizedCore(users.admin, precompiles.MAX_COUNT()); bytes memory expectedLockupCode = adjustBytecode(address(expectedLockup).code, address(expectedLockup), address(actualLockup)); assertEq(address(actualLockup).code, expectedLockupCode, "bytecodes mismatch"); assertEq(address(actualNFTDescriptor).code, address(expectedNFTDescriptor).code, "bytecodes mismatch"); + assertEq(address(actualBatchLockup).code, address(expectedBatchLockup).code, "bytecodes mismatch"); } /*////////////////////////////////////////////////////////////////////////// PERIPHERY //////////////////////////////////////////////////////////////////////////*/ - function test_DeployBatchLockup() external onlyTestOptimizedProfile { - address actualBatchLockup = address(precompiles.deployBatchLockup()); - address expectedBatchLockup = address(deployOptimizedBatchLockup()); - assertEq(actualBatchLockup.code, expectedBatchLockup.code, "bytecodes mismatch"); - } - 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"); } - function test_DeployPeriphery() external onlyTestOptimizedProfile { - (ISablierBatchLockup actualBatchLockup, ISablierMerkleFactory actualMerkleFactory) = - precompiles.deployPeriphery(users.admin); - - (ISablierBatchLockup expectedBatchLockup, ISablierMerkleFactory expectedMerkleFactory) = - deployOptimizedPeriphery(users.admin); - - assertEq(address(actualBatchLockup).code, address(expectedBatchLockup).code, "bytecodes mismatch"); - assertEq(address(actualMerkleFactory).code, address(expectedMerkleFactory).code, "bytecodes mismatch"); - } - /*////////////////////////////////////////////////////////////////////////// HELPERS //////////////////////////////////////////////////////////////////////////*/