All contract deployment scripts are written in Solidity and can be found in the script
directory.
Instructions are also provided below for running the deployment scripts using the forge
CLI tool provided by Foundry.
Before running the deployment scripts, you should first set up a .env
file with the necessary environment variables.
You can use the provided .env.example
file as a template.
The instructions are organized by recommended order of deployment. They showcase how to deploy the contracts to the
Sepolia testnet, but you can pick any other chain listed under the [rpc_endpoints]
section in
foundry.toml
.
All protocol contracts can be deployed in a single step by running the following script:
# Set the deployment variables
export NETWORK="sepolia"
# Run the script
forge script script/DeployMaster.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run()" \
--verify
Protocol contracts (i.e., LiquidityDeployer
, RushLauncher
, and RushRouterAlpha
) can also be upgraded in a single
step by running the following script:
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
export LIQUIDITY_POOL="<ADDRESS>"
export RUSH_ERC20_FACTORY="<ADDRESS>"
export RUSH_SMART_LOCK="<ADDRESS>"
export OLD_LIQUIDITY_DEPLOYER="<ADDRESS>"
export OLD_RUSH_LAUNCHER="<ADDRESS>"
export OLD_RUSH_ROUTER="<ADDRESS>"
# Run the script
forge script script/UpgradeMaster.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address,address,address,address,address,address,address)" \
--verify \
${ACL_MANAGER} \
${LIQUIDITY_POOL} \
${RUSH_ERC20_FACTORY} \
${RUSH_SMART_LOCK} \
${OLD_LIQUIDITY_DEPLOYER} \
${OLD_RUSH_LAUNCHER} \
${OLD_RUSH_ROUTER}
```
## Step-by-Step
The following sections provide step-by-step instructions for deploying each contract individually. You should replace
placeholders with the actual arguments you want to pass as follows:
- `<ADDRESS>`: An Ethereum address (e.g., `0x1234567890abcdef1234567890abcdef12345678`).
- `<WAD>`: A number in 18 decimal format (e.g., `1000000000000000000` representing 1 RushERC20 token, 1 ETH, or 100%
rate).
- `<SECONDS>`: Number of seconds (e.g., `3600` representing 1 hour).
### Deploy `ACLManager`
```shell
# Set the deployment variables
export NETWORK="sepolia"
export ADMIN="<ADDRESS>"
# Run the script
forge script script/DeployACLManager.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address)" \
--verify \
${ADMIN}
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
export ASSET="<ADDRESS>"
export MAX_TOTAL_DEPOSITS="<WAD>"
# Run the script
forge script script/DeployLiquidityPool.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address,address,uint256)" \
--verify \
${ACL_MANAGER} \
${ASSET} \
${MAX_TOTAL_DEPOSITS}
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
# Run the script
forge script script/DeployRushERC20Factory.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address)" \
--verify \
${ACL_MANAGER}
# Set the deployment variables
export NETWORK="sepolia"
export BASE_FEE_RATE="<WAD>"
export OPTIMAL_UTILIZATION_RATIO="<WAD>"
export RATE_SLOPE_1="<WAD>"
export RATE_SLOPE_2="<WAD>"
# Run the script
forge script script/DeployFeeCalculator.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(uint256,uint256,uint256,uint256)" \
--verify \
${BASE_FEE_RATE} \
${OPTIMAL_UTILIZATION_RATIO} \
${RATE_SLOPE_1} \
${RATE_SLOPE_2}
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
export LIQUIDITY_POOL="<ADDRESS>"
export UNISWAP_V2_FACTORY="<ADDRESS>"
# Run the script
forge script script/DeployRushSmartLock.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address,address,address)" \
--verify \
${ACL_MANAGER} \
${LIQUIDITY_POOL} \
${UNISWAP_V2_FACTORY}
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
export EARLY_UNWIND_THRESHOLD="<WAD>"
export FEE_CALCULATOR="<ADDRESS>"
export LIQUIDITY_POOL="<ADDRESS>"
export MAX_DEPLOYMENT_AMOUNT="<WAD>"
export MAX_DURATION="<SECONDS>"
export MIN_DEPLOYMENT_AMOUNT="<WAD>"
export MIN_DURATION="<SECONDS>"
export RESERVE="<ADDRESS>"
export RESERVE_FACTOR="<WAD>"
export REWARD_FACTOR="<WAD>"
export RUSH_SMART_LOCK="<ADDRESS>"
export SURPLUS_FACTOR="<WAD>"
# Run the script
forge script script/DeployLiquidityDeployer.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run((address,uint256,address,address,uint256,uint256,uint256,uint256,address,uint256,uint256,address,uint256))" \
--verify \
"(${ACL_MANAGER}, \
${EARLY_UNWIND_THRESHOLD}, \
${FEE_CALCULATOR}, \
${LIQUIDITY_POOL}, \
${MAX_DEPLOYMENT_AMOUNT}, \
${MAX_DURATION}, \
${MIN_DEPLOYMENT_AMOUNT}, \
${MIN_DURATION}, \
${RESERVE}, \
${RESERVE_FACTOR}, \
${REWARD_FACTOR}, \
${RUSH_SMART_LOCK}, \
${SURPLUS_FACTOR})"
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
export LIQUIDITY_DEPLOYER="<ADDRESS>"
export MAX_SUPPLY_LIMIT="<WAD>"
export MIN_SUPPLY_LIMIT="<WAD>"
export RUSH_ERC20_FACTORY="<ADDRESS>"
export UNISWAP_V2_FACTORY="<ADDRESS>"
# Run the script
forge script script/DeployRushLauncher.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address,address,uint256,uint256,address,address)" \
--verify \
${ACL_MANAGER} \
${LIQUIDITY_DEPLOYER} \
${MAX_SUPPLY_LIMIT} \
${MIN_SUPPLY_LIMIT} \
${RUSH_ERC20_FACTORY} \
${UNISWAP_V2_FACTORY}
# Set the deployment variables
export NETWORK="sepolia"
export RUSH_LAUNCHER="<ADDRESS>"
export SPONSOR="<ADDRESS>"
export VERIFIER="<ADDRESS>"
# Run the script
forge script script/DeployRushRouterAlpha.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address)" \
--verify \
${RUSH_LAUNCHER} \
${SPONSOR} \
${VERIFIER}
# Set the deployment variables
export NETWORK="sepolia"
export ACL_MANAGER="<ADDRESS>"
export RUSH_LAUNCHER="<ADDRESS>"
export OLD_RUSH_ROUTER="<ADDRESS>"
export SPONSOR="<ADDRESS>"
export VERIFIER="<ADDRESS>"
# Run the script
forge script script/UpgradeRushRouterAlpha.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address,address,address,address,address)" \
--verify \
${ACL_MANAGER} \
${RUSH_LAUNCHER} \
${OLD_RUSH_ROUTER} \
${SPONSOR} \
${VERIFIER}
# Set the deployment variables
export NETWORK="sepolia"
export RUSH_ERC20_FACTORY="<ADDRESS>"
export RUSH_ERC20_TEMPLATE="<ADDRESS>"
# Run the script
forge script script/AddTokenTemplate.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run(address,address)" \
${RUSH_ERC20_FACTORY} \
${RUSH_ERC20_TEMPLATE}
The ACLManager
contract is used to manage roles and permissions. Once the contracts are deployed, the ADMIN
role
recipient should assign the necessary roles to the contracts as follows:
It is assigned to the LiquidityDeployer
contract to allow it to manage the LiquidityPool
assets. The necessary role
is assigned by calling the addAssetManager
function on the ACLManager
contract.
aclManager.addAssetManager({
account: address(liquidityDeployer)
});
It is assigned to the RushLauncher
contract to allow it to launch new RushERC20 tokens and deploy liquidity. The
necessary role is assigned by calling the addLauncher
function on the ACLManager
contract.
aclManager.addLauncher({
account: address(rushLauncher)
});
It is assigned to the RushRouterAlpha
contract to allow it to call the launch
function on the RushLauncher
contract. The necessary role is assigned by calling the addRouter
function on the ACLManager
contract.
aclManager.addRouter({
account: address(rushRouterAlpha)
});
After the very first deposit is made to the LiquidityPool
, the ADMIN
role recipient should invoke the
takeSnapshotTotalAssets
function on the LiquidityPool
contract to take a snapshot of the total assets and enable
proper deployment fee calculation for the FeeCalculator
contract. The function is only needed to be called once after
the first deposit, as subsequent LiquidityPool interactions will automatically update the snapshot.
liquidityPool.takeSnapshotTotalAssets();
To allow the RushLauncher
contract to launch new RushERC20 tokens, the ADMIN
role recipient should add the token
templates to the RushERC20Factory
contract. The token templates are added by calling the addTemplate
function on the
RushERC20Factory
contract. But first, the token templates should be deployed to the network.
# Set the deployment variables
export NETWORK="sepolia"
# Run the scripts
forge script script/DeployTokenRushERC20Basic.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run()" \
--verify
forge script script/DeployTokenRushERC20Taxable.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run()" \
--verify
forge script script/DeployTokenRushERC20Donatable.s.sol \
--broadcast \
--rpc-url ${NETWORK} \
--sig "run()" \
--verify
rushERC20Factory.addTemplate(address(rushERC20Basic));
rushERC20Factory.addTemplate(address(rushERC20Taxable));