Skip to content

Commit

Permalink
Inherit SablierV2Blast in Batch and Factory (#341)
Browse files Browse the repository at this point in the history
* feat: inherit SablierV2Blast in Batch and Factory contracts

* feat: update scripts with admin param

feat: configure blast settings in scripts

* test: add constructor test in batch and factory

* refactor: update precompiles

* refactor: blast related changes

---------

Co-authored-by: smol-ninja <[email protected]>
  • Loading branch information
andreivladbrg and smol-ninja committed Jul 4, 2024
1 parent 62cb598 commit 36587a2
Show file tree
Hide file tree
Showing 21 changed files with 200 additions and 49 deletions.
Binary file added bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
arbitrum = "https://arbitrum-mainnet.infura.io/v3/${API_KEY_INFURA}"
avalanche = "https://avalanche-mainnet.infura.io/v3/${API_KEY_INFURA}"
base = "https://mainnet.base.org"
blast = "https://rpc.blast.io"
blast = "${RPC_URL_BLAST}"
bnb = "https://bsc-dataseed.binance.org"
ethereum = "${RPC_URL_MAINNET}"
gnosis = "https://rpc.gnosischain.com"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@openzeppelin/contracts": "5.0.2",
"@prb/math": "4.0.3",
"@sablier/v2-core": "1.2.0"
"@sablier/v2-core": "github:sablier-labs/v2-core#blast-l2"
},
"devDependencies": {
"forge-std": "github:foundry-rs/forge-std#v1.8.2",
Expand Down Expand Up @@ -51,7 +51,7 @@
"web3"
],
"peerDependencies": {
"@sablier/v2-core": "1.2.0"
"@sablier/v2-core": "github:sablier-labs/v2-core#blast-l2"
},
"publishConfig": {
"access": "public"
Expand Down
20 changes: 10 additions & 10 deletions precompiles/Precompiles.sol

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions script/Base.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
pragma solidity >=0.8.22 <0.9.0;

import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { IBlast, YieldMode, GasMode } from "@sablier/v2-core/src/interfaces/blast/IBlast.sol";
import { IERC20Rebasing } from "@sablier/v2-core/src/interfaces/blast/IERC20Rebasing.sol";

import { console2 } from "forge-std/src/console2.sol";
import { Script } from "forge-std/src/Script.sol";
Expand All @@ -12,6 +14,13 @@ contract BaseScript is Script {
using Strings for uint256;
using stdJson for string;

/// @dev Blast mainnet configuration variables.
IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
GasMode public constant GAS_MODE = GasMode.CLAIMABLE;
YieldMode public constant YIELD_MODE = YieldMode.CLAIMABLE;
IERC20Rebasing public constant WETH = IERC20Rebasing(0x4300000000000000000000000000000000000004);
IERC20Rebasing public constant USDB = IERC20Rebasing(0x4300000000000000000000000000000000000003);

/// @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";

Expand Down
10 changes: 8 additions & 2 deletions script/DeployBatchLockup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import { SablierV2BatchLockup } from "../src/SablierV2BatchLockup.sol";

contract DeployBatchLockup is BaseScript {
/// @dev Deploy via Forge.
function run() public virtual broadcast returns (SablierV2BatchLockup batchLockup) {
batchLockup = new SablierV2BatchLockup();
function run(address admin) public virtual broadcast returns (SablierV2BatchLockup batchLockup) {
batchLockup = new SablierV2BatchLockup(msg.sender);

// Configure Blast mainnet yield and gas modes.
batchLockup.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
batchLockup.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
batchLockup.configureYieldAndGas({ blast: BLAST, yieldMode: YIELD_MODE, gasMode: GAS_MODE, governor: admin });
batchLockup.transferAdmin(admin);
}
}
10 changes: 8 additions & 2 deletions script/DeployDeterministicBatchLockup.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ import { SablierV2BatchLockup } from "../src/SablierV2BatchLockup.sol";
/// @dev Reverts if the contract has already been deployed.
contract DeployDeterministicBatchLockup is BaseScript {
/// @dev Deploy via Forge.
function run() public virtual broadcast returns (SablierV2BatchLockup batchLockup) {
function run(address admin) public virtual broadcast returns (SablierV2BatchLockup batchLockup) {
bytes32 salt = constructCreate2Salt();
batchLockup = new SablierV2BatchLockup{ salt: salt }();

// Configure Blast mainnet yield and gas modes.
batchLockup = new SablierV2BatchLockup{ salt: salt }(msg.sender);
batchLockup.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
batchLockup.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
batchLockup.configureYieldAndGas({ blast: BLAST, yieldMode: YIELD_MODE, gasMode: GAS_MODE, governor: admin });
batchLockup.transferAdmin(admin);
}
}
25 changes: 22 additions & 3 deletions script/DeployDeterministicPeriphery.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,33 @@ import { SablierV2MerkleLockupFactory } from "../src/SablierV2MerkleLockupFactor
/// @dev Reverts if any contract has already been deployed.
contract DeployDeterministicPeriphery is BaseScript {
/// @dev Deploy via Forge.
function run()
function run(address admin)
public
virtual
broadcast
returns (SablierV2BatchLockup batchLockup, SablierV2MerkleLockupFactory merkleLockupFactory)
{
bytes32 salt = constructCreate2Salt();
batchLockup = new SablierV2BatchLockup{ salt: salt }();
merkleLockupFactory = new SablierV2MerkleLockupFactory{ salt: salt }();

batchLockup = new SablierV2BatchLockup{ salt: salt }(msg.sender);

// Configure Blast mainnet yield and gas modes.
batchLockup.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
batchLockup.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
batchLockup.configureYieldAndGas({ blast: BLAST, yieldMode: YIELD_MODE, gasMode: GAS_MODE, governor: admin });
batchLockup.transferAdmin(admin);

merkleLockupFactory = new SablierV2MerkleLockupFactory{ salt: salt }(msg.sender);

// Configure Blast mainnet yield and gas modes.
merkleLockupFactory.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
merkleLockupFactory.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
merkleLockupFactory.configureYieldAndGas({
blast: BLAST,
yieldMode: YIELD_MODE,
gasMode: GAS_MODE,
governor: admin
});
merkleLockupFactory.transferAdmin(admin);
}
}
15 changes: 13 additions & 2 deletions script/DeployMerkleLockupFactory.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@ import { SablierV2MerkleLockupFactory } from "../src/SablierV2MerkleLockupFactor

contract DeployMerkleLockupFactory is BaseScript {
/// @dev Deploy via Forge.
function run() public virtual broadcast returns (SablierV2MerkleLockupFactory merkleLockupFactory) {
merkleLockupFactory = new SablierV2MerkleLockupFactory();
function run(address admin) public virtual broadcast returns (SablierV2MerkleLockupFactory merkleLockupFactory) {
merkleLockupFactory = new SablierV2MerkleLockupFactory(msg.sender);

// Configure Blast mainnet yield and gas modes.
merkleLockupFactory.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
merkleLockupFactory.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
merkleLockupFactory.configureYieldAndGas({
blast: BLAST,
yieldMode: YIELD_MODE,
gasMode: GAS_MODE,
governor: admin
});
merkleLockupFactory.transferAdmin(admin);
}
}
24 changes: 21 additions & 3 deletions script/DeployPeriphery.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,31 @@ import { SablierV2BatchLockup } from "../src/SablierV2BatchLockup.sol";
/// 2. {SablierV2MerkleLockupFactory}
contract DeployPeriphery is BaseScript {
/// @dev Deploy via Forge.
function run()
function run(address admin)
public
virtual
broadcast
returns (SablierV2BatchLockup batchLockup, SablierV2MerkleLockupFactory merkleLockupFactory)
{
batchLockup = new SablierV2BatchLockup();
merkleLockupFactory = new SablierV2MerkleLockupFactory();
batchLockup = new SablierV2BatchLockup(msg.sender);

// Configure Blast mainnet yield and gas modes.
batchLockup.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
batchLockup.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
batchLockup.configureYieldAndGas({ blast: BLAST, yieldMode: YIELD_MODE, gasMode: GAS_MODE, governor: admin });
batchLockup.transferAdmin(admin);

merkleLockupFactory = new SablierV2MerkleLockupFactory(msg.sender);

// Configure Blast mainnet yield and gas modes.
merkleLockupFactory.configureRebasingAsset({ asset: USDB, yieldMode: YIELD_MODE });
merkleLockupFactory.configureRebasingAsset({ asset: WETH, yieldMode: YIELD_MODE });
merkleLockupFactory.configureYieldAndGas({
blast: BLAST,
yieldMode: YIELD_MODE,
gasMode: GAS_MODE,
governor: admin
});
merkleLockupFactory.transferAdmin(admin);
}
}
4 changes: 2 additions & 2 deletions script/DeployProtocol.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ contract DeployProtocol is BaseScript {
lockupTranched = new SablierV2LockupTranched(initialAdmin, nftDescriptor, maxTrancheCount);

// Deploy V2 Periphery.
batchLockup = new SablierV2BatchLockup();
merkleLockupFactory = new SablierV2MerkleLockupFactory();
batchLockup = new SablierV2BatchLockup(initialAdmin);
merkleLockupFactory = new SablierV2MerkleLockupFactory(initialAdmin);
}
}
14 changes: 13 additions & 1 deletion src/SablierV2BatchLockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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 { SablierV2Blast } from "@sablier/v2-core/src/abstracts/SablierV2Blast.sol";
import { ISablierV2LockupDynamic } from "@sablier/v2-core/src/interfaces/ISablierV2LockupDynamic.sol";
import { ISablierV2LockupLinear } from "@sablier/v2-core/src/interfaces/ISablierV2LockupLinear.sol";
import { ISablierV2LockupTranched } from "@sablier/v2-core/src/interfaces/ISablierV2LockupTranched.sol";
Expand All @@ -14,9 +15,20 @@ import { BatchLockup } from "./types/DataTypes.sol";

/// @title SablierV2BatchLockup
/// @notice See the documentation in {ISablierV2BatchLockup}.
contract SablierV2BatchLockup is ISablierV2BatchLockup {
contract SablierV2BatchLockup is ISablierV2BatchLockup, SablierV2Blast {
using SafeERC20 for IERC20;

/*//////////////////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////////////////*/

/// @dev Emits a {TransferAdmin} event.
/// @param initialAdmin The address of the initial contract admin.
constructor(address initialAdmin) {
admin = initialAdmin;
emit TransferAdmin({ oldAdmin: address(0), newAdmin: initialAdmin });
}

/*//////////////////////////////////////////////////////////////////////////
SABLIER-V2-LOCKUP-DYNAMIC
//////////////////////////////////////////////////////////////////////////*/
Expand Down
14 changes: 13 additions & 1 deletion src/SablierV2MerkleLockupFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity >=0.8.22;

import { uUNIT } from "@prb/math/src/UD2x18.sol";
import { SablierV2Blast } from "@sablier/v2-core/src/abstracts/SablierV2Blast.sol";
import { ISablierV2LockupLinear } from "@sablier/v2-core/src/interfaces/ISablierV2LockupLinear.sol";
import { ISablierV2LockupTranched } from "@sablier/v2-core/src/interfaces/ISablierV2LockupTranched.sol";
import { LockupLinear } from "@sablier/v2-core/src/types/DataTypes.sol";
Expand All @@ -15,7 +16,18 @@ import { MerkleLockup, MerkleLT } from "./types/DataTypes.sol";

/// @title SablierV2MerkleLockupFactory
/// @notice See the documentation in {ISablierV2MerkleLockupFactory}.
contract SablierV2MerkleLockupFactory is ISablierV2MerkleLockupFactory {
contract SablierV2MerkleLockupFactory is ISablierV2MerkleLockupFactory, SablierV2Blast {
/*//////////////////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////////////////*/

/// @dev Emits a {TransferAdmin} event.
/// @param initialAdmin The address of the initial contract admin.
constructor(address initialAdmin) {
admin = initialAdmin;
emit TransferAdmin({ oldAdmin: address(0), newAdmin: initialAdmin });
}

/*//////////////////////////////////////////////////////////////////////////
USER-FACING CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
Expand Down
3 changes: 2 additions & 1 deletion src/interfaces/ISablierV2BatchLockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity >=0.8.22;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ISablierV2Blast } from "@sablier/v2-core/src/interfaces/blast/ISablierV2Blast.sol";
import { ISablierV2LockupDynamic } from "@sablier/v2-core/src/interfaces/ISablierV2LockupDynamic.sol";
import { ISablierV2LockupLinear } from "@sablier/v2-core/src/interfaces/ISablierV2LockupLinear.sol";
import { ISablierV2LockupTranched } from "@sablier/v2-core/src/interfaces/ISablierV2LockupTranched.sol";
Expand All @@ -10,7 +11,7 @@ import { BatchLockup } from "../types/DataTypes.sol";

/// @title ISablierV2BatchLockup
/// @notice Helper to batch create Sablier V2 Lockup streams.
interface ISablierV2BatchLockup {
interface ISablierV2BatchLockup is ISablierV2Blast {
/*//////////////////////////////////////////////////////////////////////////
SABLIER-V2-LOCKUP-LINEAR
//////////////////////////////////////////////////////////////////////////*/
Expand Down
3 changes: 2 additions & 1 deletion src/interfaces/ISablierV2MerkleLockupFactory.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.22;

import { ISablierV2Blast } from "@sablier/v2-core/src/interfaces/blast/ISablierV2Blast.sol";
import { ISablierV2LockupLinear } from "@sablier/v2-core/src/interfaces/ISablierV2LockupLinear.sol";
import { ISablierV2LockupTranched } from "@sablier/v2-core/src/interfaces/ISablierV2LockupTranched.sol";
import { LockupLinear } from "@sablier/v2-core/src/types/DataTypes.sol";
Expand All @@ -11,7 +12,7 @@ import { MerkleLockup, MerkleLT } from "../types/DataTypes.sol";

/// @title ISablierV2MerkleLockupFactory
/// @notice Deploys MerkleLockup campaigns with CREATE2.
interface ISablierV2MerkleLockupFactory {
interface ISablierV2MerkleLockupFactory is ISablierV2Blast {
/*//////////////////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////////////////*/
Expand Down
6 changes: 3 additions & 3 deletions test/Base.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ abstract contract Base_Test is
/// @dev Conditionally deploy V2 Periphery normally or from an optimized source compiled with `--via-ir`.
function deployPeripheryConditionally() internal {
if (!isTestOptimizedProfile()) {
batchLockup = new SablierV2BatchLockup();
merkleLockupFactory = new SablierV2MerkleLockupFactory();
batchLockup = new SablierV2BatchLockup(users.admin);
merkleLockupFactory = new SablierV2MerkleLockupFactory(users.admin);
} else {
(batchLockup, merkleLockupFactory) = deployOptimizedPeriphery();
(batchLockup, merkleLockupFactory) = deployOptimizedPeriphery(users.admin);
}
}

Expand Down
22 changes: 22 additions & 0 deletions test/integration/batch-lockup/constructor/constructor.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.22 <0.9.0;

import { SablierV2BatchLockup } from "src/SablierV2BatchLockup.sol";

import { Integration_Test } from "../../Integration.t.sol";

contract Constructor_BatchLockup_Integration_Test is Integration_Test {
function setUp() public virtual override {
Integration_Test.setUp();
}

function test_Constructor() external {
vm.expectEmit();
emit TransferAdmin({ oldAdmin: address(0), newAdmin: users.admin });
SablierV2BatchLockup batchLockup = new SablierV2BatchLockup(users.admin);

address actualAdmin = batchLockup.admin();
address expectedAdmin = users.admin;
assertEq(actualAdmin, expectedAdmin, "admin mismatch");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.22 <0.9.0;

import { SablierV2MerkleLockupFactory } from "src/SablierV2MerkleLockupFactory.sol";

import { MerkleLockup_Integration_Test } from "../../MerkleLockup.t.sol";

contract Constructor_BatchLockup_Integration_Test is MerkleLockup_Integration_Test {
function setUp() public virtual override {
MerkleLockup_Integration_Test.setUp();
}

function test_Constructor() external {
vm.expectEmit();
emit TransferAdmin({ oldAdmin: address(0), newAdmin: users.admin });
SablierV2MerkleLockupFactory merkleLockupFactory = new SablierV2MerkleLockupFactory(users.admin);

address actualAdmin = merkleLockupFactory.admin();
address expectedAdmin = users.admin;
assertEq(actualAdmin, expectedAdmin, "admin mismatch");
}
}
23 changes: 17 additions & 6 deletions test/utils/DeployOptimized.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,33 @@ import { ISablierV2MerkleLockupFactory } from "../../src/interfaces/ISablierV2Me

abstract contract DeployOptimized is StdCheats {
/// @dev Deploys {SablierV2BatchLockup} from an optimized source compiled with `--via-ir`.
function deployOptimizedBatchLockup() internal returns (ISablierV2BatchLockup) {
return ISablierV2BatchLockup(deployCode("out-optimized/SablierV2BatchLockup.sol/SablierV2BatchLockup.json"));
function deployOptimizedBatchLockup(address initialAdmin) internal returns (ISablierV2BatchLockup) {
return ISablierV2BatchLockup(
deployCode("out-optimized/SablierV2BatchLockup.sol/SablierV2BatchLockup.json", abi.encode(initialAdmin))
);
}

/// @dev Deploys {SablierV2MerkleLockupFactory} from an optimized source compiled with `--via-ir`.
function deployOptimizedMerkleLockupFactory() internal returns (ISablierV2MerkleLockupFactory) {
function deployOptimizedMerkleLockupFactory(address initialAdmin)
internal
returns (ISablierV2MerkleLockupFactory)
{
return ISablierV2MerkleLockupFactory(
deployCode("out-optimized/SablierV2MerkleLockupFactory.sol/SablierV2MerkleLockupFactory.json")
deployCode(
"out-optimized/SablierV2MerkleLockupFactory.sol/SablierV2MerkleLockupFactory.json",
abi.encode(initialAdmin)
)
);
}

/// @notice Deploys all V2 Periphery contracts from an optimized source in the following order:
///
/// 1. {SablierV2BatchLockup}
/// 2. {SablierV2MerkleLockupFactory}
function deployOptimizedPeriphery() internal returns (ISablierV2BatchLockup, ISablierV2MerkleLockupFactory) {
return (deployOptimizedBatchLockup(), deployOptimizedMerkleLockupFactory());
function deployOptimizedPeriphery(address initialAdmin)
internal
returns (ISablierV2BatchLockup, ISablierV2MerkleLockupFactory)
{
return (deployOptimizedBatchLockup(initialAdmin), deployOptimizedMerkleLockupFactory(initialAdmin));
}
}
1 change: 1 addition & 0 deletions test/utils/Events.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ abstract contract Events {
uint256 aggregateAmount,
uint256 recipientCount
);
event TransferAdmin(address indexed oldAdmin, address indexed newAdmin);
}
Loading

0 comments on commit 36587a2

Please sign in to comment.