Skip to content

Commit

Permalink
feat: add SablierMerkleInstant (#999)
Browse files Browse the repository at this point in the history
* feat: add SablierMerkleInstant

refactor: abstract contract SablierMerkleLockup to SablierMerkleBase
refactor: library MerkleLockup to MerkleBase
refactor: contract MerkleLockupFactory to MerkleFactory

test: add test for MerkleInstant contract
chore: add CreateMerkleInstant script
test: use super.setUp() where setUp() is redundant
test: rename merkle-lockup folder to merkle
test: rename MerkleLockup_Integration_Test contract to Merkle_Shared_Integration_Test
test: fix event assersion in merkleLL and merkleLT

refactor: rename MerkleLockup to Merkle Lockup in NatSpecs

Co-authored-by: Andrei Vlad Birgaoanu <99738872+andreivladbrg@users.noreply.github.com>

* test: include asset transfer log in merkle instant claims

* test(refactor): rename Merkle_Shared_Integration_Test back to Merkle_Integration_Test

* test: refactor merkle-lockup folder to merkle-campaign

Signed-off-by: smol-ninja <shubhamy2015@gmail.com>

* refactor: polish code for createMerkleLL and createMerkleLT scripts
refactor: rename DeployMerkleLockupFactory to DeployMerkleFactory

Co-authored-by: Andrei Vlad Birgaoanu <99738872+andreivladbrg@users.noreply.github.com>

* test(fork): remove unneeded vars

---------

Signed-off-by: smol-ninja <shubhamy2015@gmail.com>
Co-authored-by: Andrei Vlad Birgaoanu <99738872+andreivladbrg@users.noreply.github.com>
Co-authored-by: andreivladbrg <andreivladbrg@gmail.com>
  • Loading branch information
3 people authored Aug 12, 2024
1 parent ce5b2df commit 14b48a6
Show file tree
Hide file tree
Showing 88 changed files with 1,468 additions and 441 deletions.
29 changes: 12 additions & 17 deletions precompiles/Precompiles.sol

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions script/DeployDeterministicProtocol.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LockupNFTDescriptor } from "../src/core/LockupNFTDescriptor.sol";
import { SablierLockupDynamic } from "../src/core/SablierLockupDynamic.sol";
import { SablierLockupLinear } from "../src/core/SablierLockupLinear.sol";
import { SablierLockupTranched } from "../src/core/SablierLockupTranched.sol";
import { SablierMerkleLockupFactory } from "../src/periphery/SablierMerkleLockupFactory.sol";
import { SablierMerkleFactory } from "../src/periphery/SablierMerkleFactory.sol";
import { SablierBatchLockup } from "../src/periphery/SablierBatchLockup.sol";

import { BaseScript } from "./Base.s.sol";
Expand All @@ -23,7 +23,7 @@ contract DeployDeterministicProtocol is BaseScript {
SablierLockupLinear lockupLinear,
SablierLockupTranched lockupTranched,
SablierBatchLockup batchLockup,
SablierMerkleLockupFactory merkleLockupFactory
SablierMerkleFactory merkleFactory
)
{
bytes32 salt = constructCreate2Salt();
Expand All @@ -38,6 +38,6 @@ contract DeployDeterministicProtocol is BaseScript {

// Deploy Periphery.
batchLockup = new SablierBatchLockup{ salt: salt }();
merkleLockupFactory = new SablierMerkleLockupFactory{ salt: salt }();
merkleFactory = new SablierMerkleFactory{ salt: salt }();
}
}
6 changes: 3 additions & 3 deletions script/DeployProtocol.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LockupNFTDescriptor } from "../src/core/LockupNFTDescriptor.sol";
import { SablierLockupDynamic } from "../src/core/SablierLockupDynamic.sol";
import { SablierLockupLinear } from "../src/core/SablierLockupLinear.sol";
import { SablierLockupTranched } from "../src/core/SablierLockupTranched.sol";
import { SablierMerkleLockupFactory } from "../src/periphery/SablierMerkleLockupFactory.sol";
import { SablierMerkleFactory } from "../src/periphery/SablierMerkleFactory.sol";
import { SablierBatchLockup } from "../src/periphery/SablierBatchLockup.sol";

import { BaseScript } from "./Base.s.sol";
Expand All @@ -23,7 +23,7 @@ contract DeployProtocol is BaseScript {
SablierLockupLinear lockupLinear,
SablierLockupTranched lockupTranched,
SablierBatchLockup batchLockup,
SablierMerkleLockupFactory merkleLockupFactory
SablierMerkleFactory merkleFactory
)
{
// Deploy Core.
Expand All @@ -34,6 +34,6 @@ contract DeployProtocol is BaseScript {

// Deploy Periphery.
batchLockup = new SablierBatchLockup();
merkleLockupFactory = new SablierMerkleLockupFactory();
merkleFactory = new SablierMerkleFactory();
}
}
33 changes: 33 additions & 0 deletions script/periphery/CreateMerkleInstant.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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);
}
}
33 changes: 15 additions & 18 deletions script/periphery/CreateMerkleLL.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,37 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import { ISablierLockupLinear } from "../../src/core/interfaces/ISablierLockupLinear.sol";
import { LockupLinear } from "../../src/core/types/DataTypes.sol";
import { ISablierMerkleFactory } from "../../src/periphery/interfaces/ISablierMerkleFactory.sol";
import { ISablierMerkleLL } from "../../src/periphery/interfaces/ISablierMerkleLL.sol";
import { ISablierMerkleLockupFactory } from "../../src/periphery/interfaces/ISablierMerkleLockupFactory.sol";
import { MerkleLockup } from "../../src/periphery/types/DataTypes.sol";
import { MerkleBase } 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.
ISablierMerkleLockupFactory merkleLockupFactory =
ISablierMerkleLockupFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc); // TODO: Update address once deployed.
// TODO: Update address once deployed.
ISablierMerkleFactory merkleFactory = ISablierMerkleFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc);

MerkleLockup.ConstructorParams memory baseParams;
MerkleBase.ConstructorParams memory baseParams;
baseParams.asset = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
baseParams.cancelable = true;
baseParams.expiration = uint40(block.timestamp + 30 days);
baseParams.initialAdmin = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844;
baseParams.ipfsCID = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR";
baseParams.merkleRoot = 0x0000000000000000000000000000000000000000000000000000000000000000;
baseParams.name = "The Boys LL";
baseParams.transferable = true;

// TODO: Update address once deployed.
ISablierLockupLinear lockupLinear = ISablierLockupLinear(0x3962f6585946823440d274aD7C719B02b49DE51E);
LockupLinear.Durations memory streamDurations;
streamDurations.cliff = 0;
streamDurations.total = 3600;
uint256 campaignTotalAmount = 10_000e18;
uint256 recipientCount = 100;

// Deploy MerkleLL contract.
merkleLL = merkleLockupFactory.createMerkleLL(
baseParams, lockupLinear, streamDurations, campaignTotalAmount, recipientCount
);
// TODO: Update address once deployed.
merkleLL = merkleFactory.createMerkleLL({
baseParams: baseParams,
lockupLinear: ISablierLockupLinear(0x3962f6585946823440d274aD7C719B02b49DE51E),
cancelable: true,
transferable: true,
streamDurations: LockupLinear.Durations({ cliff: 0, total: 3600 }),
aggregateAmount: 10_000e18,
recipientCount: 100
});
}
}
29 changes: 15 additions & 14 deletions script/periphery/CreateMerkleLT.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,43 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { UD2x18 } from "@prb/math/src/UD2x18.sol";

import { ISablierLockupTranched } from "../../src/core/interfaces/ISablierLockupTranched.sol";
import { ISablierMerkleLockupFactory } from "../../src/periphery/interfaces/ISablierMerkleLockupFactory.sol";
import { ISablierMerkleFactory } from "../../src/periphery/interfaces/ISablierMerkleFactory.sol";
import { ISablierMerkleLT } from "../../src/periphery/interfaces/ISablierMerkleLT.sol";
import { MerkleLockup, MerkleLT } from "../../src/periphery/types/DataTypes.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.
ISablierMerkleLockupFactory merkleLockupFactory =
ISablierMerkleLockupFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc); // TODO: Update address once deployed.
// TODO: Update address once deployed.
ISablierMerkleFactory merkleFactory = ISablierMerkleFactory(0xF35aB407CF28012Ba57CAF5ee2f6d6E4420253bc);

MerkleLockup.ConstructorParams memory baseParams;
MerkleBase.ConstructorParams memory baseParams;
baseParams.asset = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
baseParams.cancelable = true;
baseParams.expiration = uint40(block.timestamp + 30 days);
baseParams.initialAdmin = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844;
baseParams.ipfsCID = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR";
baseParams.merkleRoot = 0x0000000000000000000000000000000000000000000000000000000000000000;
baseParams.name = "The Boys LT";
baseParams.transferable = true;

// TODO: Update address once deployed.
ISablierLockupTranched lockupTranched = ISablierLockupTranched(0xf86B359035208e4529686A1825F2D5BeE38c28A8);
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 });
uint256 campaignTotalAmount = 10_000e18;
uint256 recipientCount = 100;

// Deploy MerkleLT contract.
merkleLT = merkleLockupFactory.createMerkleLT(
baseParams, lockupTranched, tranchesWithPercentages, campaignTotalAmount, recipientCount
);
// TODO: Update address once deployed.
merkleLT = merkleFactory.createMerkleLT({
baseParams: baseParams,
lockupTranched: ISablierLockupTranched(0xf86B359035208e4529686A1825F2D5BeE38c28A8),
cancelable: true,
transferable: true,
tranchesWithPercentages: tranchesWithPercentages,
aggregateAmount: 10_000e18,
recipientCount: 100
});
}
}
8 changes: 4 additions & 4 deletions script/periphery/DeployDeterministicPeriphery.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
pragma solidity >=0.8.22 <0.9.0;

import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol";
import { SablierMerkleLockupFactory } from "../../src/periphery/SablierMerkleLockupFactory.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. {SablierMerkleLockupFactory}
/// 2. {SablierMerkleFactory}
///
/// @dev Reverts if any contract has already been deployed.
contract DeployDeterministicPeriphery is BaseScript {
Expand All @@ -18,10 +18,10 @@ contract DeployDeterministicPeriphery is BaseScript {
public
virtual
broadcast
returns (SablierBatchLockup batchLockup, SablierMerkleLockupFactory merkleLockupFactory)
returns (SablierBatchLockup batchLockup, SablierMerkleFactory merkleFactory)
{
bytes32 salt = constructCreate2Salt();
batchLockup = new SablierBatchLockup{ salt: salt }();
merkleLockupFactory = new SablierMerkleLockupFactory{ salt: salt }();
merkleFactory = new SablierMerkleFactory{ salt: salt }();
}
}
13 changes: 13 additions & 0 deletions script/periphery/DeployMerkleFactory.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// 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() public virtual broadcast returns (SablierMerkleFactory merkleFactory) {
merkleFactory = new SablierMerkleFactory();
}
}
13 changes: 0 additions & 13 deletions script/periphery/DeployMerkleLockupFactory.s.sol

This file was deleted.

8 changes: 4 additions & 4 deletions script/periphery/DeployPeriphery.s.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.22 <0.9.0;

import { SablierMerkleLockupFactory } from "../../src/periphery/SablierMerkleLockupFactory.sol";
import { SablierMerkleFactory } from "../../src/periphery/SablierMerkleFactory.sol";
import { SablierBatchLockup } from "../../src/periphery/SablierBatchLockup.sol";

import { BaseScript } from "../Base.s.sol";

/// @notice Deploys all Periphery contract in the following order:
///
/// 1. {SablierBatchLockup}
/// 2. {SablierMerkleLockupFactory}
/// 2. {SablierMerkleFactory}
contract DeployPeriphery is BaseScript {
/// @dev Deploy via Forge.
function run()
public
virtual
broadcast
returns (SablierBatchLockup batchLockup, SablierMerkleLockupFactory merkleLockupFactory)
returns (SablierBatchLockup batchLockup, SablierMerkleFactory merkleFactory)
{
batchLockup = new SablierBatchLockup();
merkleLockupFactory = new SablierMerkleLockupFactory();
merkleFactory = new SablierMerkleFactory();
}
}
4 changes: 2 additions & 2 deletions shell/deploy-multi-chain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ for chain in "${provided_chains[@]}"; do
lockupDynamic_address=$(echo "${output}" | awk '/lockupDynamic: contract/{print $NF}')
lockupLinear_address=$(echo "${output}" | awk '/lockupLinear: contract/{print $NF}')
lockupTranched_address=$(echo "${output}" | awk '/lockupTranched: contract/{print $NF}')
merkleLockupFactory_address=$(echo "${output}" | awk '/merkleLockupFactory: contract/{print $NF}')
merkleFactory_address=$(echo "${output}" | awk '/merkleFactory: contract/{print $NF}')
nftDescriptor_address=$(echo "${output}" | awk '/nftDescriptor: contract/{print $NF}')

# Save to the chain file
Expand All @@ -372,7 +372,7 @@ for chain in "${provided_chains[@]}"; do
echo "SablierLockupTranched = ${lockupTranched_address}"
echo "Periphery Contracts"
echo "SablierBatchLockup = ${batchLockup_address}"
echo "SablierMerkleLockupFactory = ${merkleLockupFactory_address}"
echo "SablierMerkleFactory = ${merkleFactory_address}"
} >> "$chain_file"

echo -e "${SC}${TICK} Deployed on ${chain}. You can find the addresses in ${chain_file}${NC}"
Expand Down
6 changes: 4 additions & 2 deletions shell/prepare-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ cp out-optimized/Errors.sol/Errors.json $core_libraries

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/SablierMerkleLockupFactory.sol/SablierMerkleLockupFactory.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/ISablierMerkleLockupFactory.sol/ISablierMerkleLockupFactory.json $periphery_interfaces
cp out-optimized/ISablierMerkleLT.sol/ISablierMerkleLT.json $periphery_interfaces

periphery_libraries=./artifacts/periphery/libraries
Expand Down
4 changes: 2 additions & 2 deletions shell/update-precompiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ batch_lockup=$(cat out-optimized/SablierBatchLockup.sol/SablierBatchLockup.json
lockup_dynamic=$(cat out-optimized/SablierLockupDynamic.sol/SablierLockupDynamic.json | jq -r '.bytecode.object' | cut -c 3-)
lockup_linear=$(cat out-optimized/SablierLockupLinear.sol/SablierLockupLinear.json | jq -r '.bytecode.object' | cut -c 3-)
lockup_tranched=$(cat out-optimized/SablierLockupTranched.sol/SablierLockupTranched.json | jq -r '.bytecode.object' | cut -c 3-)
merkle_lockup_factory=$(cat out-optimized/SablierMerkleLockupFactory.sol/SablierMerkleLockupFactory.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"
Expand All @@ -30,7 +30,7 @@ sd "(BYTECODE_BATCH_LOCKUP =)[^;]+;" "\$1 hex\"$batch_lockup\";" $precompiles_pa
sd "(BYTECODE_LOCKUP_DYNAMIC =)[^;]+;" "\$1 hex\"$lockup_dynamic\";" $precompiles_path
sd "(BYTECODE_LOCKUP_LINEAR =)[^;]+;" "\$1 hex\"$lockup_linear\";" $precompiles_path
sd "(BYTECODE_LOCKUP_TRANCHED =)[^;]+;" "\$1 hex\"$lockup_tranched\";" $precompiles_path
sd "(BYTECODE_MERKLE_LOCKUP_FACTORY =)[^;]+;" "\$1 hex\"$merkle_lockup_factory\";" $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
Expand Down
Loading

0 comments on commit 14b48a6

Please sign in to comment.