Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
93fe784
Add testnet governance deployment and testing scripts
alysiahuggins Jan 7, 2026
136a572
add scripts, do not commit governance env as not needed in main
alysiahuggins Jan 7, 2026
9e557b2
wait for user input if not deploying and testing on localhost
alysiahuggins Jan 7, 2026
5ccd4e2
merge from main
alysiahuggins Jan 8, 2026
c08aea0
added retry_until_true helper for state checks, add 1s cooldown afyme…
alysiahuggins Jan 12, 2026
8b8b8b8
update readme and add env file acceptance to scripts
alysiahuggins Jan 12, 2026
f49ef44
comment grant roles for now
alysiahuggins Jan 12, 2026
ce47e0e
update readme
alysiahuggins Jan 12, 2026
f179194
updated readme, made some flow changes to the deployment script and i…
alysiahuggins Jan 14, 2026
8ae6260
give user option to set output file
alysiahuggins Jan 14, 2026
2892972
clippy fix
alysiahuggins Jan 14, 2026
e8c3864
Merge branch 'main' into gov-test
alysiahuggins Jan 14, 2026
e2d98e7
ensur that the read_proxy_impl can read addresses that are not proxies
alysiahuggins Jan 14, 2026
e7c2917
Update README.md for ENV_FILE instructions
alysiahuggins Jan 16, 2026
9c1c7e6
Update README to reference OUTPUT_FILE instead of ENV_FILE
alysiahuggins Jan 16, 2026
219ee88
refactor retry_until_true
alysiahuggins Jan 16, 2026
b3f385d
updates to the readme
alysiahuggins Jan 19, 2026
e1ec799
ci fix
alysiahuggins Jan 19, 2026
f31ebf8
clippy fix
alysiahuggins Jan 19, 2026
5e1d235
clipy fix
alysiahuggins Jan 19, 2026
4776e0a
Merge branch 'main' into gov-test
alysiahuggins Jan 19, 2026
1b5c25b
make some vars optional
alysiahuggins Jan 28, 2026
45aba77
Merge branch 'main' into gov-test
alysiahuggins Jan 28, 2026
59156b3
Update contracts/rust/deployer/scripts/testnet-governance-deploy.sh
alysiahuggins Jan 29, 2026
4300862
fix: add bc to nix flake
sveitser Jan 29, 2026
ebf2494
Update contracts/rust/deployer/scripts/testnet-governance-flows.sh
alysiahuggins Jan 29, 2026
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
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ ESPRESSO_NASTY_CLIENT_PORT=24011
# which ensures that all services work correctly in the demo without admin access. In a real
# deployment, we would set this to the address of a multisig wallet.
ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS=8626f6940e2eb28930efb4cef49b2d1f2c9c1199
ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS=8626f6940e2eb28930efb4cef49b2d1f2c9c1199
ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}

# Set this to the number of blocks you would like to confirm the sequencer can reach
INTEGRATION_TEST_EXPECTED_BLOCK_HEIGHT=10
Expand All @@ -176,6 +176,6 @@ ESPRESSO_OPS_TIMELOCK_ADMIN=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}
ESPRESSO_OPS_TIMELOCK_PROPOSERS=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}
ESPRESSO_OPS_TIMELOCK_EXECUTORS=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}
ESPRESSO_SAFE_EXIT_TIMELOCK_DELAY=1209600
ESPRESSO_SAFE_EXIT_TIMELOCK_ADMIN=8626f6940e2eb28930efb4cef49b2d1f2c9c1199
ESPRESSO_SAFE_EXIT_TIMELOCK_ADMIN=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}
ESPRESSO_SAFE_EXIT_TIMELOCK_PROPOSERS=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}
ESPRESSO_SAFE_EXIT_TIMELOCK_EXECUTORS=${ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ data/*-actual.bin
.env.contracts.water
.env*.decaf
.env.docker
.env.governance.test

# Generated by nix-direnv
.direnv/
Expand Down
69 changes: 69 additions & 0 deletions contracts/rust/deployer/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Governance script test

For testing purposes, use this to deploy POS contracts, with timelock ownership, and execute various timelock flows.

## Pre-requisites

- `nix` installed
- in the root of the directory, enter `nix develop`

### Build Optimization

To avoid rebuilds during script execution, pre-build the deploy binary:

```bash
cargo build --bin deploy
```

## Deploying the contracts

1. Copy the env file

```bash
export ENV_FILE={YOUR_ENV_FILE}
cp .env $ENV_FILE
```

- and replace the following fields in the `$ENV_FILE` if not deploying to a local network via anvil.
- `ESPRESSO_SEQUENCER_ETH_MNEMONIC`
- `ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS`

- The default ops and safe exit timelock delays in this script is 30 and 60 seconds respectively. If you want to change
it then also add the following fields to the ENV_FILE:
- `OPS_DELAY` (in seconds)
- `SAFE_EXIT_DELAY` (in seconds)

2. set the RPC_URL, ACCOUNT_INDEX and OUTPUT_FILE

```bash
export RPC_URL={YOUR_RPC_URL}
export ACCOUNT_INDEX={YOUR_ACCOUNT_INDEX} # Optional: default value is zero
export OUTPUT_FILE={YOUR_OUTPUT_FILE} # Optional: customize output file
```

3. Run the script

```bash
./contracts/rust/deployer/scripts/testnet-governance-deploy.sh --env-file $ENV_FILE
```

## Running the test flow

1. Assuming the contracts are deployed and their proxy addresses are found `$OUTPUT_FILE`
2. Ensure that you have an RPC URL for the network the contracts are deployed to
3. Have your ledger connected (assumes account index = 0 otherwise set `export ACCOUNT_INDEX=YOUR_ACCOUNT_INDEX`)

```bash
export RPC_URL={YOUR_RPC_URL}
./contracts/rust/deployer/scripts/testnet-governance-flows.sh --ledger --env-file $OUTPUT_FILE
```

**Note**: The `$OUTPUT_FILE` from the deploy script contains the deployed contract addresses and should be used as
`--env-file` for the flows script.

## Notes

- The script will prompt for confirmation before each operation
- Operations use a 30-second delay by default (configurable via OPS_DELAY env var)
- For non-localhost RPCs, you'll be prompted to confirm before proceeding
- to use a ledger with any command, use `--ledger`
196 changes: 196 additions & 0 deletions contracts/rust/deployer/scripts/testnet-governance-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
#!/usr/bin/env bash
# This script deploys the contracts to testnet so that governance flows can be tested
set -euo pipefail

# Find repo root and source .env file
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
echo "REPO_ROOT: $REPO_ROOT"

# Parse command line arguments
USE_LEDGER=false
ENV_FILE=""
while [[ $# -gt 0 ]]; do
case $1 in
--ledger)
USE_LEDGER=true
shift
;;
--env-file)
ENV_FILE="$2"
shift 2
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--ledger] [--env-file FILE]"
exit 1
;;
esac
done

# Source env file if provided, otherwise try default .env
if [[ -n "$ENV_FILE" ]]; then
if [[ ! -f "$ENV_FILE" ]]; then
echo "Error: env file not found: $ENV_FILE"
exit 1
fi
set -a
source "$ENV_FILE"
set +a
elif [[ -f "$REPO_ROOT/.env" ]]; then
set -a
source "$REPO_ROOT/.env"
set +a
fi

# Unset any variables containing "PROXY_ADDRESS" to force fresh deployment
for var in $(env | grep -i "PROXY_ADDRESS" | cut -d= -f1); do
unset "$var" 2>/dev/null || true
done


RPC_URL="${RPC_URL:-http://localhost:8545}"
OUTPUT_FILE="${OUTPUT_FILE:-.env.governance.testnet}"
ACCOUNT_INDEX="${ACCOUNT_INDEX:-0}"
OPS_DELAY="${OPS_DELAY:-30}" # 30 seconds default
SAFE_EXIT_DELAY="${SAFE_EXIT_DELAY:-60}" # 60 seconds default

# Helper function to check if RPC URL is localhost
is_localhost_rpc() {
local url="$1"
# Check for localhost, 127.0.0.1
[[ "$url" =~ ^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?(/.*)?$ ]]
}

if is_localhost_rpc "$RPC_URL"; then
unset ESPRESSO_SEQUENCER_ETH_MULTISIG_ADDRESS
fi

# Function to prompt user for confirmation on real testnets
confirm() {
local message="${1:-Continue?}"
if is_localhost_rpc "$RPC_URL"; then
return 0
fi
read -p "$message [y/N] " -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborted."
exit 1
fi
}

# Use hardcoded anvil addresses only for localhost, otherwise use env vars
if is_localhost_rpc "$RPC_URL"; then
ESPRESSO_OPS_TIMELOCK_PROPOSERS="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"
ESPRESSO_OPS_TIMELOCK_EXECUTORS="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"
ESPRESSO_SAFE_EXIT_TIMELOCK_PROPOSERS="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"
ESPRESSO_SAFE_EXIT_TIMELOCK_EXECUTORS="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"
ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"
else
ESPRESSO_OPS_TIMELOCK_PROPOSERS="${ESPRESSO_OPS_TIMELOCK_PROPOSERS:?ESPRESSO_OPS_TIMELOCK_PROPOSERS must be set for non-localhost deployments}"
ESPRESSO_OPS_TIMELOCK_EXECUTORS="${ESPRESSO_OPS_TIMELOCK_EXECUTORS:?ESPRESSO_OPS_TIMELOCK_EXECUTORS must be set for non-localhost deployments}"
ESPRESSO_SAFE_EXIT_TIMELOCK_PROPOSERS="${ESPRESSO_SAFE_EXIT_TIMELOCK_PROPOSERS:?ESPRESSO_SAFE_EXIT_TIMELOCK_PROPOSERS must be set for non-localhost deployments}"
ESPRESSO_SAFE_EXIT_TIMELOCK_EXECUTORS="${ESPRESSO_SAFE_EXIT_TIMELOCK_EXECUTORS:?ESPRESSO_SAFE_EXIT_TIMELOCK_EXECUTORS must be set for non-localhost deployments}"
ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS="${ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS:?ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS must be set for non-localhost deployments}"
fi

DEPLOY_CMD="cargo run --bin deploy --"
if $USE_LEDGER; then
DEPLOY_CMD="$DEPLOY_CMD --ledger"
unset ESPRESSO_SEQUENCER_ETH_MNEMONIC
unset ESPRESSO_DEPLOYER_ACCOUNT_INDEX
fi

echo "=== Deploying Governance Contracts ==="
echo "RPC URL: $RPC_URL"
if ! is_localhost_rpc "$RPC_URL"; then
echo "WARNING: This will deploy to a non-localhost network!"
confirm "Are you sure you want to proceed with deployment?"
fi

echo ""
echo "### Deploying Ops Timelock ###"
$DEPLOY_CMD --rpc-url "$RPC_URL" --account-index "$ACCOUNT_INDEX" \
--deploy-ops-timelock \
--ops-timelock-admin "$ESPRESSO_OPS_TIMELOCK_ADMIN" \
--ops-timelock-delay "$OPS_DELAY" \
--ops-timelock-proposers "$ESPRESSO_OPS_TIMELOCK_PROPOSERS" \
--ops-timelock-executors "$ESPRESSO_OPS_TIMELOCK_EXECUTORS" \
--out "$OUTPUT_FILE"

set -a
source "${OUTPUT_FILE}"
set +a

echo ""
echo "### Deploying Safe Exit Timelock ###"
$DEPLOY_CMD --rpc-url "$RPC_URL" --account-index "$ACCOUNT_INDEX" \
--deploy-safe-exit-timelock \
--safe-exit-timelock-admin "$ESPRESSO_SAFE_EXIT_TIMELOCK_ADMIN" \
--safe-exit-timelock-delay "$SAFE_EXIT_DELAY" \
--safe-exit-timelock-proposers "$ESPRESSO_SAFE_EXIT_TIMELOCK_PROPOSERS" \
--safe-exit-timelock-executors "$ESPRESSO_SAFE_EXIT_TIMELOCK_EXECUTORS" \
--out "$OUTPUT_FILE"

set -a
source "${OUTPUT_FILE}"
set +a

echo ""
echo "### Deploying Core Contracts (v1) ###"
# Deploy contracts without timelock ownership
BASE_ARGS=(
--rpc-url "$RPC_URL"
--account-index "$ACCOUNT_INDEX"
--multisig-pauser-address "$ESPRESSO_SEQUENCER_ETH_MULTISIG_PAUSER_ADDRESS"
--token-name "$ESP_TOKEN_NAME"
--token-symbol "$ESP_TOKEN_SYMBOL"
--initial-token-supply "$ESP_TOKEN_INITIAL_SUPPLY"
--initial-token-grant-recipient "$ESP_TOKEN_INITIAL_GRANT_RECIPIENT_ADDRESS"
--exit-escrow-period "$ESPRESSO_SEQUENCER_STAKE_TABLE_EXIT_ESCROW_PERIOD"
--mock-espresso-live-network
)

[[ -n "${ESPRESSO_SEQUENCER_PERMISSIONED_PROVER:-}" ]] && \
BASE_ARGS+=(--permissioned-prover "$ESPRESSO_SEQUENCER_PERMISSIONED_PROVER")

$DEPLOY_CMD "${BASE_ARGS[@]}" \
--deploy-light-client-v1 \
--deploy-esp-token-v1 \
--deploy-stake-table-v1 \
--use-mock \
--upgrade-light-client-v2 \
--out "$OUTPUT_FILE"

set -a
source "${OUTPUT_FILE}"
set +a

echo ""
echo "### Deploying Upgrades (v2/v3) ###"
UPGRADE_OUTPUT_FILE="${OUTPUT_FILE}.upgrade"
$DEPLOY_CMD "${BASE_ARGS[@]}" \
--deploy-reward-claim-v1 \
--upgrade-esp-token-v2 \
--upgrade-light-client-v3 \
--upgrade-stake-table-v2 \
--use-timelock-owner \
--out "${UPGRADE_OUTPUT_FILE}"

set -a
source "${UPGRADE_OUTPUT_FILE}"
set +a

echo ""
echo "### Deploy Fee Contract with timelock owner"
$DEPLOY_CMD "${BASE_ARGS[@]}" \
--deploy-fee-v1 \
--use-timelock-owner \
--out "$OUTPUT_FILE"

echo ""
echo "### Verifying Deployment ###"
"${REPO_ROOT}/scripts/verify-pos-deployment.sh" --rpc-url "$RPC_URL"
echo ""
echo "Deployment complete!"
Loading
Loading