Skip to content
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
30 changes: 14 additions & 16 deletions contracts/rust/deployer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ unset ESPRESSO_SEQUENCER_FEE_CONTRACT_PROXY_ADDRESS
unset ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS

# Execute the deployment command
RUST_LOG=info cargo run --bin deploy -- --deploy-fee --rpc-url=$RPC_URL
RUST_LOG=info cargo run --bin deploy -- --deploy-fee-v1 --rpc-url=$RPC_URL
```

### Transfer Ownership with Cargo
Expand Down Expand Up @@ -130,7 +130,7 @@ set +a
unset ESPRESSO_SEQUENCER_FEE_CONTRACT_PROXY_ADDRESS

# Deploy the fee contract with a multisig owner (requires ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS to be set which occurs in the step above)
RUST_LOG=info cargo run --bin deploy -- --deploy-fee --rpc-url=$RPC_URL
RUST_LOG=info cargo run --bin deploy -- --deploy-fee-v1 --rpc-url=$RPC_URL
```

## Timelock Owner
Expand All @@ -146,7 +146,7 @@ set -a
source .env
set +a
unset ESPRESSO_SEQUENCER_FEE_CONTRACT_PROXY_ADDRESS
RUST_LOG=info cargo run --bin deploy -- --deploy-ops-timelock --deploy-fee --use-timelock-owner --rpc-url=$RPC_URL
RUST_LOG=info cargo run --bin deploy -- --deploy-ops-timelock --deploy-fee-v1 --use-timelock-owner --rpc-url=$RPC_URL
```

### Deploying Fee Contract with Docker compose
Expand All @@ -171,7 +171,7 @@ docker compose run --rm \
-e RPC_URL \
-v $(pwd)/.env.mydemo:/app/.env.mydemo \
deploy-sequencer-contracts \
deploy --deploy-ops-timelock --deploy-fee --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
deploy --deploy-ops-timelock --deploy-fee-v1 --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
```

# Token
Expand Down Expand Up @@ -200,7 +200,7 @@ source .env
set +a
unset ESPRESSO_SEQUENCER_ESP_TOKEN_PROXY_ADDRESS
unset ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS
RUST_LOG=info cargo run --bin deploy -- --deploy-esp-token --rpc-url=$RPC_URL
RUST_LOG=info cargo run --bin deploy -- --deploy-esp-token-v1 --rpc-url=$RPC_URL
```

## Multisig Owner
Expand All @@ -212,7 +212,7 @@ set -a
source .env
set +a
unset ESPRESSO_SEQUENCER_ESP_TOKEN_PROXY_ADDRESS
RUST_LOG=info cargo run --bin deploy -- --deploy-esp-token --rpc-url=$RPC_URL
RUST_LOG=info cargo run --bin deploy -- --deploy-esp-token-v1 --rpc-url=$RPC_URL
```

## Timelock Owner
Expand All @@ -228,7 +228,7 @@ set -a
source .env
set +a
unset ESPRESSO_SEQUENCER_ESP_TOKEN_PROXY_ADDRESS
RUST_LOG=info cargo run --bin deploy -- --deploy-safe-exit-timelock --deploy-esp-token --use-timelock-owner --rpc-url=$RPC_URL
RUST_LOG=info cargo run --bin deploy -- --deploy-safe-exit-timelock --deploy-esp-token-v1 --use-timelock-owner --rpc-url=$RPC_URL
```

### Deploying Token with Docker compose
Expand All @@ -253,7 +253,7 @@ docker compose run --rm \
-e RPC_URL \
-v $(pwd)/.env.mydemo:/app/.env.mydemo \
deploy-sequencer-contracts \
deploy --deploy-safe-exit-timelock --deploy-esp-token --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
deploy --deploy-safe-exit-timelock --deploy-esp-token-v1 --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
```

Example output file (.env.mydemo) contents after a successful run
Expand Down Expand Up @@ -284,7 +284,7 @@ export ESPRESSO_OPS_TIMELOCK_ADMIN=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
export ESPRESSO_OPS_TIMELOCK_PROPOSERS=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
export ESPRESSO_OPS_TIMELOCK_EXECUTORS=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
export ESPORESS_OPS_TIMELOCK_DELAY=0
RUST_LOG=info cargo run --bin deploy -- --deploy-ops-timelock --deploy-fee --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
RUST_LOG=info cargo run --bin deploy -- --deploy-ops-timelock --deploy-fee-v1 --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
```

The deployed contracts will be written to `.env.mydemo`
Expand Down Expand Up @@ -399,7 +399,7 @@ export ESPRESSO_OPS_TIMELOCK_ADMIN=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
export ESPRESSO_OPS_TIMELOCK_PROPOSERS=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
export ESPRESSO_OPS_TIMELOCK_EXECUTORS=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
export ESPORESS_OPS_TIMELOCK_DELAY=0
RUST_LOG=info cargo run --bin deploy -- --deploy-ops-timelock --deploy-fee --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
RUST_LOG=info cargo run --bin deploy -- --deploy-ops-timelock --deploy-fee-v1 --use-timelock-owner --rpc-url=$RPC_URL --out .env.mydemo
```

The deployed contracts will be written to `.env.mydemo`
Expand Down Expand Up @@ -577,7 +577,7 @@ set +a
unset ESPRESSO_SEQUENCER_ESP_TOKEN_PROXY_ADDRESS
# If doing a real run then, export ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS=YOUR_MULTISIG_ADDRESS
RUST_LOG=info cargo run --bin deploy -- \
--deploy-esp-token \
--deploy-esp-token-v1 \
--upgrade-esp-token-v2 \
--rpc-url=$RPC_URL \
--use-multisig
Expand All @@ -593,7 +593,7 @@ docker compose run --rm \
-e ESPRESSO_SEQUENCER_ETH_MNEMONIC \
-v $(pwd)/.env.mydemo:/app/.env.mydemo \
deploy-sequencer-contracts \
deploy --deploy-esp-token --upgrade-esp-token-v2 --rpc-url=$RPC_URL --use-multisig
deploy --deploy-esp-token-v1 --upgrade-esp-token-v2 --rpc-url=$RPC_URL --use-multisig
# to simulate, add --dry-run
```

Expand Down Expand Up @@ -654,7 +654,6 @@ export RPC_URL=""
cargo run --bin deploy -- \
--propose-transfer-ownership-to-timelock \
--target-contract FeeContract \
--timelock-address $ESPRESSO_SEQUENCER_OPS_TIMELOCK_ADDRESS \
--fee-contract-proxy $ESPRESSO_SEQUENCER_FEE_CONTRACT_PROXY_ADDRESS \
--multisig-address $ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS \
--rpc-url $RPC_URL \
Expand All @@ -678,7 +677,6 @@ export RPC_URL=""
docker-compose run --rm deploy-sequencer-contracts \
--propose-transfer-ownership-to-timelock \
--target-contract lightclient \
--timelock-address $ESPRESSO_SEQUENCER_TIMELOCK_ADDRESS \
--light-client-proxy $ESPRESSO_SEQUENCER_LIGHT_CLIENT_PROXY_ADDRESS \
--multisig-address $ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS \
--rpc-url $RPC_URL
Expand Down Expand Up @@ -1117,7 +1115,7 @@ docker compose run --rm \
-v $(pwd)/$OUTPUT_FILE:/app/$OUTPUT_FILE \
\
deploy-sequencer-contracts \
deploy --deploy-esp-token --use-timelock-owner --rpc-url=$RPC_URL --out $OUTPUT_FILE
deploy --deploy-esp-token-v1 --use-timelock-owner --rpc-url=$RPC_URL --out $OUTPUT_FILE
# to simulate, add --dry-run
```

Expand Down Expand Up @@ -1226,7 +1224,7 @@ docker compose run --rm \
-v $(pwd)/$OUTPUT_FILE:/app/$OUTPUT_FILE \
\
deploy-sequencer-contracts \
deploy --deploy-stake-table --upgrade-stake-table-v2 --use-timelock-owner --rpc-url=$RPC_URL --out $OUTPUT_FILE
deploy --deploy-stake-table-v1 --upgrade-stake-table-v2 --use-timelock-owner --rpc-url=$RPC_URL --out $OUTPUT_FILE
# to simulate, add --dry-run
```

Expand Down
95 changes: 45 additions & 50 deletions contracts/rust/deployer/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use crate::{
StakeTableV2UpgradeParams, TransferOwnershipParams,
},
timelock::{
cancel_timelock_operation, execute_timelock_operation, schedule_timelock_operation,
TimelockOperationData, TimelockOperationType,
cancel_timelock_operation, derive_timelock_address_from_contract_type,
execute_timelock_operation, schedule_timelock_operation, TimelockOperationData,
TimelockOperationType,
},
},
Contract, Contracts,
Expand Down Expand Up @@ -132,8 +133,6 @@ pub struct DeployerArgs<P: Provider + WalletProvider> {
transfer_ownership_from_eoa: Option<bool>,
#[builder(default)]
transfer_ownership_new_owner: Option<Address>,
#[builder(default)]
timelock_address: Option<Address>,
}

impl<P: Provider + WalletProvider> DeployerArgs<P> {
Expand All @@ -156,9 +155,8 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {
);
// deployer is the timelock owner
if use_timelock_owner {
let timelock_addr = contracts
.address(Contract::OpsTimelock)
.expect("fail to get OpsTimelock address");
let timelock_addr =
derive_timelock_address_from_contract_type(target, contracts)?;
crate::transfer_ownership(provider, target, addr, timelock_addr).await?;
}
} else if let Some(multisig) = self.multisig {
Expand Down Expand Up @@ -217,9 +215,8 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {
// - No emergency updates are expected for token functionality
// - SafeExitTimelock provides sufficient security for token operations
tracing::info!("Transferring ownership to SafeExitTimelock");
let timelock_addr = contracts
.address(Contract::SafeExitTimelock)
.expect("fail to get SafeExitTimelock address");
let timelock_addr =
derive_timelock_address_from_contract_type(target, contracts)?;
crate::transfer_ownership(provider, target, addr, timelock_addr)
.await?;
}
Expand Down Expand Up @@ -340,9 +337,8 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {
tracing::info!("Transferring ownership to OpsTimelock");
// deployer is the timelock owner
if use_timelock_owner {
let timelock_addr = contracts
.address(Contract::OpsTimelock)
.expect("fail to get OpsTimelock address");
let timelock_addr =
derive_timelock_address_from_contract_type(target, contracts)?;
crate::transfer_ownership(provider, target, addr, timelock_addr)
.await?;
}
Expand Down Expand Up @@ -406,18 +402,18 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {
} else {
// Pick admin from config. StakeTable uses OpsTimelock for faster
// emergency updates since it handles critical staking ops.
let admin = if let Some(use_timelock_owner) = self.use_timelock_owner {
if use_timelock_owner {
contracts
.address(Contract::OpsTimelock)
.expect("fail to get OpsTimelock address")
} else {
admin // deployer
}
} else if let Some(multisig) = self.multisig {
multisig
} else {
admin // deployer
let admin = match self.use_timelock_owner {
Some(true) => {
derive_timelock_address_from_contract_type(target, contracts)?
},
Some(false) => admin, // deployer
None => {
if let Some(multisig) = self.multisig {
multisig
} else {
admin // deployer
}
},
};

tracing::info!("Upgrading StakeTableV2 with admin: {:?}", admin);
Expand Down Expand Up @@ -497,21 +493,16 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {

// RewardClaim uses SafeExitTimelock (longer delay) since it can mint tokens
// and users need time to react to upgrades. Can be paused in emergencies.
let admin = if let Some(use_timelock_owner) = self.use_timelock_owner {
if use_timelock_owner {
contracts
.address(Contract::SafeExitTimelock)
.expect("fail to get SafeExitTimelock address")
} else {
self.ops_timelock_admin.context(
"SafeExitTimelock contract address must be set when using \
--use-timelock-owner flag",
)?
}
} else if let Some(multisig) = self.multisig {
multisig
} else {
admin
let admin = match self.use_timelock_owner {
Some(true) => derive_timelock_address_from_contract_type(target, contracts)?,
Some(false) => admin, // deployer
None => {
if let Some(multisig) = self.multisig {
multisig
} else {
admin // deployer
}
},
};

tracing::info!("Deploying RewardClaimProxy with admin: {:?}", admin);
Expand Down Expand Up @@ -615,6 +606,12 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {
.context("StakeTableProxy address not found")?,
Contract::StakeTableProxy,
),
"RewardClaim" => (
contracts
.address(Contract::RewardClaimProxy)
.context("RewardClaimProxy address not found")?,
Contract::RewardClaimProxy,
),
_ => anyhow::bail!("Invalid target contract: {}", target_contract),
};

Expand Down Expand Up @@ -688,29 +685,27 @@ impl<P: Provider + WalletProvider> DeployerArgs<P> {
)
})?;

let timelock_address = self.timelock_address.ok_or_else(|| {
anyhow::anyhow!(
"Timelock address must be set when proposing ownership transfer. Use \
--timelock-address or ESPRESSO_SEQUENCER_TIMELOCK_ADDRESS"
)
})?;

// Parse the contract type from string
let contract_type = match target_contract.to_lowercase().as_str() {
"lightclient" | "lightclientproxy" => Contract::LightClientProxy,
"feecontract" | "feecontractproxy" => Contract::FeeContractProxy,
"esptoken" | "esptokenproxy" => Contract::EspTokenProxy,
"staketable" | "staketableproxy" => Contract::StakeTableProxy,
"rewardclaim" | "rewardclaimproxy" => Contract::RewardClaimProxy,
_ => anyhow::bail!(
"Unknown contract type: {}. Supported types: lightclient, feecontract, esptoken, \
staketable",
staketable, rewardclaim",
target_contract
),
};

let timelock_address =
derive_timelock_address_from_contract_type(contract_type, contracts)?;

tracing::info!(
"Proposing transfer of ownership from multisig to timelock for {}",
target_contract
"Proposing transfer of ownership from multisig to timelock for {} (timelock: {:?})",
target_contract,
timelock_address
);

let contract = contract_type;
Expand Down
Loading
Loading