Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add automated building and deployment flows for Omni contracts on NEAR and EVM #155

Merged
merged 19 commits into from
Dec 25, 2024
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
72 changes: 72 additions & 0 deletions .github/workflows/build-contracts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Build Contracts

on:
pull_request:
types: [closed]
branches: [main]


jobs:
build:
name: Build Contracts
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
strategy:
matrix:
platform: [evm, near]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
if: matrix.platform == 'evm'
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'yarn'
cache-dependency-path: evm/yarn.lock

- name: Setup Rust toolchain
if: matrix.platform == 'near' || matrix.platform == 'solana'
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.79.0
target: wasm32-unknown-unknown

- name: Install NEAR CLI RS
if: matrix.platform == 'near'
run: |
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/near-cli-rs/releases/download/v0.7.4/near-cli-rs-installer.sh | sh

- name: Install Docker
if: matrix.platform == 'near'
uses: docker/setup-buildx-action@v2

- name: Install Solana CLI
if: matrix.platform == 'solana'
run: |
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
export PATH="/home/runner/.local/share/solana/install/active_release/bin:$PATH"

- name: Install Anchor
if: matrix.platform == 'solana'
run: |
cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli

- name: Build Contracts
run: |
if [ "${{ matrix.platform }}" == "evm" ]; then
make -C ${{ github.workspace }}/e2e-testing/ evm-build
elif [ "${{ matrix.platform }}" == "near" ]; then
make -C ${{ github.workspace }}/e2e-testing/ near-build
elif [ "${{ matrix.platform }}" == "solana" ]; then
make -C ${{ github.workspace }}/e2e-testing/ solana-build
fi

- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.platform }}-artifacts
path: |
${{ github.workspace }}/e2e-testing/${{ matrix.platform }}_artifacts
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.DS_Store
**/target
.history
node_modules
node_modules
17 changes: 17 additions & 0 deletions e2e-testing/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
evm_artifacts/
near_artifacts/
solana_artifacts/
evm_deploy_results/
near_deploy_results/
solana_deploy_results/


evm_scripts/build/
evm_scripts/cache/
evm_scripts/coverage/
evm_scripts/coverage.json
evm_scripts/.openzeppelin/
evm_scripts/node_modules/
evm_scripts/.env
evm_scripts/typechain-types/
evm_scripts/dist/
190 changes: 190 additions & 0 deletions e2e-testing/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
.PHONY: evm-compile evm-scripts-build

.DELETE_ON_ERROR:

TESTING_ROOT := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

TIMESTAMP := $(shell date -u +%Y%m%d-%H%M%S)

EVM_DIR := $(TESTING_ROOT)/../evm
EVM_SCRIPT_DIR := $(TESTING_ROOT)/evm_scripts
ETHEREUM_DEPLOY_RESULTS_DIR := $(TESTING_ROOT)/ethereum_deploy_results

NEAR_DIR := $(TESTING_ROOT)/../near
NEAR_DEPLOY_RESULTS_DIR := $(TESTING_ROOT)/near_deploy_results

SOLANA_DIR := $(TESTING_ROOT)/../solana
SOLANA_DEPLOY_RESULTS_DIR := $(TESTING_ROOT)/solana_deploy_results

NEAR_BRIDGE_ID_FILE := $(NEAR_DEPLOY_RESULTS_DIR)/omni_bridge.json

##########################################################
# EVM
##########################################################

EVM_COMPILE_STAMP := $(TESTING_ROOT)/.evm-compile.stamp
EVM_ARTIFACTS_DIR := $(TESTING_ROOT)/evm_artifacts
EVM_SCRIPT_COMPILE_STAMP := $(TESTING_ROOT)/.evm-scripts-compile.stamp

EVM_NETWORKS := sepolia arbitrumSepolia baseSepolia

EVM_DEPLOY_RESULTS_DIR := $(TESTING_ROOT)/evm_deploy_results

DEPLOY_EVM_TOKEN_IMPL = yarn --silent --cwd $(EVM_DIR) hardhat deploy-token-impl --network $(1)
DEPLOY_EVM_OMNI_BRIDGE_CONTRACT = yarn --silent --cwd $(EVM_DIR) hardhat deploy-bridge-token-factory --network $(1) --bridge-token-impl $(2) --near-bridge-account-id $(3)
DEPLOY_EVM_FAKE_PROVER = yarn --silent --cwd $(EVM_DIR) hardhat deploy-fake-prover --network $(1)
DEPLOY_EVM_ENEAR_PROXY = yarn --silent --cwd $(EVM_DIR) hardhat deploy-e-near-proxy --network $(1) --enear $(2)

DEPLOY_EVM_BYTECODE = yarn --silent --cwd $(EVM_SCRIPT_DIR) hardhat deploy-bytecode --network $(1) --bytecode $(2)
DEPLOY_EVM_TEST_TOKEN = yarn --silent --cwd $(EVM_SCRIPT_DIR) hardhat deploy-test-token --network $(1) --name $(2) --symbol $(3)

ENEAR_CREATION_TEMPLATE_FILE := $(TESTING_ROOT)/bin/eNear_creation.template

$(EVM_DEPLOY_RESULTS_DIR):
mkdir -p $@

evm-build: $(EVM_COMPILE_STAMP)
$(EVM_COMPILE_STAMP):
@echo "Compiling EVM contracts"
mkdir -p $(EVM_ARTIFACTS_DIR) && \
yarn --cwd $(EVM_DIR) install --frozen-lockfile && \
yarn --cwd $(EVM_DIR) hardhat compile && \
cp -r $(EVM_DIR)/build/* $(EVM_ARTIFACTS_DIR)
touch $@

evm-scripts-build: $(EVM_SCRIPT_COMPILE_STAMP)
$(EVM_SCRIPT_COMPILE_STAMP):
@echo "Compiling EVM scripts"
yarn --cwd $(EVM_SCRIPT_DIR) install && \
yarn --cwd $(EVM_SCRIPT_DIR) hardhat compile
touch $@

# Arguments:
# $(1) - the network name
define generate_evm_deploy_rules

.PHONY: $(1)-deploy-fake-prover $(1)-deploy-enear $(1)-deploy-enear-proxy $(1)-deploy-bridge $(1)-deploy-token-impl $(1)-deploy-test-token

$(1)_DEPLOY_RESULTS_DIR := $(EVM_DEPLOY_RESULTS_DIR)/$(1)

$$($(1)_DEPLOY_RESULTS_DIR): | $(EVM_DEPLOY_RESULTS_DIR)
mkdir -p $$@

$(1)-deploy: $(1)-deploy-bridge $(1)-deploy-enear-proxy $(1)-deploy-test-token

$(1)_BRIDGE_CONTRACT_ADDRESS_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/omni_bridge.json
$(1)_TOKEN_IMPL_ADDRESS_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/token_factory.json
$(1)_FAKE_PROVER_ADDRESS_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/fake_prover.json

$(1)_ENEAR_ADDRESS_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/eNear.json
$(1)_ENEAR_PROXY_ADDRESS_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/eNearProxy.json
$(1)_ENEAR_CREATION_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/eNear_creation

$(1)_TEST_TOKEN_ADDRESS_FILE := $$($(1)_DEPLOY_RESULTS_DIR)/test_token.json

$(1)-deploy-fake-prover: $$($(1)_FAKE_PROVER_ADDRESS_FILE)
$$($(1)_FAKE_PROVER_ADDRESS_FILE): $(EVM_COMPILE_STAMP) | $$($(1)_DEPLOY_RESULTS_DIR)
$$(call DEPLOY_EVM_FAKE_PROVER,$(1)) 2>/dev/stderr 1> $$@

$(1)-deploy-enear: $$($(1)_ENEAR_ADDRESS_FILE)
$$($(1)_ENEAR_ADDRESS_FILE): $$($(1)_ENEAR_CREATION_FILE) $(EVM_SCRIPT_COMPILE_STAMP) | $$($(1)_DEPLOY_RESULTS_DIR)
$$(call DEPLOY_EVM_BYTECODE,$(1),$$($(1)_ENEAR_CREATION_FILE)) 2>/dev/stderr 1> $$@

$(1)-deploy-enear-proxy: $$($(1)_ENEAR_PROXY_ADDRESS_FILE)
$$($(1)_ENEAR_PROXY_ADDRESS_FILE): $$($(1)_ENEAR_ADDRESS_FILE) $(EVM_COMPILE_STAMP) | $$($(1)_DEPLOY_RESULTS_DIR)
$$(call DEPLOY_EVM_ENEAR_PROXY,$(1),$$(shell cat $$($(1)_ENEAR_ADDRESS_FILE) | jq -r .contractAddress)) 2>/dev/stderr 1> $$@

$(1)-deploy-bridge: $$($(1)_BRIDGE_CONTRACT_ADDRESS_FILE)
$$($(1)_BRIDGE_CONTRACT_ADDRESS_FILE): $$($(1)_TOKEN_IMPL_ADDRESS_FILE) $(NEAR_BRIDGE_ID_FILE) $(EVM_COMPILE_STAMP) | $$($(1)_DEPLOY_RESULTS_DIR)
$$(call DEPLOY_EVM_OMNI_BRIDGE_CONTRACT,$(1),$$(shell cat $$($(1)_TOKEN_IMPL_ADDRESS_FILE) | jq -r .tokenImplAddress),$$(shell cat $(NEAR_BRIDGE_ID_FILE) | jq -r .contract_id)) 2>/dev/stderr 1> $$@

$(1)-deploy-token-impl: $$($(1)_TOKEN_IMPL_ADDRESS_FILE)
$$($(1)_TOKEN_IMPL_ADDRESS_FILE): $(EVM_COMPILE_STAMP) | $$($(1)_DEPLOY_RESULTS_DIR)
$$(call DEPLOY_EVM_TOKEN_IMPL,$(1)) 2>/dev/stderr 1> $$@

$$($(1)_ENEAR_CREATION_FILE): $(ENEAR_CREATION_TEMPLATE_FILE) $$($(1)_FAKE_PROVER_ADDRESS_FILE) | $$($(1)_DEPLOY_RESULTS_DIR)
cat $$< | \
sed "s/<PROVER_ADDRESS>/$$(shell cat $$($(1)_FAKE_PROVER_ADDRESS_FILE) | jq -r .fakeProverAddress | sed 's/^0x//')/" > $$@


$(1)-deploy-test-token: $$($(1)_TEST_TOKEN_ADDRESS_FILE)
$$($(1)_TEST_TOKEN_ADDRESS_FILE): $(EVM_SCRIPT_COMPILE_STAMP) | $$($(1)_DEPLOY_RESULTS_DIR)
$$(call DEPLOY_EVM_TEST_TOKEN,$(1),E2ETestToken-$(TIMESTAMP),E2ETT-$(TIMESTAMP)) 2>/dev/stderr 1> $$@

endef

$(foreach network,$(EVM_NETWORKS),$(eval $(call generate_evm_deploy_rules,$(network))))

##########################################################
# NEAR
##########################################################

NEAR_BINARY_DIR := $(TESTING_ROOT)/near_artifacts

.PHONY: near-build near-deploy

# List all expected WASM binaries
NEAR_BINARIES := evm_prover.wasm omni_bridge.wasm omni_prover.wasm omni_token.wasm token_deployer.wasm wormhole_omni_prover_proxy.wasm mock_token.wasm
NEAR_BINARY_PATHS := $(addprefix $(NEAR_BINARY_DIR)/,$(NEAR_BINARIES))

NEAR_BUILD_STAMP := $(TESTING_ROOT)/.near-build.stamp

DEPLOY_RESULTS := $(patsubst $(NEAR_BINARY_DIR)/%.wasm,$(NEAR_DEPLOY_RESULTS_DIR)/%.json,$(NEAR_BINARY_PATHS))

near-deploy: $(DEPLOY_RESULTS)

$(NEAR_DEPLOY_RESULTS_DIR):
mkdir -p $@

near-build: $(NEAR_BUILD_STAMP)
$(NEAR_BUILD_STAMP):
$(NEAR_DIR)/build.sh --output-dir $(NEAR_BINARY_DIR)
touch $@

# Arguments:
# $(1) - the path to the binary file
define generate_near_deploy_rules

$(NEAR_DEPLOY_RESULTS_DIR)/$(basename $(notdir $(1))).json: $(1) | $(NEAR_DEPLOY_RESULTS_DIR)
./scripts/deploy-near-contract.sh $(1) $$@ $$(basename $$(notdir $(1)))-$(TIMESTAMP).testnet

$(1): $(NEAR_BUILD_STAMP)

endef

$(foreach binary,$(NEAR_BINARY_PATHS),$(eval $(call generate_near_deploy_rules,$(binary))))


########################################
# Solana
########################################

SOLANA_BUILD_STAMP := $(TESTING_ROOT)/.solana-build.stamp
SOLANA_ARTIFACTS_DIR := $(TESTING_ROOT)/solana_artifacts

SOLANA_PROGRAMS := bridge_token_factory
SOLANA_PROGRAMS_KEYPAIRS := $(foreach program,$(SOLANA_PROGRAMS),$(SOLANA_DIR)/$(program)/target/deploy/$(program)-keypair.json)
SOLANA_PROGRAMS_BINARIES := $(foreach program,$(SOLANA_PROGRAMS),$(SOLANA_ARTIFACTS_DIR)/$(program)/target/deploy/$(program).so)

solana-build: $(SOLANA_BUILD_STAMP)
$(SOLANA_BUILD_STAMP): $(SOLANA_PROGRAMS_KEYPAIRS) $(SOLANA_PROGRAMS_BINARIES)
touch $@

# Arguments:
# $(1) - the program name
define generate_solana_build_rules

$(SOLANA_DIR)/$(1)/target/deploy/$(1)-keypair.json: $(TESTING_ROOT)/$(1)-keypair.json
mkdir -p $$(dir $$@) && \
cp $$< $$@

$(SOLANA_ARTIFACTS_DIR)/$(1)/target/deploy/$(1).so: $(SOLANA_DIR)/$(1)/target/deploy/$(1)-keypair.json
mkdir -p $(SOLANA_ARTIFACTS_DIR)/$(1) && \
cd $(SOLANA_DIR)/$(1) && \
anchor build && \
cp -r $(SOLANA_DIR)/$(1)/target/* $(SOLANA_ARTIFACTS_DIR)/$(1)

endef

$(foreach program,$(SOLANA_PROGRAMS),$(eval $(call generate_solana_build_rules,$(program))))

63 changes: 63 additions & 0 deletions e2e-testing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# End-to-end testing

## Prerequisites

- yarn
- cargo
- [NEAR CLI RS](https://github.com/near/near-cli-rs)
- docker
- [Solana CLI and Anchor](https://solana.com/docs/intro/installation)
- Bridge SDK CLI: `cargo install --git https://github.com/Near-One/bridge-sdk-rs/ bridge-cli`

## Using the Makefile

The `Makefile` in this project is designed to automate the deployment and compilation processes for both EVM and NEAR environments. It provides a set of predefined rules that can be executed to perform specific tasks, such as compiling contracts, deploying them to various networks, and setting up necessary infrastructure.

### Common Tasks

- **Compile EVM Contracts**: To compile the EVM contracts, run:
```bash
make evm-compile
```

- **Deploy to EVM Networks**: To deploy contracts to a specific EVM network, use the following pattern:
```bash
make <network>-deploy
```
Replace `<network>` with the desired network name, such as `sepolia` or `arbitrumSepolia`.

- **Build NEAR Contracts**: To build the NEAR contracts, execute:
```bash
make near-build
```

- **Deploy NEAR Contracts**: To deploy NEAR contracts, run:
```bash
make near-deploy
```

These tasks automate the process of setting up the testing environment, ensuring that all necessary components are compiled and deployed correctly.

### Additional Requirements

- **Private Key Requirement**: For Ethereum deployment, ensure that you add your `EVM_PRIVATE_KEY` to the `./evm/.env` file. This key is necessary for authenticating transactions on the Ethereum network.

- **Solana Keypair Requirement**: For Solana bulding and deployment, ensure that for every program you have a keypair in `.e2e-testing/` directory in the format of `<program_name>-keypair.json`. However, this key pair is secret and should not be shared.

### Deployment Results

- **Storage of Results**: The addresses of deployed contracts are stored in JSON files in their corresponding locations. For example, the token factory deployed on the `arbitrumSepolia` network will be stored in `evm_deploy_results/arbitrumSepolia/token_factory.json`. This is done to reuse these addresses across different runs of the tests.

### General Working Principles

- **Phony Targets**: The `Makefile` uses `.PHONY` targets to define tasks that do not correspond to actual files. This ensures that these tasks are always executed when called, regardless of the presence of files with the same name.

- **Variables**: The `Makefile` defines several variables to manage paths and configurations, such as `TESTING_ROOT`, `EVM_DIR`, and `NEAR_DIR`. These variables help in organizing the file structure and making the `Makefile` adaptable to different environments.

- **Rule Expansion**: The `Makefile` uses a combination of static and dynamic rule definitions. Dynamic rules are generated using the `define` directive, which allows for the creation of rules based on the networks specified in the `EVM_NETWORKS` variable. This approach reduces redundancy and makes it easy to add support for additional networks.

- **Dependencies**: Each target in the `Makefile` specifies its dependencies, ensuring that all necessary steps are completed before executing a task. For example, deploying a contract requires that it is compiled first.

- **Command Execution**: The `Makefile` uses shell commands to execute tasks, such as running `yarn` for EVM contract compilation and deployment, and custom scripts for NEAR contract deployment.

In order to see which commands will be executed without actually executing them, you can add `--dry-run` to the command.
1 change: 1 addition & 0 deletions e2e-testing/bin/eNear_creation.template

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions e2e-testing/evm_scripts/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
INFURA_API_KEY=
EVM_PRIVATE_KEY=
Loading
Loading