-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add a deployment bash script for multiple chains
feat: add deploy protocol 2 scripts build: remove etherscan api keys from foundry.toml build: improve .env.example chore: git ignore deployments
- Loading branch information
1 parent
93edc66
commit 6a3ca31
Showing
6 changed files
with
324 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,39 @@ | ||
export API_KEY_ARBISCAN="YOUR_API_KEY_ARBISCAN" | ||
export API_KEY_BSCSCAN="YOUR_API_KEY_BSCSCAN" | ||
export API_KEY_ETHERSCAN="YOUR_API_KEY_ETHERSCAN" | ||
export API_KEY_GNOSISSCAN="YOUR_API_KEY_GNOSISSCAN" | ||
export API_KEY_INFURA="YOUR_API_KEY_INFURA" | ||
export API_KEY_OPTIMISTIC_ETHERSCAN="YOUR_API_KEY_OPTIMISTIC_ETHERSCAN" | ||
export API_KEY_POLYGONSCAN="YOUR_API_KEY_POLYGONSCAN" | ||
export API_KEY_SNOWTRACE="YOUR_API_KEY_SNOWTRACE" | ||
# Run `cp .env.example .env` command to create your .env file | ||
|
||
# General | ||
export API_KEY_INFURA="YOUR_INFURA_KEY" | ||
export FOUNDRY_PROFILE="lite" | ||
export MNEMONIC="YOUR_MNEMONIC" | ||
export RPC_URL_GOERLI="YOUR_RPC_URL_GOERLI" | ||
export RPC_URL_MAINNET="YOUR_RPC_URL_MAINNET" | ||
|
||
# RPC URLs | ||
export ARBITRUM_RPC_URL="YOUR_RPC_URL" | ||
export AVALANCHE_RPC_URL="YOUR_RPC_URL" | ||
export BASE_RPC_URL="YOUR_RPC_URL" | ||
export BINANCE_RPC_URL="YOUR_RPC_URL" | ||
export GNOSIS_RPC_URL="YOUR_RPC_URL" | ||
export MAINNET_RPC_URL="YOUR_RPC_URL" | ||
export OPTIMISM_RPC_URL="YOUR_RPC_URL" | ||
export POLYGON_RPC_URL="YOUR_RPC_URL" | ||
export SCROLL_RPC_URL="YOUR_RPC_URL" | ||
|
||
# Etherscan API keys | ||
export ARBISCAN_API_KEY="YOUR_API_KEY" | ||
export BASESCAN_API_KEY="YOUR_API_KEY" | ||
export BSCSCAN_API_KEY="YOUR_API_KEY" | ||
export ETHERSCAN_API_KEY="YOUR_API_KEY" | ||
export GNOSISSCAN_API_KEY="YOUR_API_KEY" | ||
export OPTIMISTIC_API_KEY="YOUR_API_KEY" | ||
export POLYGONSCAN_API_KEY="YOUR_API_KEY" | ||
export SCROLL_API_KEY="YOUR_API_KEY" | ||
export SNOWTRACE_API_KEY="YOUR_API_KEY" | ||
|
||
# Script variables | ||
export ARBITRUM_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export AVALANCHE_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export BASE_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export BSC_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export GNOSIS_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export MAINNET_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export OPTIMISM_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export POLYGON_ADMIN="YOUR_ADMIN_ADDRESS" | ||
export SCROLL_ADMIN="YOUR_ADMIN_ADDRESS" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ artifacts | |
broadcast | ||
cache | ||
coverage | ||
deployments | ||
docs | ||
node_modules | ||
out-optimized | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity >=0.8.19 <0.9.0; | ||
|
||
import { SablierV2Comptroller } from "@sablier/v2-core/src/SablierV2Comptroller.sol"; | ||
import { SablierV2LockupDynamic } from "@sablier/v2-core/src/SablierV2LockupDynamic.sol"; | ||
import { SablierV2LockupLinear } from "@sablier/v2-core/src/SablierV2LockupLinear.sol"; | ||
import { SablierV2NFTDescriptor } from "@sablier/v2-core/src/SablierV2NFTDescriptor.sol"; | ||
|
||
import { BaseScript } from "./Base.s.sol"; | ||
|
||
import { SablierV2Batch } from "../src/SablierV2Batch.sol"; | ||
import { SablierV2MerkleStreamerFactory } from "../src/SablierV2MerkleStreamerFactory.sol"; | ||
|
||
/// @notice Deploys the Sablier V2 Protocol deterministically expect for comptroller. | ||
contract DeployDeterministicPeriphery is BaseScript { | ||
/// @dev The presence of the salt instructs Forge to deploy the contract via a deterministic CREATE2 factory. | ||
/// https://github.com/Arachnid/deterministic-deployment-proxy | ||
function run( | ||
string memory create2Salt, | ||
address initialAdmin, | ||
SablierV2Comptroller comptroller | ||
) | ||
public | ||
virtual | ||
broadcast | ||
returns ( | ||
SablierV2LockupDynamic lockupDynamic, | ||
SablierV2LockupLinear lockupLinear, | ||
SablierV2NFTDescriptor nftDescriptor, | ||
SablierV2Batch batch, | ||
SablierV2MerkleStreamerFactory merkleStreamerFactory | ||
) | ||
{ | ||
bytes32 salt = bytes32(abi.encodePacked(create2Salt)); | ||
|
||
nftDescriptor = new SablierV2NFTDescriptor{ salt: salt }(); | ||
lockupLinear = new SablierV2LockupLinear{ salt: salt }(initialAdmin, comptroller, nftDescriptor); | ||
|
||
uint256 maxSegmentCount = 300; | ||
|
||
lockupDynamic = | ||
new SablierV2LockupDynamic{ salt: salt }(initialAdmin, comptroller, nftDescriptor, maxSegmentCount); | ||
|
||
batch = new SablierV2Batch{ salt: salt }(); | ||
merkleStreamerFactory = new SablierV2MerkleStreamerFactory{ salt: salt }(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity >=0.8.19 <0.9.0; | ||
|
||
import { SablierV2Comptroller } from "@sablier/v2-core/src/SablierV2Comptroller.sol"; | ||
import { SablierV2LockupDynamic } from "@sablier/v2-core/src/SablierV2LockupDynamic.sol"; | ||
import { SablierV2LockupLinear } from "@sablier/v2-core/src/SablierV2LockupLinear.sol"; | ||
import { SablierV2NFTDescriptor } from "@sablier/v2-core/src/SablierV2NFTDescriptor.sol"; | ||
import { BaseScript } from "./Base.s.sol"; | ||
|
||
import { SablierV2MerkleStreamerFactory } from "../src/SablierV2MerkleStreamerFactory.sol"; | ||
import { SablierV2Batch } from "../src/SablierV2Batch.sol"; | ||
|
||
/// @notice Deploys the Sablier V2 Protocol expect for comptroller. | ||
contract DeployProtocol is BaseScript { | ||
function run( | ||
address initialAdmin, | ||
SablierV2Comptroller comptroller | ||
) | ||
public | ||
virtual | ||
broadcast | ||
returns ( | ||
SablierV2LockupDynamic lockupDynamic, | ||
SablierV2LockupLinear lockupLinear, | ||
SablierV2NFTDescriptor nftDescriptor, | ||
SablierV2Batch batch, | ||
SablierV2MerkleStreamerFactory merkleStreamerFactory | ||
) | ||
{ | ||
uint256 maxSegmentCount = 300; | ||
|
||
// Deploy V2 Core. | ||
nftDescriptor = new SablierV2NFTDescriptor(); | ||
lockupDynamic = new SablierV2LockupDynamic(initialAdmin, comptroller, nftDescriptor, maxSegmentCount); | ||
lockupLinear = new SablierV2LockupLinear(initialAdmin, comptroller, nftDescriptor); | ||
|
||
batch = new SablierV2Batch(); | ||
merkleStreamerFactory = new SablierV2MerkleStreamerFactory(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Usage: ./shell/deploy-multi-chains.sh [options] [chain1 [chain2 ...]] | ||
# Options: | ||
# --deterministic Deploy using the deterministic script. | ||
# --broadcast Broadcast the deployment and verify on Etherscan. | ||
# Example: ./shell/deploy-multi-chains.sh # Default deploys only to Sepolia | ||
# Example: ./shell/deploy-multi-chains.sh --broadcast arbitrum_one mainnet | ||
# Example: ./shell/deploy-multi-chains.sh --deterministic --broadcast mainnet | ||
|
||
# Make sure you set-up your .env file first. See .env.example. | ||
|
||
# Pre-requisites: | ||
# - foundry (https://getfoundry.sh) | ||
|
||
# Strict mode: https://gist.github.com/vncsna/64825d5609c146e80de8b1fd623011ca | ||
set -euo pipefail | ||
|
||
# Create deployments directory | ||
deployments=./deployments | ||
rm -rf $deployments | ||
mkdir $deployments | ||
|
||
# Declare chain IDs | ||
ARBITRUM_CHAIN_ID="42161" | ||
AVALANCHE_CHAIN_ID="43114" | ||
BASE_CHAIN_ID="8453" | ||
BSC_CHAIN_ID="56" | ||
GOERLI_CHAIN_ID="5" | ||
GNOSIS_CHAIN_ID="100" | ||
MAINNET_CHAIN_ID="1" | ||
OPTIMISM_CHAIN_ID="10" | ||
POLYGON_CHAIN_ID="137" | ||
SCROLL_CHAIN_ID="534352" | ||
SEPOLIA_CHAIN_ID="11155111" | ||
|
||
# from: https://docs.sablier.com/contracts/v2/deployments | ||
ARBITRUM_COMPTROLLER="0x17Ec73692F0aDf7E7C554822FBEAACB4BE781762" | ||
AVALANCHE_COMPTROLLER="0x66F5431B0765D984f82A4fc4551b2c9ccF7eAC9C" | ||
BASE_COMPTROLLER="0x7Faaedd40B1385C118cA7432952D9DC6b5CbC49e" | ||
BSC_COMPTROLLER="0x33511f69A784Fd958E6713aCaC7c9dCF1A5578E8" | ||
MAINNET_COMPTROLLER="0xC3Be6BffAeab7B297c03383B4254aa3Af2b9a5BA" | ||
GNOSIS_COMPTROLLER="0x73962c44c0fB4cC5e4545FB91732a5c5e87F55C2" | ||
OPTIMISM_COMPTROLLER="0x1EECb6e6EaE6a1eD1CCB4323F3a146A7C5443A10" | ||
POLYGON_COMPTROLLER="0x9761692EDf10F5F2A69f0150e2fd50dcecf05F2E" | ||
SCROLL_COMPTROLLER="0x859708495E3B3c61Bbe19e6E3E1F41dE3A5C5C5b" | ||
SEPOLIA_COMPTROLLER="0x2006d43E65e66C5FF20254836E63947FA8bAaD68" | ||
|
||
# Define chain configurations | ||
declare -A chains | ||
chains["arbitrum_one"]="$ARBITRUM_RPC_URL $ARBISCAN_API_KEY $ARBITRUM_CHAIN_ID $ARBITRUM_ADMIN $ARBITRUM_COMPTROLLER" | ||
chains["avalanche"]="$AVALANCHE_RPC_URL $SNOWTRACE_API_KEY $AVALANCHE_CHAIN_ID $AVALANCHE_ADMIN $AVALANCHE_COMPTROLLER" | ||
chains["base"]="$BASE_RPC_URL $BASESCAN_API_KEY $BASE_CHAIN_ID $BASE_ADMIN $BASE_ADMIN $BASE_COMPTROLLER" | ||
chains["bnb_smart_chain"]="$BSC_RPC_URL $BSCSCAN_API_KEY $BSC_CHAIN_ID $BSC_ADMIN $BSC_COMPTROLLER" | ||
chains["gnosis"]="$GNOSIS_RPC_URL $GNOSISSCAN_API_KEY $GNOSIS_CHAIN_ID $GNOSIS_ADMIN $GNOSIS_COMPTROLLER" | ||
chains["mainnet"]="$MAINNET_RPC_URL $ETHERSCAN_API_KEY $MAINNET_CHAIN_ID $MAINNET_ADMIN $MAINNET_COMPTROLLER" | ||
chains["optimism"]="$OPTIMISM_RPC_URL $OPTIMISTIC_API_KEY $OPTIMISM_CHAIN_ID $OPTIMISM_ADMIN $OPTIMISM_COMPTROLLER" | ||
chains["polygon"]="$POLYGON_RPC_URL $POLYGONSCAN_API_KEY $POLYGON_CHAIN_ID $POLYGON_ADMIN $POLYGON_COMPTROLLER" | ||
chains["scroll"]="$SCROLL_RPC_URL $SCROLL_API_KEY $SCROLL_CHAIN_ID $SCROLL_ADMIN $SCROLL_COMPTROLLER" | ||
chains["sepolia"]="$SEPOLIA_RPC_URL $ETHERSCAN_API_KEY $SEPOLIA_CHAIN_ID $SEPOLIA_ADMIN $SEPOLIA_COMPTROLLER" | ||
|
||
# Flag for broadcast deployment | ||
BROADCAST_DEPLOYMENT=false | ||
|
||
# Flag for deterministic deployment | ||
DETERMINISTIC_DEPLOYMENT=false | ||
|
||
# Flag for gas price | ||
WITH_GAS_PRICE=false | ||
GAS_PRICE=0 | ||
|
||
# Requested chains | ||
requested_chains=() | ||
|
||
# Check for arguments passed to the script | ||
for ((i=1; i<=$#; i++)); do | ||
arg=${!i} | ||
|
||
# Check for '--broadcast' flag in the arguments | ||
if [[ $arg == "--broadcast" ]]; then | ||
BROADCAST_DEPLOYMENT=true | ||
fi | ||
|
||
# Check for '--broadcast' flag in the arguments | ||
if [[ $arg == "--deterministic" ]]; then | ||
DETERMINISTIC_DEPLOYMENT=true | ||
fi | ||
|
||
# Check for '--with-gas-price' flag in the arguments | ||
if [[ $arg == "--with-gas-price" ]]; then | ||
WITH_GAS_PRICE=true | ||
# Increment index to get the next argument, which should be the gas price | ||
((i++)) | ||
GAS_PRICE=${!i} | ||
if ! [[ $GAS_PRICE =~ ^[0-9]+$ ]]; then | ||
echo "Error: Gas price must be a number." | ||
exit 1 | ||
fi | ||
fi | ||
|
||
# Check for '--all' flag in the arguments | ||
if [[ $arg == "--all" ]]; then | ||
requested_chains=("${!chains[@]}") | ||
fi | ||
|
||
# Check for passed chains | ||
if [[ $arg != "--all" && $arg != "--deterministic" && $arg != "--broadcast" && $arg != "--with-gas-price" ]]; then | ||
requested_chains+=("$arg") | ||
fi | ||
done | ||
|
||
# Set the default chain to Sepolia if no chains are requested | ||
if [ ${#requested_chains[@]} -eq 0 ]; then | ||
requested_chains=("sepolia") | ||
fi | ||
|
||
# Compile the contracts | ||
echo "Compiling the contracts..." | ||
FOUNDRY_PROFILE=optimized forge build | ||
|
||
# Deploy to requested chains | ||
for chain in "${requested_chains[@]}"; do | ||
# Check if the requested chain is defined | ||
if [[ ! -v "chains[$chain]" ]]; then | ||
echo "Chain configuration for '$chain' not found." | ||
continue | ||
fi | ||
|
||
# Split the configuration into RPC, API key and the Chain ID | ||
IFS=' ' read -r rpc_url api_key chain_id admin comptroller<<< "${chains[$chain]}" | ||
|
||
# Declare a deployment command | ||
deployment_command=""; | ||
|
||
# Choose the script based on the flag | ||
if [[ $DETERMINISTIC_DEPLOYMENT == true ]]; then | ||
echo "Deploying deterministic contracts to $chain..." | ||
# Construct the command | ||
deployment_command="forge script script/DeployDeterministicProtocol2.s.sol \ | ||
--rpc-url $rpc_url \ | ||
--sig run(string,address,address) \ | ||
\"ChainID $chain_id, Version 1.1.0\" \ | ||
$admin \ | ||
$comptroller \ | ||
-vvv" | ||
else | ||
echo "Deploying contracts to $chain..." | ||
# Construct the command | ||
deployment_command="forge script script/DeployProtocol2.s.sol \ | ||
--rpc-url $rpc_url \ | ||
--sig run(address,address) \ | ||
$admin \ | ||
$comptroller \ | ||
-vvv" | ||
fi | ||
|
||
# Append additional options if broadcast is enabled | ||
if [[ $BROADCAST_DEPLOYMENT == true ]]; then | ||
echo "This deployment is broadcasted on $chain" | ||
deployment_command+=" --broadcast --verify --etherscan-api-key \"$api_key\"" | ||
else | ||
echo "This deployment is simulated on $chain" | ||
fi | ||
|
||
# Append additional options if gas price is enabled | ||
if [[ $WITH_GAS_PRICE == true ]]; then | ||
gas_price_in_gwei=$(echo "scale=2; $GAS_PRICE / 1000000000" | bc) | ||
echo "This deployment is using gas price of $gas_price_in_gwei gwei" | ||
deployment_command+=" --with-gas-price $GAS_PRICE" | ||
fi | ||
|
||
# Run the deployment command | ||
output=$(FOUNDRY_PROFILE=optimized $deployment_command) | ||
|
||
# Create a file for the chain | ||
chain_file="$deployments/$chain.txt" | ||
touch "$chain_file" | ||
|
||
# Extract and save contract addresses | ||
nftDescriptor_address=$(echo "$output" | awk '/nftDescriptor: contract/{print $NF}') | ||
lockupLinear_address=$(echo "$output" | awk '/lockupLinear: contract/{print $NF}') | ||
lockupDynamic_address=$(echo "$output" | awk '/lockupDynamic: contract/{print $NF}') | ||
batch_address=$(echo "$output" | awk '/batch: contract/{print $NF}') | ||
merkleStreamerFactory_address=$(echo "$output" | awk '/merkleStreamerFactory: contract/{print $NF}') | ||
|
||
# Save to the chain file | ||
{ | ||
echo "NFTDescriptor = $nftDescriptor_address" | ||
echo "LockupLinear = $lockupLinear_address" | ||
echo "LockupDynamic = $lockupDynamic_address" | ||
echo "SablierV2Batch = $batch_address" | ||
echo "SablierV2MerkleStreamerFactory = $merkleStreamerFactory_address" | ||
} >> "$chain_file" | ||
|
||
echo "Deployment for $chain done. Addresses saved in $chain_file" | ||
done | ||
|
||
echo "All deployments completed." |