Skip to content

Commit

Permalink
ZK-611: contract deployment environments (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
kroist authored Dec 12, 2024
1 parent 0cddb67 commit 60321d0
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 125 deletions.
21 changes: 14 additions & 7 deletions .github/workflows/_check-vars-and-secrets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ jobs:
if [[ \
-z '${{ vars.SHIELDER_CONTRACT_ADDRESS }}' || \
-z '${{ vars.KUSTOMIZE_VERSION }}' || \
-z '${{ vars.CI_TESTNET_ALICE_PUBLIC_KEY }} }}' || \
-z '${{ vars.CI_TESTNET_BOB_PUBLIC_KEY }} }}' || \
-z '${{ vars.CI_TESTNET_CHARLIE_PUBLIC_KEY }} }}' || \
-z '${{ vars.CI_TESTNET_TS_SDK_PUBLIC_KEY }} }}' || \
-z '${{ vars.CI_TESTNET_RELAYER_SIGNER_ADDRESSES }} }}' || \
-z '${{ vars.CI_TESTNET_FEE_DESTINATION }} }}'
-z '${{ vars.CI_TESTNET_ALICE_PUBLIC_KEY }}' || \
-z '${{ vars.CI_TESTNET_BOB_PUBLIC_KEY }}' || \
-z '${{ vars.CI_TESTNET_CHARLIE_PUBLIC_KEY }}' || \
-z '${{ vars.CI_TESTNET_TS_SDK_PUBLIC_KEY }}' || \
-z '${{ vars.CI_TESTNET_RELAYER_SIGNER_ADDRESSES }}' || \
-z '${{ vars.CI_TESTNET_FEE_DESTINATION }}' || \
-z '${{ vars.CI_TESTNET_STAGE_OWNER_ADDRESS }}' || \
-z '${{ vars.MAINNET_PROD_OWNER_ADDRESS }}'
]]; then
echo '!!! Some repository variables are either missing or empty.'
echo '!!! Please check either repository or organization settings.'
Expand Down Expand Up @@ -52,10 +54,15 @@ jobs:
-z '${{ secrets.NPM_PUBLISHING_KEY }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_DEV_RW_AWS_ACCESS_KEY_ID }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_DEV_RW_AWS_SECRET_ACCESS_KEY }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_STAGE_RW_AWS_ACCESS_KEY_ID }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_STAGE_RW_AWS_SECRET_ACCESS_KEY }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ADDRESSES_MAINNET_PROD_RW_AWS_ACCESS_KEY_ID }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ADDRESSES_MAINNET_PROD_RW_AWS_SECRET_ACCESS_KEY }}' || \
-z '${{ secrets.CONTRACTS_S3BUCKET_REGION }}' || \
-z '${{ secrets.CONTRACTS_S3BUCKET_NAME }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ARTIFACTS_RW_AWS_ACCESS_KEY_ID }}' || \
-z '${{ secrets.CONTRACTS_ZKOS_ARTIFACTS_RW_AWS_SECRET_ACCESS_KEY }}'
-z '${{ secrets.CONTRACTS_ZKOS_ARTIFACTS_RW_AWS_SECRET_ACCESS_KEY }}' || \
-z '${{ secrets.CI_MAINNET_DEPLOYER_PRIVATE_KEY }}'
]]; then
echo '!!! Some repository secrets are either missing or empty.'
echo '!!! Please check either repository or organization settings.'
Expand Down
161 changes: 161 additions & 0 deletions .github/workflows/manual-deploy-contract.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
---
name: "Manually Deploy contracts"

on:
workflow_dispatch:
inputs:
environment:
description: "Environment to deploy to"
required: true
default: "dev"
type: choice
options:
- "dev"
- "stage"
- "prod"

jobs:
deploy-contracts:
name: Deploy contracts on ${{ github.event.inputs.environment }}
runs-on: [self-hosted, Linux, X64, medium]
steps:
- name: GIT | Checkout
uses: actions/checkout@v4

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 18

- name: Prepare Rust env
uses: ./.github/actions/prepare-rust-env
with:
poseidon-gadget-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
zkos-circuits-private-key: ${{ secrets.ZKOS_CIRCUITS_SSH_PRIVATE_KEY }}

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1.2.0
with:
cache-key: custom-seed-coverage-${{ github.ref_name }}
cache-restore-keys: |-
contract-suite
version: nightly-31dd1f77fd9156d09836486d97963cec7f555343

- name: Install deps
run: make deps

# for "dev" we use default owner address, as it's not important
- name: Set environment-specific variables
run: |
if [ "${{ github.event.inputs.environment }}" == "dev" ]; then
echo "PRIVATE_KEY=${{ secrets.CI_TESTNET_DEPLOYER_PRIVATE_KEY }}" >> $GITHUB_ENV
echo "NETWORK=https://rpc.alephzero-testnet.gelato.digital" >> $GITHUB_ENV
echo "EXPLORER_URL=https://evm-explorer-testnet.alephzero.org/api" >> $GITHUB_ENV
elif [ "${{ github.event.inputs.environment }}" == "stage" ]; then
echo "OWNER_ADDRESS=${{ vars.CI_TESTNET_STAGE_OWNER_ADDRESS }}" >> $GITHUB_ENV
echo "PRIVATE_KEY=${{ secrets.CI_TESTNET_DEPLOYER_PRIVATE_KEY }}" >> $GITHUB_ENV
echo "NETWORK=https://rpc.alephzero-testnet.gelato.digital" >> $GITHUB_ENV
echo "EXPLORER_URL=https://evm-explorer-testnet.alephzero.org/api" >> $GITHUB_ENV
elif [ "${{ github.event.inputs.environment }}" == "prod" ]; then
echo "OWNER_ADDRESS=${{ vars.MAINNET_PROD_OWNER_ADDRESS }}" >> $GITHUB_ENV
echo "PRIVATE_KEY=${{ secrets.CI_MAINNET_DEPLOYER_PRIVATE_KEY }}" >> $GITHUB_ENV
echo "NETWORK=https://rpc.alephzero.raas.gelato.cloud" >> $GITHUB_ENV
echo "EXPLORER_URL=https://evm-explorer.alephzero.org/api" >> $GITHUB_ENV
else
echo "Invalid environment selected!" >&2
exit 1
fi
- name: Compile eth contracts
run: make compile-contracts

- name: Deploy contracts
run: |
make deploy-contracts
- name: Verify Shielder contract
run: ./scripts/verify-shielder.sh

- name: Upload Shielder abi to artifacts
uses: actions/upload-artifact@v4
with:
name: shielder_abi
path: artifacts/Shielder.sol/Shielder.json
include-hidden-files: true
retention-days: 14

- name: Upload Shielder contract address to artifacts
uses: actions/upload-artifact@v4
with:
name: shielder_address
path: shielder_address.txt
include-hidden-files: true
retention-days: 14

- name: Create a JSON with address
run: |
echo -n $(cat shielder_address.txt | xargs) | jq -Rs '{ shielder: . }' \
> evm_addresses.json
- name: Prepare contract_spec JSON
uses: Cardinal-Cryptography/github-actions/generate-contract-spec@v6
with:
src-files: |-
evm_addresses.json|evm_
dst-file: contract_spec.json
spec-version: "0.1"
contract-version: "${{ github.sha }}"

- name: Add block numbers to contract_spec JSON
shell: bash
run: |
cat contract_spec.json | \
jq ".start_blocks = { evm: \"$(cat shielder_block_number.txt)\" }" \
> contract_spec_with_block_numbers.json
cat contract_spec_with_block_numbers.json
# yamllint disable rule:line-length
- name: Store addresses in S3 bucket (dev)
if: ${{ inputs.environment == 'dev' }}
shell: bash
env:
AWS_REGION: ${{ secrets.CONTRACTS_S3BUCKET_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_DEV_RW_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_DEV_RW_AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 cp contract_spec_with_block_numbers.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/addresses/testnet/dev.json
aws s3 cp broadcast/Shielder.s.sol/2039/run-latest.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/addresses/testnet/dev-broadcast.json
# yamllint disable rule:line-length
- name: Store addresses in S3 bucket (stage)
if: ${{ inputs.environment == 'stage' }}
shell: bash
env:
AWS_REGION: ${{ secrets.CONTRACTS_S3BUCKET_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_STAGE_RW_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CONTRACTS_ZKOS_ADDRESSES_TESTNET_STAGE_RW_AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 cp contract_spec_with_block_numbers.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/addresses/testnet/stage.json
aws s3 cp broadcast/Shielder.s.sol/2039/run-latest.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/addresses/testnet/stage-broadcast.json
# yamllint disable rule:line-length
- name: Store addresses in S3 bucket (prod)
if: ${{ inputs.environment == 'prod' }}
shell: bash
env:
AWS_REGION: ${{ secrets.CONTRACTS_S3BUCKET_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.CONTRACTS_ZKOS_ADDRESSES_MAINNET_PROD_RW_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CONTRACTS_ZKOS_ADDRESSES_MAINNET_PROD_RW_AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 cp contract_spec_with_block_numbers.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/addresses/mainnet/prod.json
aws s3 cp broadcast/Shielder.s.sol/41455/run-latest.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/addresses/mainnet/prod-broadcast.json
- name: Store artifact in S3 bucket
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CONTRACTS_ZKOS_ARTIFACTS_RW_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CONTRACTS_ZKOS_ARTIFACTS_RW_AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.CONTRACTS_S3BUCKET_REGION }}
run: |
aws s3 cp artifacts/Shielder.sol/Shielder.json s3://${{ secrets.CONTRACTS_S3BUCKET_NAME }}/zkos/artifacts/${{ github.sha }}/eth_shielder/
105 changes: 0 additions & 105 deletions .github/workflows/manual-testnet-deploy-contract.yml

This file was deleted.

5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
NETWORK ?= anvil
PRIVATE_KEY ?= 0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659 # pkey of the dev account `0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E` prefunded with ETH on all networks
OWNER_ADDRESS ?= $(shell cast wallet address $(PRIVATE_KEY))

.PHONY: help
help: # Show help for each of the Makefile recipes.
Expand Down Expand Up @@ -50,9 +51,9 @@ deploy-contracts: # Deploy solidity contracts
deploy-contracts:
ifeq ($(NETWORK),anvil)
$(eval PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80) \
PRIVATE_KEY=$(PRIVATE_KEY) forge script DeployShielderScript --broadcast --rpc-url anvil --sender $(shell cast wallet address $(PRIVATE_KEY))
PRIVATE_KEY=$(PRIVATE_KEY) OWNER_ADDRESS=$(OWNER_ADDRESS) forge script DeployShielderScript --broadcast --rpc-url anvil --sender $(shell cast wallet address $(PRIVATE_KEY))
else
PRIVATE_KEY=$(PRIVATE_KEY) forge script DeployShielderScript --broadcast --rpc-url $(NETWORK) --sender $(shell cast wallet address $(PRIVATE_KEY))
PRIVATE_KEY=$(PRIVATE_KEY) OWNER_ADDRESS=$(OWNER_ADDRESS) forge script DeployShielderScript --broadcast --rpc-url $(NETWORK) --sender $(shell cast wallet address $(PRIVATE_KEY))
endif

.PHONY: generate-poseidon-contracts
Expand Down
9 changes: 6 additions & 3 deletions scripts/Shielder.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ contract DeployShielderScript is Script {
function run() external {
uint256 privateKey = vm.envUint("PRIVATE_KEY");

address owner = vm.addr(privateKey);
console2.log("Using", owner, "as broadcaster");
address owner = vm.envAddress("OWNER_ADDRESS");
address broadcaster = vm.addr(privateKey);
console2.log("Using", broadcaster, "as broadcaster");

vm.startBroadcast(privateKey);

Expand All @@ -34,7 +35,9 @@ contract DeployShielderScript is Script {
Shielder shielder = Shielder(proxy);

console2.log("Shielder deployed at:", address(shielder));
shielder.unpause();
if (owner == broadcaster) {
shielder.unpause();
}

vm.stopBroadcast();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

set -euo pipefail

LIBRARIES=$(cat broadcast/Shielder.s.sol/2039/run-latest.json | jq -r '.libraries | map("--libraries " + .) | join(" ")')
IMPL_CONTRACT_ADDRESS=$(cat broadcast/Shielder.s.sol/2039/run-latest.json \
CHAIN_ID=$(cast chain-id --rpc-url ${NETWORK})

LIBRARIES=$(cat broadcast/Shielder.s.sol/${CHAIN_ID}/run-latest.json | jq -r '.libraries | map("--libraries " + .) | join(" ")')
IMPL_CONTRACT_ADDRESS=$(cat broadcast/Shielder.s.sol/${CHAIN_ID}/run-latest.json \
| jq -r '.transactions | .[] | select(.transactionType=="CREATE") | select(.contractName=="Shielder") | .contractAddress')
PROXY_CONTRACT_ADDRESS=$(cat broadcast/Shielder.s.sol/2039/run-latest.json \
PROXY_CONTRACT_ADDRESS=$(cat broadcast/Shielder.s.sol/${CHAIN_ID}/run-latest.json \
| jq -r '.transactions | .[] | select(.transactionType=="CREATE") | select(.contractName=="ERC1967Proxy") | .contractAddress')
PROXY_DEPLOYMENT_TX_HASH=$(cat broadcast/Shielder.s.sol/2039/run-latest.json \
PROXY_DEPLOYMENT_TX_HASH=$(cat broadcast/Shielder.s.sol/${CHAIN_ID}/run-latest.json \
| jq '.transactions | .[] | select(.transactionType=="CREATE") | select(.contractName=="ERC1967Proxy") | .hash')
PROXY_BLOCK_NUMBER=$(cast to-dec $(cat broadcast/Shielder.s.sol/2039/run-latest.json \
PROXY_BLOCK_NUMBER=$(cast to-dec $(cat broadcast/Shielder.s.sol/${CHAIN_ID}/run-latest.json \
| jq -r ".receipts | .[] | select(.transactionHash==${PROXY_DEPLOYMENT_TX_HASH}) | .blockNumber"))

echo ${PROXY_CONTRACT_ADDRESS} > shielder_address.txt
echo ${PROXY_BLOCK_NUMBER} > shielder_block_number.txt

forge verify-contract --rpc-url https://rpc.alephzero-testnet.gelato.digital \
--verifier blockscout --verifier-url https://evm-explorer-testnet.alephzero.org/api \
forge verify-contract --rpc-url ${NETWORK} \
--verifier blockscout --verifier-url ${EXPLORER_URL} \
${LIBRARIES} \
${IMPL_CONTRACT_ADDRESS} \
contracts/Shielder.sol:Shielder
4 changes: 3 additions & 1 deletion tooling-e2e-tests/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ mtzero() {
####################################################################################################
deploy_contracts() {
SHIELDER_CONTRACT_ADDRESS=$(
PRIVATE_KEY="${DEPLOYER_PRIVATE_KEY}" forge script DeployShielderScript \
PRIVATE_KEY="${DEPLOYER_PRIVATE_KEY}" \
OWNER_ADDRESS="$(cast wallet address ${DEPLOYER_PRIVATE_KEY})" \
forge script DeployShielderScript \
--rpc-url "${NODE_RPC_URL}" \
--broadcast \
--non-interactive \
Expand Down

0 comments on commit 60321d0

Please sign in to comment.