Skip to content

Emergency Role Transfer #3

Emergency Role Transfer

Emergency Role Transfer #3

name: Emergency Role Transfer
on:
workflow_dispatch:
inputs:
execution_mode:
description: 'Execution mode'
required: true
type: choice
options:
- full-transfer-with-delay
- step-1-only
- step-2-only
default: full-transfer-with-delay
network_type:
description: 'Network type to transfer roles on'
required: true
type: choice
options:
- testnets
- sepolia-only
- arbitrum_sepolia-only
default: testnets
jobs:
setup-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set matrix based on network type
id: set-matrix
run: |
case "${{ github.event.inputs.network_type }}" in
testnets)
MATRIX='["sepolia", "arbitrum_sepolia"]'
;;
sepolia-only)
MATRIX='["sepolia"]'
;;
arbitrum_sepolia-only)
MATRIX='["arbitrum_sepolia"]'
;;
esac
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
transfer-roles:
needs: setup-matrix
runs-on: ubuntu-latest
strategy:
matrix:
network: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}
fail-fast: false
environment: ${{ matrix.network }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: v1.4.4
cache: true
- name: Validate inputs
run: |
echo "Using addresses from GitHub Variables:"
echo " OLD_ADDRESS: ${{ vars.OLD_ADDRESS }}"
echo " NEW_ADDRESS: ${{ vars.NEW_ADDRESS }}"
echo ""
if [ "${{ inputs.execution_mode }}" = "step-1-only" ] || [ "${{ inputs.execution_mode }}" = "full-transfer-with-delay" ]; then
if [ -z "${{ vars.NEW_ADDRESS }}" ]; then
echo "Error: NEW_ADDRESS variable is not set in GitHub Variables"
echo "Please configure NEW_ADDRESS in repository settings -> Variables"
exit 1
fi
fi
if [ -z "${{ vars.OLD_ADDRESS }}" ]; then
echo "Error: OLD_ADDRESS variable is not set in GitHub Variables"
echo "Please configure OLD_ADDRESS in repository settings -> Variables"
exit 1
fi
- name: Execute Step 1 - Grant Roles and Begin Transfer
if: inputs.execution_mode == 'step-1-only' || inputs.execution_mode == 'full-transfer-with-delay'
env:
ADMIN_PRIVATE_KEY: ${{ secrets.ADMIN_PRIVATE_KEY }}
CHAIN: ${{ matrix.network }}
RPC_URL: ${{ secrets.RPC_URL }}
OLD_ADDRESS: ${{ vars.OLD_ADDRESS }}
NEW_ADDRESS: ${{ vars.NEW_ADDRESS }}
run: |
echo "========================================="
echo "STEP 1: Grant Roles and Begin Transfer"
echo "========================================="
echo "Chain: $CHAIN"
echo "Old address: $OLD_ADDRESS"
echo "New address: $NEW_ADDRESS"
echo ""
make grant-roles-begin-transfer
- name: Wait for Delay Period
if: inputs.execution_mode == 'full-transfer-with-delay'
env:
CHAIN: ${{ matrix.network }}
RPC_URL: ${{ secrets.RPC_URL }}
run: |
echo "========================================="
echo "WAITING FOR DELAY PERIOD"
echo "========================================="
echo "Querying contract for delay schedule..."
# Get the scheduled timestamp from the contract
# This script will query the pendingDefaultAdmin and calculate wait time
cat > get_delay.sh << 'EOF'
#!/bin/bash
# Query RLCCrosschainToken or RLCLiquidityUnifier
if [ "$CHAIN" = "sepolia" ]; then
CONTRACT_ADDRESS="0x7198CA5eAeFE7416d4f3900b58Ff1bEA33771A65"
CONTRACT_NAME="RLCLiquidityUnifier"
else
CONTRACT_ADDRESS="0x9923eD3cbd90CD78b910c475f9A731A6e0b8C963"
CONTRACT_NAME="RLCCrosschainToken"
fi
echo "Contract: $CONTRACT_NAME at $CONTRACT_ADDRESS"
# Get pending admin info (returns address and uint48 schedule)
RESULT=$(cast call $CONTRACT_ADDRESS "pendingDefaultAdmin()(address,uint48)" --rpc-url $RPC_URL)
# Extract the timestamp (second value)
SCHEDULED_TIME=$(echo $RESULT | awk '{print $2}')
CURRENT_TIME=$(date +%s)
echo "Current timestamp: $CURRENT_TIME"
echo "Scheduled timestamp: $SCHEDULED_TIME"
# Calculate wait time (minimum required by contract)
WAIT_SECONDS=$((SCHEDULED_TIME - CURRENT_TIME))
# Add 1 second to ensure we're past the scheduled time
TOTAL_WAIT=$((WAIT_SECONDS + 1))
if [ $TOTAL_WAIT -le 0 ]; then
echo "✅ Delay period has already passed!"
echo "Proceeding immediately with Step 2..."
exit 0
fi
echo ""
echo "⏰ Delay period:"
echo " - Required wait: $WAIT_SECONDS seconds ($((WAIT_SECONDS / 60)) minutes)"
echo " - Safety buffer: 1 second"
echo " - Total wait: $TOTAL_WAIT seconds ($((TOTAL_WAIT / 60)) minutes)"
echo ""
echo "Waiting until: $(date -u -r $((SCHEDULED_TIME + 1)) '+%Y-%m-%d %H:%M:%S UTC')"
echo ""
# Sleep in chunks to show progress
INTERVAL=60 # Show progress every minute
ELAPSED=0
while [ $ELAPSED -lt $TOTAL_WAIT ]; do
REMAINING=$((TOTAL_WAIT - ELAPSED))
if [ $REMAINING -lt $INTERVAL ]; then
sleep $REMAINING
ELAPSED=$TOTAL_WAIT
else
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
echo "⏳ Progress: $((ELAPSED / 60))/$((TOTAL_WAIT / 60)) minutes elapsed..."
fi
done
echo ""
echo "✅ Delay period complete! Proceeding to Step 2..."
EOF
chmod +x get_delay.sh
./get_delay.sh
- name: Execute Step 2 - Accept Admin and Revoke Old Roles
if: inputs.execution_mode == 'step-2-only' || inputs.execution_mode == 'full-transfer-with-delay'
env:
NEW_ADMIN_PRIVATE_KEY: ${{ secrets.NEW_ADMIN_PRIVATE_KEY }}
CHAIN: ${{ matrix.network }}
RPC_URL: ${{ secrets.RPC_URL }}
OLD_ADDRESS: ${{ vars.OLD_ADDRESS }}
run: |
echo "========================================="
echo "STEP 2: Accept Admin and Revoke Old Roles"
echo "========================================="
echo "Chain: $CHAIN"
echo "Old address to revoke: $OLD_ADDRESS"
echo ""
make accept-admin-revoke-old
- name: Summary
run: |
echo ""
echo "========================================="
echo "SUMMARY"
echo "========================================="
if [ "${{ inputs.execution_mode }}" = "full-transfer-with-delay" ]; then
echo "✅ FULL TRANSFER COMPLETE on ${{ matrix.network }}"
echo ""
echo "Steps completed:"
echo " 1. ✅ Granted operational roles to new address"
echo " 2. ✅ Began admin transfer with delay period"
echo " 3. ✅ Waited for minimum contract delay period"
echo " 4. ✅ Accepted admin role with new address"
echo " 5. ✅ Revoked all roles from old address"
echo ""
echo "🎉 All roles have been transferred!"
echo "🔒 Old address has been completely removed from all contracts"
elif [ "${{ inputs.execution_mode }}" = "step-1-only" ]; then
echo "✅ STEP 1 COMPLETE on ${{ matrix.network }}"
echo ""
echo "⏰ Wait for the delay period to pass before running Step 2"
echo "📝 Next: Run this workflow again with execution_mode=step-2-only"
else
echo "✅ STEP 2 COMPLETE on ${{ matrix.network }}"
echo ""
echo "🎉 All roles have been transferred!"
echo "🔒 Old address has been completely removed from all contracts"
fi