Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LockupTranched contract #817

Merged
merged 3 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ contract MyContract {

## Architecture

V2 Core uses a singleton-style architecture, where all streams are managed in the `LockupLinear` and `LockupDynamic`
contracts. That is, Sablier does not deploy a new contract for each stream. It bundles all streams into a single
contract, which is more gas-efficient and easier to maintain.
V2 Core uses a singleton-style architecture, where all streams are managed in the `LockupLinear`, `LockupDynamic` and
`LockupTranched` contracts. That is, Sablier does not deploy a new contract for each stream. It bundles all streams into
a single contract, which is more gas-efficient and easier to maintain.

For more information, see the [Technical Overview](https://docs.sablier.com/contracts/v2/reference/overview) in our
docs, as well as these [diagrams](https://docs.sablier.com/contracts/v2/reference/diagrams).
Expand Down
2 changes: 2 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"SablierV2Comptroller",
"SablierV2LockupDynamic",
"SablierV2LockupLinear",
"SablierV2LockupTranched",
"SablierV2NFTDescriptor",
]
optimizer = true
Expand Down Expand Up @@ -68,6 +69,7 @@
[profile.smt.model_checker.contracts]
"src/SablierV2LockupDynamic.sol" = ["SablierV2LockupDynamic"]
"src/SablierV2LockupLinear.sol" = ["SablierV2LockupLinear"]
"src/SablierV2LockupTranched.sol" = ["SablierV2LockupTranched"]
"src/SablierV2NFTDescriptor.sol" = ["SablierV2NFTDescriptor"]

# Test the optimized contracts without re-compiling them
Expand Down
4 changes: 4 additions & 0 deletions script/DeployCore.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity >=0.8.22 <0.9.0;
import { SablierV2Comptroller } from "../src/SablierV2Comptroller.sol";
import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol";
import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";
import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol";

import { BaseScript } from "./Base.s.sol";
Expand All @@ -14,6 +15,7 @@ import { BaseScript } from "./Base.s.sol";
/// 2. {SablierV2NFTDescriptor}
/// 3. {SablierV2LockupDynamic}
/// 4. {SablierV2LockupLinear}
/// 5. {SablierV2LockupTranched}
contract DeployCore is BaseScript {
function run(address initialAdmin)
public
Expand All @@ -23,12 +25,14 @@ contract DeployCore is BaseScript {
SablierV2Comptroller comptroller,
SablierV2LockupDynamic lockupDynamic,
SablierV2LockupLinear lockupLinear,
SablierV2LockupTranched lockupTranched,
SablierV2NFTDescriptor nftDescriptor
)
{
comptroller = new SablierV2Comptroller(initialAdmin);
nftDescriptor = new SablierV2NFTDescriptor();
lockupDynamic = new SablierV2LockupDynamic(initialAdmin, comptroller, nftDescriptor, maxCount);
lockupLinear = new SablierV2LockupLinear(initialAdmin, comptroller, nftDescriptor);
lockupTranched = new SablierV2LockupTranched(initialAdmin, comptroller, nftDescriptor, maxCount);
}
}
6 changes: 5 additions & 1 deletion script/DeployCore2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ISablierV2NFTDescriptor } from "../src/interfaces/ISablierV2NFTDescript
import { SablierV2Comptroller } from "../src/SablierV2Comptroller.sol";
import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol";
import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";

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

Expand All @@ -13,6 +14,7 @@ import { BaseScript } from "./Base.s.sol";
/// 1. {SablierV2Comptroller}
/// 2. {SablierV2LockupDynamic}
/// 3. {SablierV2LockupLinear}
/// 4. {SablierV2LockupTranched}
contract DeployCore2 is BaseScript {
function run(
address initialAdmin,
Expand All @@ -24,11 +26,13 @@ contract DeployCore2 is BaseScript {
returns (
SablierV2Comptroller comptroller,
SablierV2LockupDynamic lockupDynamic,
SablierV2LockupLinear lockupLinear
SablierV2LockupLinear lockupLinear,
SablierV2LockupTranched lockupTranched
)
{
comptroller = new SablierV2Comptroller(initialAdmin);
lockupDynamic = new SablierV2LockupDynamic(initialAdmin, comptroller, nftDescriptor, maxCount);
lockupLinear = new SablierV2LockupLinear(initialAdmin, comptroller, nftDescriptor);
lockupTranched = new SablierV2LockupTranched(initialAdmin, comptroller, nftDescriptor, maxCount);
}
}
8 changes: 6 additions & 2 deletions script/DeployCore3.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
pragma solidity >=0.8.22 <0.9.0;

import { ISablierV2Comptroller } from "../src/interfaces/ISablierV2Comptroller.sol";
import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol";
import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol";
import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";
import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol";

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

Expand All @@ -13,6 +14,7 @@ import { BaseScript } from "./Base.s.sol";
/// 1. {SablierV2NFTDescriptor}
/// 2. {SablierV2LockupDynamic}
/// 3. {SablierV2LockupLinear}
/// 4. {SablierV2LockupTranched}
contract DeployCore3 is BaseScript {
function run(
address initialAdmin,
Expand All @@ -24,11 +26,13 @@ contract DeployCore3 is BaseScript {
returns (
SablierV2NFTDescriptor nftDescriptor,
SablierV2LockupDynamic lockupDynamic,
SablierV2LockupLinear lockupLinear
SablierV2LockupLinear lockupLinear,
SablierV2LockupTranched lockupTranched
)
{
nftDescriptor = new SablierV2NFTDescriptor();
lockupDynamic = new SablierV2LockupDynamic(initialAdmin, comptroller, nftDescriptor, maxCount);
lockupLinear = new SablierV2LockupLinear(initialAdmin, comptroller, nftDescriptor);
lockupTranched = new SablierV2LockupTranched(initialAdmin, comptroller, nftDescriptor, maxCount);
}
}
4 changes: 4 additions & 0 deletions script/DeployDeterministicCore.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity >=0.8.22 <0.9.0;
import { SablierV2Comptroller } from "../src/SablierV2Comptroller.sol";
import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol";
import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";
import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol";

import { BaseScript } from "./Base.s.sol";
Expand All @@ -14,6 +15,7 @@ import { BaseScript } from "./Base.s.sol";
/// 2. {SablierV2NFTDescriptor}
/// 3. {SablierV2LockupDynamic}
/// 4. {SablierV2LockupLinear}
/// 5. {SablierV2LockupTranched}
///
/// @dev Reverts if any contract has already been deployed.
contract DeployDeterministicCore is BaseScript {
Expand All @@ -25,6 +27,7 @@ contract DeployDeterministicCore is BaseScript {
SablierV2Comptroller comptroller,
SablierV2LockupDynamic lockupDynamic,
SablierV2LockupLinear lockupLinear,
SablierV2LockupTranched lockupTranched,
SablierV2NFTDescriptor nftDescriptor
)
{
Expand All @@ -33,5 +36,6 @@ contract DeployDeterministicCore is BaseScript {
nftDescriptor = new SablierV2NFTDescriptor{ salt: salt }();
lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxCount);
lockupLinear = new SablierV2LockupLinear{ salt: salt }(initialAdmin, comptroller, nftDescriptor);
lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxCount);
}
}
6 changes: 5 additions & 1 deletion script/DeployDeterministicCore2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ISablierV2NFTDescriptor } from "../src/interfaces/ISablierV2NFTDescript
import { SablierV2Comptroller } from "../src/SablierV2Comptroller.sol";
import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol";
import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";

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

Expand All @@ -13,6 +14,7 @@ import { BaseScript } from "./Base.s.sol";
/// 1. {SablierV2Comptroller}
/// 2. {SablierV2LockupDynamic}
/// 3. {SablierV2LockupLinear}
/// 4. {SablierV2LockupTranched}
///
/// @dev Reverts if any contract has already been deployed.
contract DeployDeterministicCore2 is BaseScript {
Expand All @@ -26,12 +28,14 @@ contract DeployDeterministicCore2 is BaseScript {
returns (
SablierV2Comptroller comptroller,
SablierV2LockupDynamic lockupDynamic,
SablierV2LockupLinear lockupLinear
SablierV2LockupLinear lockupLinear,
SablierV2LockupTranched lockupTranched
)
{
bytes32 salt = constructCreate2Salt();
comptroller = new SablierV2Comptroller{ salt: salt }(initialAdmin);
lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxCount);
lockupLinear = new SablierV2LockupLinear{ salt: salt }(initialAdmin, comptroller, nftDescriptor);
lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxCount);
}
}
8 changes: 6 additions & 2 deletions script/DeployDeterministicCore3.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
pragma solidity >=0.8.22 <0.9.0;

import { ISablierV2Comptroller } from "../src/interfaces/ISablierV2Comptroller.sol";
import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol";
import { SablierV2LockupDynamic } from "../src/SablierV2LockupDynamic.sol";
import { SablierV2LockupLinear } from "../src/SablierV2LockupLinear.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";
import { SablierV2NFTDescriptor } from "../src/SablierV2NFTDescriptor.sol";

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

Expand All @@ -13,6 +14,7 @@ import { BaseScript } from "./Base.s.sol";
/// 1. {SablierV2NFTDescriptor}
/// 2. {SablierV2LockupDynamic}
/// 3. {SablierV2LockupLinear}
/// 4. {SablierV2LockupTranched}
///
/// @dev Reverts if any contract has already been deployed.
contract DeployDeterministicCore3 is BaseScript {
Expand All @@ -26,12 +28,14 @@ contract DeployDeterministicCore3 is BaseScript {
returns (
SablierV2NFTDescriptor nftDescriptor,
SablierV2LockupDynamic lockupDynamic,
SablierV2LockupLinear lockupLinear
SablierV2LockupLinear lockupLinear,
SablierV2LockupTranched lockupTranched
)
{
bytes32 salt = constructCreate2Salt();
nftDescriptor = new SablierV2NFTDescriptor{ salt: salt }();
lockupDynamic = new SablierV2LockupDynamic{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxCount);
lockupLinear = new SablierV2LockupLinear{ salt: salt }(initialAdmin, comptroller, nftDescriptor);
lockupTranched = new SablierV2LockupTranched{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxCount);
}
}
27 changes: 27 additions & 0 deletions script/DeployDeterministicLockupTranched.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.22 <0.9.0;

import { ISablierV2Comptroller } from "../src/interfaces/ISablierV2Comptroller.sol";
import { ISablierV2NFTDescriptor } from "../src/interfaces/ISablierV2NFTDescriptor.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";

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

/// @dev Deploys {SablierV2LockupTranched} at a deterministic address across chains.
/// @dev Reverts if the contract has already been deployed.
contract DeployDeterministicLockupTranched is BaseScript {
function run(
address initialAdmin,
ISablierV2Comptroller initialComptroller,
ISablierV2NFTDescriptor initialNFTDescriptor
)
public
virtual
broadcast
returns (SablierV2LockupTranched lockupTranched)
{
bytes32 salt = constructCreate2Salt();
lockupTranched =
new SablierV2LockupTranched{ salt: salt }(initialAdmin, initialComptroller, initialNFTDescriptor, maxCount);
}
}
23 changes: 23 additions & 0 deletions script/DeployLockupTranched.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.22 <0.9.0;

import { ISablierV2Comptroller } from "../src/interfaces/ISablierV2Comptroller.sol";
import { ISablierV2NFTDescriptor } from "../src/interfaces/ISablierV2NFTDescriptor.sol";
import { SablierV2LockupTranched } from "../src/SablierV2LockupTranched.sol";

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

contract DeployLockupTranched is BaseScript {
function run(
address initialAdmin,
ISablierV2Comptroller initialComptroller,
ISablierV2NFTDescriptor initialNFTDescriptor
)
public
virtual
broadcast
returns (SablierV2LockupTranched lockupTranched)
{
lockupTranched = new SablierV2LockupTranched(initialAdmin, initialComptroller, initialNFTDescriptor, maxCount);
}
}
20 changes: 11 additions & 9 deletions shell/deploy-multi-chain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ else
# load values from the terminal prompt
echo -e "${WC}Missing '.env.deployment'. Provide details below: ${NC}\n"

# initialize chains with chain id and comptroller
# initialize chains with comptroller
initialize_interactive

fi
Expand Down Expand Up @@ -199,10 +199,10 @@ for ((i=1; i<=$#; i++)); do
# Sort the names
sorted_names=($(printf "%s\n" "${names[@]}" | sort))
# Print the header
printf "\nSupported chains: \n%-20s %-20s\n" "Chain Name" "Chain ID"
printf "%-20s %-20s\n" "-----------" "-----------"
printf "\nSupported chains: \n%-20s %-20s\n" "Chain Name"
printf "%-20s %-20s\n" "-----------"

# Print the chains and their Chain IDs
# Print the supported chains
for chain in "${sorted_names[@]}"; do
IFS=' ' read -r rpc_url api_key admin comptroller <<< "${chains[$chain]}"

Expand All @@ -217,7 +217,7 @@ for ((i=1; i<=$#; i++)); do
INTERACTIVE=true
echo -e "Interactive mode activated. Provide details below: \n"

# initialize only chain id and comptroller
# initialize only comptroller
initialize_interactive
fi

Expand Down Expand Up @@ -330,9 +330,9 @@ for chain in "${provided_chains[@]}"; do
# echo removes single quotes
####################################################################
if [[ ${READ_ONLY} == true ]]; then
deployment_command+=("--sig" "'run(address,address,uint256)'")
deployment_command+=("--sig" "'run(address,address)'")
else
deployment_command+=("--sig" "run(address,address,uint256)")
deployment_command+=("--sig" "run(address,address)")
fi
else
# Construct the command
Expand All @@ -344,9 +344,9 @@ for chain in "${provided_chains[@]}"; do
deployment_command+=("--rpc-url" "${rpc_url}")

if [[ ${READ_ONLY} == true ]]; then
deployment_command+=("--sig" "'run(address,address,uint256)'")
deployment_command+=("--sig" "'run(address,address)'")
else
deployment_command+=("--sig" "run(address,address,uint256)")
deployment_command+=("--sig" "run(address,address)")
fi
fi

Expand Down Expand Up @@ -389,12 +389,14 @@ for chain in "${provided_chains[@]}"; do
# Extract and save contract addresses
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}')
nftDescriptor_address=$(echo "${output}" | awk '/nftDescriptor: contract/{print $NF}')

# Save to the chain file
{
echo "SablierV2LockupDynamic = ${lockupDynamic_address}"
echo "SablierV2LockupLinear = ${lockupLinear_address}"
echo "SablierV2LockupTranched = ${lockupTranched_address}"
echo "SablierV2NFTDescriptor = ${nftDescriptor_address}"
} >> "$chain_file"

Expand Down
2 changes: 2 additions & 0 deletions shell/prepare-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ FOUNDRY_PROFILE=optimized forge build
cp out-optimized/SablierV2Comptroller.sol/SablierV2Comptroller.json $artifacts
cp out-optimized/SablierV2LockupDynamic.sol/SablierV2LockupDynamic.json $artifacts
cp out-optimized/SablierV2LockupLinear.sol/SablierV2LockupLinear.json $artifacts
cp out-optimized/SablierV2LockupTranched.sol/SablierV2LockupTranched.json $artifacts
cp out-optimized/SablierV2NFTDescriptor.sol/SablierV2NFTDescriptor.json $artifacts

interfaces=./artifacts/interfaces
Expand All @@ -34,6 +35,7 @@ cp out-optimized/ISablierV2Comptroller.sol/ISablierV2Comptroller.json $interface
cp out-optimized/ISablierV2Lockup.sol/ISablierV2Lockup.json $interfaces
cp out-optimized/ISablierV2LockupDynamic.sol/ISablierV2LockupDynamic.json $interfaces
cp out-optimized/ISablierV2LockupLinear.sol/ISablierV2LockupLinear.json $interfaces
cp out-optimized/ISablierV2LockupTranched.sol/ISablierV2LockupTranched.json $interfaces
cp out-optimized/ISablierV2NFTDescriptor.sol/ISablierV2NFTDescriptor.json $interfaces

erc20=./artifacts/interfaces/erc20
Expand Down
2 changes: 2 additions & 0 deletions shell/update-precompiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ FOUNDRY_PROFILE=optimized forge build
comptroller=$(cat out-optimized/SablierV2Comptroller.sol/SablierV2Comptroller.json | jq -r '.bytecode.object' | cut -c 3-)
lockup_dynamic=$(cat out-optimized/SablierV2LockupDynamic.sol/SablierV2LockupDynamic.json | jq -r '.bytecode.object' | cut -c 3-)
lockup_linear=$(cat out-optimized/SablierV2LockupLinear.sol/SablierV2LockupLinear.json | jq -r '.bytecode.object' | cut -c 3-)
lockup_tranched=$(cat out-optimized/SablierV2LockupTranched.sol/SablierV2LockupTranched.json | jq -r '.bytecode.object' | cut -c 3-)
nft_descriptor=$(cat out-optimized/SablierV2NFTDescriptor.sol/SablierV2NFTDescriptor.json | jq -r '.bytecode.object' | cut -c 3-)

precompiles_path="test/utils/Precompiles.sol"
Expand All @@ -27,6 +28,7 @@ fi
sd "(BYTECODE_COMPTROLLER =)[^;]+;" "\$1 hex\"$comptroller\";" $precompiles_path
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_NFT_DESCRIPTOR =)[^;]+;" "\$1 hex\"$nft_descriptor\";" $precompiles_path

# Reformat the code with Forge
Expand Down
1 change: 1 addition & 0 deletions src/SablierV2LockupDynamic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ contract SablierV2LockupDynamic is
notNull(streamId)
returns (LockupDynamic.StreamLD memory stream)
{
// Retrieve the lockup stream from storage.
Lockup.Stream memory lockupStream = _streams[streamId];

// Settled streams cannot be canceled.
Expand Down
1 change: 1 addition & 0 deletions src/SablierV2LockupLinear.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ contract SablierV2LockupLinear is
notNull(streamId)
returns (LockupLinear.StreamLL memory stream)
{
// Retrieve the lockup stream from storage.
Lockup.Stream memory lockupStream = _streams[streamId];

// Settled streams cannot be canceled.
Expand Down
Loading
Loading