diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9c0f6058db..f997dd9e02 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,7 +59,14 @@ jobs: command: | echo "Running Build Tests" make clean - make test + make test-coverage + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + file: coverage.out + token: ${{ secrets.CODECOV_TOKEN }} + slug: zeta-chain/node - name: Build zetacored and zetaclientd env: @@ -77,7 +84,7 @@ jobs: shell: bash run: rm -rf * - smoke-test: + e2e-test: runs-on: buildjet-4vcpu-ubuntu-2204 timeout-minutes: 25 steps: @@ -120,12 +127,12 @@ jobs: cd contrib/localnet/ docker compose up -d zetacore0 zetacore1 zetaclient0 zetaclient1 eth bitcoin - - name: Run Smoke Test + - name: Run E2E Test run: | cd contrib/localnet docker-compose up orchestrator --exit-code-from orchestrator if [ $? -ne 0 ]; then - echo "Smoke Test Failed" + echo "E2E Test Failed" exit 1 fi diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 04988adeb0..277bc9e654 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -216,7 +216,14 @@ jobs: command: | echo "Running Build Tests" make clean - make test + make test-coverage + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + file: coverage.out + token: ${{ secrets.CODECOV_TOKEN }} + slug: zeta-chain/node - name: Build zetacored and zetaclientd if: ${{ github.event.inputs.skip_checks != 'true' }} diff --git a/Dockerfile b/Dockerfile index d2fe91c032..8785a09ef5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,9 @@ +# Purpose: This Dockerfile creates an environment for running ZetaChain +# It contains: +# - zetacored: the ZetaChain node binary +# - zetaclientd: the ZetaChain client binary for observers +# - zetae2e: the ZetaChain end-to-end tests CLI + FROM golang:1.20-alpine3.18 ENV GOPATH /go diff --git a/Dockerfile-release b/Dockerfile-release deleted file mode 100644 index 1d869e73fe..0000000000 --- a/Dockerfile-release +++ /dev/null @@ -1,40 +0,0 @@ -FROM golang:1.20-alpine3.18 as builder - -ENV GOPATH /go -ENV GOOS=linux -ENV CGO_ENABLED=1 - -WORKDIR /go/delivery/zeta-node - -RUN apk update && \ - apk --no-cache add git make build-base jq openssh libusb-dev linux-headers bash curl tmux - -COPY go.mod . -COPY go.sum . - -RUN --mount=type=cache,target=/root/.cache/go-build \ - go mod download - -COPY . . - -RUN --mount=type=cache,target=/root/.cache/go-build \ - make install - -RUN cp /go/bin/zetaclientd /usr/local/bin -RUN cp /go/bin/zetacored /usr/local/bin -RUN cp /go/bin/smoketest /usr/local/bin - -#BUILD MAIN BINARY IMAGE -FROM golang:1.20-alpine - -RUN apk --no-cache add jq bash curl wget nano tmux - -COPY --chmod=765 --from=builder /usr/local/bin/zetaclientd /usr/local/bin/zetaclientd -COPY --chmod=765 --from=builder /usr/local/bin/zetacored /usr/local/bin/zetacored - -WORKDIR /root/zetachain/ - -EXPOSE 26657 -EXPOSE 26656 -EXPOSE 1317 -EXPOSE 9090 diff --git a/Dockerfile-versioned-source b/Dockerfile-upgrade similarity index 80% rename from Dockerfile-versioned-source rename to Dockerfile-upgrade index f1089f4959..b9344981a4 100644 --- a/Dockerfile-versioned-source +++ b/Dockerfile-upgrade @@ -1,11 +1,14 @@ FROM golang:1.20-alpine3.18 +# Purpose: This Dockerfile creates an environment for performing an upgrade test on ZetaChain +# It contains the ZetaChain and ZetaClient binaries for two different versions of ZetaChain +# One is specified with the old_version argument and the other is the current source code +# The image also contains the cosmovisor binary for running the upgrade test + ENV GOPATH /go ENV GOOS=linux ENV CGO_ENABLED=1 -ARG old_version - RUN apk --no-cache add git make build-base jq openssh libusb-dev linux-headers bash curl tmux RUN ssh-keygen -b 2048 -t rsa -f /root/.ssh/localtest.pem -q -N "" @@ -17,6 +20,7 @@ WORKDIR /go/delivery/zeta-node RUN mkdir -p $GOPATH/bin/old RUN mkdir -p $GOPATH/bin/new +ARG OLD_VERSION=v12.2.1 ENV NEW_VERSION=v13 # Build new release from the current source @@ -33,7 +37,7 @@ RUN cp $GOPATH/bin/zetaclientd $GOPATH/bin/new/ RUN git clone https://github.com/zeta-chain/node.git RUN cd node && git fetch -RUN cd node && git checkout ${old_version} +RUN cd node && git checkout ${OLD_VERSION} RUN cd node && make install RUN cp $GOPATH/bin/zetacored $GOPATH/bin/old/ RUN cp $GOPATH/bin/zetaclientd $GOPATH/bin/old/ diff --git a/Dockerfile-versioned b/Dockerfile-versioned deleted file mode 100644 index 96e8c0e88e..0000000000 --- a/Dockerfile-versioned +++ /dev/null @@ -1,66 +0,0 @@ -FROM golang:1.20-alpine3.18 - -ENV GOPATH /go -ENV GOOS=linux -ENV CGO_ENABLED=1 - -ARG old_version -ARG new_version - -RUN apk --no-cache add git make build-base jq openssh libusb-dev linux-headers bash curl tmux -RUN ssh-keygen -b 2048 -t rsa -f /root/.ssh/localtest.pem -q -N "" - -WORKDIR /go/delivery/zeta-node - -RUN mkdir -p $GOPATH/bin/old -RUN mkdir -p $GOPATH/bin/new - -ENV NEW_VERSION=${new_version} - -# Checkout and build new binary -RUN git clone https://github.com/zeta-chain/node.git -RUN cd node && git fetch -RUN cd node && git checkout ${new_version} -RUN cd node && make install -RUN cd node && make install-smoketest -RUN cp $GOPATH/bin/zetacored $GOPATH/bin/new/ -RUN cp $GOPATH/bin/zetaclientd $GOPATH/bin/new/ -RUN cp $GOPATH/bin/smoketest $GOPATH/bin/new/ - -# Checkout and build old binary -RUN cd node && git checkout ${old_version} -RUN cd node && make install -RUN cd node && make install-smoketest -RUN cp $GOPATH/bin/zetacored $GOPATH/bin/old/ -RUN cp $GOPATH/bin/zetaclientd $GOPATH/bin/old/ -RUN cp $GOPATH/bin/smoketest $GOPATH/bin/old/ - -RUN git clone https://github.com/zeta-chain/cosmos-sdk.git -RUN cd cosmos-sdk && git checkout zetavisor-v0.1.5 -RUN cd cosmos-sdk/cosmovisor && make zetavisor - -RUN ssh-keygen -A -WORKDIR /root - -RUN cp /root/.ssh/localtest.pem.pub /root/.ssh/authorized_keys - -RUN cp /go/bin/zetaclientd /usr/local/bin -RUN cp /go/bin/zetacored /usr/local/bin -RUN cp /go/bin/smoketest /usr/local/bin -RUN cp /go/bin/zetavisor /usr/local/bin - -COPY contrib/localnet/scripts /root -COPY contrib/localnet/preparams /root/preparams -COPY contrib/localnet/ssh_config /root/.ssh/config -COPY contrib/localnet/zetacored /root/zetacored -COPY contrib/localnet/tss /root/tss - -RUN chmod 755 /root/*.sh -RUN chmod 700 /root/.ssh -RUN chmod 600 /root/.ssh/* - -WORKDIR /usr/local/bin -ENV SHELL /bin/sh -EXPOSE 22 - -ENTRYPOINT ["/usr/sbin/sshd", "-D"] diff --git a/LOCAL_TESTING.md b/LOCAL_TESTING.md new file mode 100644 index 0000000000..c127aa0e7d --- /dev/null +++ b/LOCAL_TESTING.md @@ -0,0 +1,205 @@ +# ZetaChain Localnet Development & Testing Environment + +ZetaChain localnet development and testing environment is divided into three different directories: + +- [localnet](./contrib/localnet/README.md): a set of Docker images and script for spinning up a localnet. +- [e2e](./e2e/README.md): a set of Go packages for end-to-end testing between ZetaChain and other blockchains. +- [zetae2e](./cmd/zetae2e/README.md): a CLI tool using `e2e` for running end-to-end tests. + +A description of each directory is provided in the respective README files. + +## Running E2E tests + +### Build zetanode +```bash +$ make zetanode +``` + +This Makefile rule builds the zetanode image. **Rebuild if zetacored/zetaclientd code is updated**. +```bash +# in zeta-node/ +$ docker build -t zetanode . +``` + +### Run e2e tests + +Now we have built all the docker images, we can run the e2e test with make command: +```bash +# in zeta-node/ +make start-e2e-test +``` + +### Run upgrade tests + +Upgrade tests run the E2E tests with an older version, upgrade the nodes to the new version, and run the E2E tests again. +This allows testing the upgrade process with a populated state. + +Before running the upgrade tests, the versions must be specified in `Dockefile-upgrade`: + +```dockerfile +ARG OLD_VERSION=v{old_major_version}.{old_minor_version}.{old_patch_version} +ENV NEW_VERSION=v{new_major_version} +``` +The new version must match the version specified in `app/setup_handlers.go` + +NOTE: We only specify the major version for `NEW_VERSION` since we use major version only for chain upgrade. Semver is needed for `OLD_VERSION` because we use this value to fetch the release tag from the GitHub repository. + +The upgrade tests can be run with the following command: +```bash +# in zeta-node/ +make start-upgrade-test +``` + +### Run stress tests + +Stress tests run the E2E tests with a larger number of nodes and clients to test the performance of the network. +It also stresses the network by sending a large number of cross-chain transactions. + +The stress tests can be run with the following command: +```bash +# in zeta-node/ +make start-stress-test +``` + +### Test logs + +For all tests, the most straightforward logs to observe are the orchestrator logs. +If everything works fine, it should finish without panic. + +The logs can be observed with the following command: +```bash +# in zeta-node/contrib/localnet/orchestrator +$ docker logs -f orchestrator +``` + +### Stop tests + +To stop the tests, +```bash +# in zeta-node/ +make stop-test +``` + +### Run monitoring setup + +Before starting the monitoring setup, make sure the Zetacore API is up at http://localhost:1317. +You can also add any additional ETH addresses to monitor in `zeta-node/contrib/localnet/grafana/addresses.txt` file + +```bash +# in zeta-node/ +make start-monitoring +``` + +### Grafana credentials and dashboards + +The Grafana default credentials are admin:admin. The dashboards are located at http://localhost:3000. + +### Stop monitoring setup + +```bash +# in zeta-node/ +make stop-monitoring +``` + +## Interacting with the Localnet + +In addition to running automated tests, you can also interact with the localnet directly for more specific testing. + +The localnet can be started without running tests with the following command: + +```bash +# in zeta-node/ +make start-localnet +``` + +The localnet takes a few minutes to start. Printing the logs of the orchestrator will show when the localnet is ready. Once setup, it will display: +``` +✅ the localnet has been setup +``` + +### Interaction with ZetaChain + +ZetaChain +The user can connect to the `zetacore0` and directly use the node CLI with the zetacored binary with a funded account: + +The account is named `operator` in the keyring and has the address: `zeta1amcsn7ja3608dj74xt93pcu5guffsyu2xfdcyp` + +```bash +docker exec -it zetacore0 sh +``` + +Performing a query: + +```bash +zetacored q bank balances zeta1amcsn7ja3608dj74xt93pcu5guffsyu2xfdcyp +``` + +Sending a transaction: + +```bash +zetacored tx bank send operator zeta172uf5cwptuhllf6n4qsncd9v6xh59waxnu83kq 5000azeta --from operator --fees 2000000000000000azeta +``` + +### Interaction with EVM + +The user can interact with the local Ethereum node with the exposed RPC on `http://0.0.0.0:8545`. The following testing account is funded: + +``` +Address: 0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC +Private key: d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263 +``` + +Examples with the [cast](https://book.getfoundry.sh/cast/) CLI: + +```bash +cast balance 0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC --rpc-url http://0.0.0.0:8545 +98897999997945970464 + +cast send 0x9fd96203f7b22bCF72d9DCb40ff98302376cE09c --value 42 --rpc-url http://0.0.0.0:8545 --private-key "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263" +``` + +## Useful data + +- TSS Address (on ETH): 0xF421292cb0d3c97b90EEEADfcD660B893592c6A2 + +## Add more e2e tests + +The e2e tests are located in the e2e/e2etests package. New tests can be added. The process: + +1. Add a new test file in the e2e/e2etests package, the `test_` prefix should be used for the file name. +2. Implement a method that satisfies the interface: +```go +type E2ETestFunc func(*E2ERunner) +``` +3. Add the test to list in the `e2e/e2etests/e2etests.go` file. + +The test can interact with the different networks using the runned object: +```go +type E2ERunner struct { + ZevmClient *ethclient.Client + GoerliClient *ethclient.Client + BtcRPCClient *rpcclient.Client + + CctxClient crosschaintypes.QueryClient + FungibleClient fungibletypes.QueryClient + AuthClient authtypes.QueryClient + BankClient banktypes.QueryClient + ObserverClient observertypes.QueryClient + ZetaTxServer txserver.ZetaTxServer + + GoerliAuth *bind.TransactOpts + ZevmAuth *bind.TransactOpts + + // ... +} +``` + +## Localnet Governance Proposals + +Localnet can be used for testing the creation and execution of governance propoosals. + +Exec into the `zetacored0` docker container and run the script to automatically generate proposals in a variety of states and then extends the voting window to one hour, allowing you time to view a proposal in a pending state. +``` +docker exec -it zetacore0 bash +/root/test-gov-proposals.sh +``` diff --git a/Makefile b/Makefile index 0c00dd615a..7caeeb66e7 100644 --- a/Makefile +++ b/Makefile @@ -179,73 +179,39 @@ generate: proto openapi specs typescript docs-zetacored .PHONY: generate ############################################################################### -### E2E tests ### +### E2E tests and localnet ### ############################################################################### -install-zetae2e: go.sum - @echo "--> Installing zetae2e" - @go install -mod=readonly $(BUILD_FLAGS) ./cmd/zetae2e -.PHONY: install-zetae2e - -############################################################################### -### Smoke tests ### -############################################################################### - -# Note: smoke tests are deprecated and will be removed in the future, replaced with e2e tests - -install-smoketest: go.sum - @echo "--> Installing orchestrator" - @go install -mod=readonly $(BUILD_FLAGS) ./contrib/localnet/orchestrator/smoketest/cmd/smoketest - zetanode: @echo "Building zetanode" $(DOCKER) build -t zetanode -f ./Dockerfile . $(DOCKER) build -t orchestrator -f contrib/localnet/orchestrator/Dockerfile.fastbuild . .PHONY: zetanode -smoketest: - @echo "DEPRECATED: NO-OP: Building smoketest" +install-zetae2e: go.sum + @echo "--> Installing zetae2e" + @go install -mod=readonly $(BUILD_FLAGS) ./cmd/zetae2e +.PHONY: install-zetae2e -start-smoketest: - @echo "--> Starting smoketest" +start-e2e-test: + @echo "--> Starting e2e test" cd contrib/localnet/ && $(DOCKER) compose up -d -start-smoketest-upgrade: - @echo "--> Starting smoketest with upgrade proposal" - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-upgrade.yml up -d - -start-smoketest-p2p-diag: - @echo "--> Starting smoketest in p2p diagnostic mode" - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-p2p-diag.yml up -d - -stop-smoketest: - @echo "--> Stopping smoketest" - cd contrib/localnet/ && $(DOCKER) compose down --remove-orphans +start-stress-test: zetanode + cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-stresstest.yml up -d -stop-smoketest-p2p-diag: - @echo "--> Stopping smoketest in p2p diagnostic mode" - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-p2p-diag.yml down --remove-orphans - -stress-test: zetanode - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-stresstest.yml up -d - -stop-stress-test: - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-stresstest.yml down --remove-orphans - -stateful-upgrade: - @echo "--> Starting stateful smoketest" - $(DOCKER) build --build-arg old_version=mock-mainnet-01-5-ga66d0b77 --build-arg new_version=v10.0.0-30 -t zetanode -f ./Dockerfile-versioned . - $(DOCKER) build -t orchestrator -f contrib/localnet/orchestrator/Dockerfile-upgrade.fastbuild . - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-stateful.yml up -d +start-upgrade-test: + @echo "--> Starting upgrade test" + $(DOCKER) build --build-arg -t zetanode -f ./Dockerfile-upgrade . + $(DOCKER) build -t orchestrator -f contrib/localnet/orchestrator/Dockerfile.fastbuild . + cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-upgrade.yml up -d -stateful-upgrade-source: - @echo "--> Starting stateful smoketest" - $(DOCKER) build --build-arg old_version=v12.2.1 -t zetanode -f ./Dockerfile-versioned-source . - $(DOCKER) build -t orchestrator -f contrib/localnet/orchestrator/Dockerfile-upgrade.fastbuild . - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-stateful.yml up -d +start-localnet: + @echo "--> Starting localnet" + cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-setup-only.yml up -d -stop-stateful-upgrade: - cd contrib/localnet/ && $(DOCKER) compose -f docker-compose-stateful.yml down --remove-orphans +stop-test: + cd contrib/localnet/ && $(DOCKER) compose down --remove-orphans ############################################################################### ### Monitoring ### diff --git a/changelog.md b/changelog.md index 147e4a0056..2080bde846 100644 --- a/changelog.md +++ b/changelog.md @@ -39,6 +39,7 @@ ### Tests * [1584](https://github.com/zeta-chain/node/pull/1584) - allow to run E2E tests on any networks +* [1746](https://github.com/zeta-chain/node/pull/1746) - rename smoke tests to e2e tests * [1753](https://github.com/zeta-chain/node/pull/1753) - fix gosec errors on usage of rand package * [1762](https://github.com/zeta-chain/node/pull/1762) - improve coverage for fungibile module * [1782](https://github.com/zeta-chain/node/pull/1782) - improve coverage for fungibile module system contract @@ -51,6 +52,7 @@ * Added docker-compose and make commands for launching full nodes. `make mainnet-zetarpc-node` `make mainnet-bitcoind-node` * Made adjustments to the docker-compose for launching mainnet full nodes to include examples of using the docker images build from the docker image build pipeline. * [1736](https://github.com/zeta-chain/node/pull/1736) - chore: add Ethermint endpoints to OpenAPI +* [1781](https://github.com/zeta-chain/node/pull/1781) - add codecov coverage report in CI ### Features diff --git a/cmd/zetae2e/readme.md b/cmd/zetae2e/README.md similarity index 100% rename from cmd/zetae2e/readme.md rename to cmd/zetae2e/README.md diff --git a/cmd/zetae2e/balances.go b/cmd/zetae2e/balances.go index d1643dab53..7924ba88c6 100644 --- a/cmd/zetae2e/balances.go +++ b/cmd/zetae2e/balances.go @@ -9,9 +9,9 @@ import ( "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/app" zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" ) const flagSkipBTC = "skip-btc" diff --git a/cmd/zetae2e/bitcoin_address.go b/cmd/zetae2e/bitcoin_address.go index f1728e584b..f4827b850d 100644 --- a/cmd/zetae2e/bitcoin_address.go +++ b/cmd/zetae2e/bitcoin_address.go @@ -9,9 +9,9 @@ import ( "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/app" zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" ) const flagPrivKey = "privkey" diff --git a/cmd/zetae2e/config/clients.go b/cmd/zetae2e/config/clients.go index 99752648e4..e85acd2dc3 100644 --- a/cmd/zetae2e/config/clients.go +++ b/cmd/zetae2e/config/clients.go @@ -4,18 +4,17 @@ import ( "context" "fmt" - "google.golang.org/grpc" - "github.com/btcsuite/btcd/rpcclient" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" + "github.com/zeta-chain/zetacore/e2e/config" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "google.golang.org/grpc" ) // getClientsFromConfig get clients from config diff --git a/cmd/zetae2e/config/config.go b/cmd/zetae2e/config/config.go index d9a4f17edc..2d0cd3fed0 100644 --- a/cmd/zetae2e/config/config.go +++ b/cmd/zetae2e/config/config.go @@ -5,9 +5,9 @@ import ( "fmt" ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/txserver" ) // RunnerFromConfig create test runner from config @@ -21,7 +21,7 @@ func RunnerFromConfig( zetaUserName string, zetaUserMnemonic string, logger *runner.Logger, -) (*runner.SmokeTestRunner, error) { +) (*runner.E2ERunner, error) { // initialize clients btcRPCClient, goerliClient, @@ -48,8 +48,8 @@ func RunnerFromConfig( return nil, fmt.Errorf("failed to initialize ZetaChain tx server: %w", err) } - // initialize smoke test runner - sm := runner.NewSmokeTestRunner( + // initialize E2E test runner + newRunner := runner.NewE2ERunner( ctx, name, ctxCancel, @@ -71,7 +71,7 @@ func RunnerFromConfig( ) // set contracts - err = setContractsFromConfig(sm, conf) + err = setContractsFromConfig(newRunner, conf) if err != nil { return nil, fmt.Errorf("failed to set contracts from config: %w", err) } @@ -81,28 +81,28 @@ func RunnerFromConfig( if err != nil { return nil, fmt.Errorf("failed to get bitcoin params: %w", err) } - sm.BitcoinParams = &chainParams + newRunner.BitcoinParams = &chainParams - return sm, err + return newRunner, err } // ExportContractsFromRunner export contracts from the runner to config using a source config -func ExportContractsFromRunner(sm *runner.SmokeTestRunner, conf config.Config) config.Config { +func ExportContractsFromRunner(r *runner.E2ERunner, conf config.Config) config.Config { // copy contracts from deployer runner - conf.Contracts.EVM.ZetaEthAddress = sm.ZetaEthAddr.Hex() - conf.Contracts.EVM.ConnectorEthAddr = sm.ConnectorEthAddr.Hex() - conf.Contracts.EVM.CustodyAddr = sm.ERC20CustodyAddr.Hex() - conf.Contracts.EVM.USDT = sm.USDTERC20Addr.Hex() + conf.Contracts.EVM.ZetaEthAddress = r.ZetaEthAddr.Hex() + conf.Contracts.EVM.ConnectorEthAddr = r.ConnectorEthAddr.Hex() + conf.Contracts.EVM.CustodyAddr = r.ERC20CustodyAddr.Hex() + conf.Contracts.EVM.USDT = r.USDTERC20Addr.Hex() - conf.Contracts.ZEVM.SystemContractAddr = sm.SystemContractAddr.Hex() - conf.Contracts.ZEVM.ETHZRC20Addr = sm.ETHZRC20Addr.Hex() - conf.Contracts.ZEVM.USDTZRC20Addr = sm.USDTZRC20Addr.Hex() - conf.Contracts.ZEVM.BTCZRC20Addr = sm.BTCZRC20Addr.Hex() - conf.Contracts.ZEVM.UniswapFactoryAddr = sm.UniswapV2FactoryAddr.Hex() - conf.Contracts.ZEVM.UniswapRouterAddr = sm.UniswapV2RouterAddr.Hex() - conf.Contracts.ZEVM.ZEVMSwapAppAddr = sm.ZEVMSwapAppAddr.Hex() - conf.Contracts.ZEVM.ContextAppAddr = sm.ContextAppAddr.Hex() - conf.Contracts.ZEVM.TestDappAddr = sm.TestDAppAddr.Hex() + conf.Contracts.ZEVM.SystemContractAddr = r.SystemContractAddr.Hex() + conf.Contracts.ZEVM.ETHZRC20Addr = r.ETHZRC20Addr.Hex() + conf.Contracts.ZEVM.USDTZRC20Addr = r.USDTZRC20Addr.Hex() + conf.Contracts.ZEVM.BTCZRC20Addr = r.BTCZRC20Addr.Hex() + conf.Contracts.ZEVM.UniswapFactoryAddr = r.UniswapV2FactoryAddr.Hex() + conf.Contracts.ZEVM.UniswapRouterAddr = r.UniswapV2RouterAddr.Hex() + conf.Contracts.ZEVM.ZEVMSwapAppAddr = r.ZEVMSwapAppAddr.Hex() + conf.Contracts.ZEVM.ContextAppAddr = r.ContextAppAddr.Hex() + conf.Contracts.ZEVM.TestDappAddr = r.TestDAppAddr.Hex() return conf } diff --git a/cmd/zetae2e/config/contracts.go b/cmd/zetae2e/config/contracts.go index 0b80d44c4c..04cd24f9d2 100644 --- a/cmd/zetae2e/config/contracts.go +++ b/cmd/zetae2e/config/contracts.go @@ -13,15 +13,15 @@ import ( "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-core/contracts/uniswapv2factory.sol" uniswapv2router "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-periphery/contracts/uniswapv2router02.sol" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/contextapp" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/erc20" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/zevmswap" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/contracts/contextapp" + "github.com/zeta-chain/zetacore/e2e/contracts/erc20" + "github.com/zeta-chain/zetacore/e2e/contracts/zevmswap" + "github.com/zeta-chain/zetacore/e2e/runner" ) // setContractsFromConfigs get EVM contracts from config -func setContractsFromConfig(r *runner.SmokeTestRunner, conf config.Config) error { +func setContractsFromConfig(r *runner.E2ERunner, conf config.Config) error { var err error // set EVM contracts diff --git a/cmd/zetae2e/init.go b/cmd/zetae2e/init.go index eb112c98e2..f3308da4ca 100644 --- a/cmd/zetae2e/init.go +++ b/cmd/zetae2e/init.go @@ -3,10 +3,9 @@ package main import ( "fmt" - "github.com/zeta-chain/zetacore/cmd/zetae2e/local" - "github.com/spf13/cobra" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" + "github.com/zeta-chain/zetacore/cmd/zetae2e/local" + "github.com/zeta-chain/zetacore/e2e/config" ) var initConf = config.Config{} @@ -26,7 +25,7 @@ func NewInitCmd() *cobra.Command { InitCmd.Flags().StringVar(&initConf.RPCs.Bitcoin.Host, "btcURL", "bitcoin:18443", "--grpcURL bitcoin:18443") InitCmd.Flags().StringVar(&initConf.ZetaChainID, "chainID", "athens_101-1", "--chainID athens_101-1") - InitCmd.Flags().StringVar(&configFile, local.FlagConfigFile, "smoketest.config", "--cfg ./smoketest.config") + InitCmd.Flags().StringVar(&configFile, local.FlagConfigFile, "e2e.config", "--cfg ./e2e.config") return InitCmd } diff --git a/cmd/zetae2e/list_tests.go b/cmd/zetae2e/list_tests.go index 5e23da7090..b044d6d0fd 100644 --- a/cmd/zetae2e/list_tests.go +++ b/cmd/zetae2e/list_tests.go @@ -5,8 +5,8 @@ import ( "github.com/fatih/color" "github.com/spf13/cobra" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) // NewListTestsCmd returns the list test cmd @@ -25,12 +25,12 @@ func runListTests(_ *cobra.Command, _ []string) error { logger := runner.NewLogger(false, color.FgHiGreen, "") logger.Print("Available tests:") - renderTests(logger, smoketests.AllSmokeTests) + renderTests(logger, e2etests.AllE2ETests) return nil } -func renderTests(logger *runner.Logger, tests []runner.SmokeTest) { +func renderTests(logger *runner.Logger, tests []runner.E2ETest) { // Find the maximum length of the Name field maxNameLength := 0 for _, test := range tests { diff --git a/cmd/zetae2e/local/admin.go b/cmd/zetae2e/local/admin.go index 34900fbaf4..26adb3fa0a 100644 --- a/cmd/zetae2e/local/admin.go +++ b/cmd/zetae2e/local/admin.go @@ -2,19 +2,20 @@ package local import ( "fmt" + "runtime" "time" "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) // adminTestRoutine runs admin functions tests func adminTestRoutine( conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, verbose bool, ) func() error { return func() (err error) { @@ -60,11 +61,11 @@ func adminTestRoutine( adminRunner.WaitForMinedCCTX(txERC20Deposit) // run erc20 advanced test - if err := adminRunner.RunSmokeTestsFromNames( - smoketests.AllSmokeTests, - smoketests.TestPauseZRC20Name, - smoketests.TestUpdateBytecodeName, - smoketests.TestDepositEtherLiquidityCapName, + if err := adminRunner.RunE2ETestsFromNames( + e2etests.AllE2ETests, + e2etests.TestPauseZRC20Name, + e2etests.TestUpdateBytecodeName, + e2etests.TestDepositEtherLiquidityCapName, ); err != nil { return fmt.Errorf("admin tests failed: %v", err) } diff --git a/cmd/zetae2e/local/bitcoin.go b/cmd/zetae2e/local/bitcoin.go index 908b02b13b..2cd39f9c53 100644 --- a/cmd/zetae2e/local/bitcoin.go +++ b/cmd/zetae2e/local/bitcoin.go @@ -6,15 +6,15 @@ import ( "time" "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) -// bitcoinTestRoutine runs Bitcoin related smoke tests +// bitcoinTestRoutine runs Bitcoin related e2e tests func bitcoinTestRoutine( conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, verbose bool, initBitcoinNetwork bool, ) func() error { @@ -64,11 +64,11 @@ func bitcoinTestRoutine( // run bitcoin test // Note: due to the extensive block generation in Bitcoin localnet, block header test is run first // to make it faster to catch up with the latest block header - if err := bitcoinRunner.RunSmokeTestsFromNames( - smoketests.AllSmokeTests, - smoketests.TestBitcoinWithdrawName, - smoketests.TestZetaWithdrawBTCRevertName, - smoketests.TestCrosschainSwapName, + if err := bitcoinRunner.RunE2ETestsFromNames( + e2etests.AllE2ETests, + e2etests.TestBitcoinWithdrawName, + e2etests.TestZetaWithdrawBTCRevertName, + e2etests.TestCrosschainSwapName, ); err != nil { return fmt.Errorf("bitcoin tests failed: %v", err) } diff --git a/cmd/zetae2e/local/erc20.go b/cmd/zetae2e/local/erc20.go index ed82b80308..c3dbc3f354 100644 --- a/cmd/zetae2e/local/erc20.go +++ b/cmd/zetae2e/local/erc20.go @@ -6,15 +6,15 @@ import ( "time" "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) -// erc20TestRoutine runs erc20 related smoke tests +// erc20TestRoutine runs erc20 related e2e tests func erc20TestRoutine( conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, verbose bool, ) func() error { return func() (err error) { @@ -60,12 +60,12 @@ func erc20TestRoutine( //erc20Runner.DepositBTC() // run erc20 test - if err := erc20Runner.RunSmokeTestsFromNames( - smoketests.AllSmokeTests, - smoketests.TestERC20WithdrawName, - smoketests.TestMultipleWithdrawsName, - smoketests.TestERC20DepositAndCallRefundName, - smoketests.TestZRC20SwapName, + if err := erc20Runner.RunE2ETestsFromNames( + e2etests.AllE2ETests, + e2etests.TestERC20WithdrawName, + e2etests.TestMultipleWithdrawsName, + e2etests.TestERC20DepositAndCallRefundName, + e2etests.TestZRC20SwapName, ); err != nil { return fmt.Errorf("erc20 tests failed: %v", err) } diff --git a/cmd/zetae2e/local/ethereum.go b/cmd/zetae2e/local/ethereum.go index 2b4ffd7eb5..31e0e33b37 100644 --- a/cmd/zetae2e/local/ethereum.go +++ b/cmd/zetae2e/local/ethereum.go @@ -6,15 +6,15 @@ import ( "time" "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) -// ethereumTestRoutine runs Ethereum related smoke tests +// ethereumTestRoutine runs Ethereum related e2e tests func ethereumTestRoutine( conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, verbose bool, ) func() error { return func() (err error) { @@ -53,12 +53,12 @@ func ethereumTestRoutine( // run ethereum test // Note: due to the extensive block generation in Ethereum localnet, block header test is run first // to make it faster to catch up with the latest block header - if err := ethereumRunner.RunSmokeTestsFromNames( - smoketests.AllSmokeTests, - smoketests.TestEtherWithdrawName, - smoketests.TestContextUpgradeName, - smoketests.TestEtherDepositAndCallName, - smoketests.TestDepositAndCallRefundName, + if err := ethereumRunner.RunE2ETestsFromNames( + e2etests.AllE2ETests, + e2etests.TestEtherWithdrawName, + e2etests.TestContextUpgradeName, + e2etests.TestEtherDepositAndCallName, + e2etests.TestDepositAndCallRefundName, ); err != nil { return fmt.Errorf("ethereum tests failed: %v", err) } diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index db82a23c85..4e4ab4c8f5 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -9,9 +9,9 @@ import ( "github.com/fatih/color" "github.com/spf13/cobra" zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" "golang.org/x/sync/errgroup" ) @@ -33,7 +33,7 @@ var ( ) // NewLocalCmd returns the local command -// which runs the smoketest locally on the machine with localnet for each blockchain +// which runs the E2E tests locally on the machine with localnet for each blockchain func NewLocalCmd() *cobra.Command { cmd := &cobra.Command{ Use: "local", @@ -229,6 +229,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { // if setup only, quit if setupOnly { + logger.Print("✅ the localnet has been setup") os.Exit(0) } diff --git a/cmd/zetae2e/local/misc.go b/cmd/zetae2e/local/misc.go index 6dc12fc9bb..26aeb9f3b4 100644 --- a/cmd/zetae2e/local/misc.go +++ b/cmd/zetae2e/local/misc.go @@ -2,19 +2,20 @@ package local import ( "fmt" + "runtime" "time" "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) -// miscTestRoutine runs miscellaneous smoke tests +// miscTestRoutine runs miscellaneous e2e tests func miscTestRoutine( conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, verbose bool, ) func() error { return func() (err error) { @@ -55,10 +56,10 @@ func miscTestRoutine( miscRunner.WaitForMinedCCTX(txZetaDeposit) // run misc test - if err := miscRunner.RunSmokeTestsFromNames( - smoketests.AllSmokeTests, - //smoketests.TestBlockHeadersName, - smoketests.TestMyTestName, + if err := miscRunner.RunE2ETestsFromNames( + e2etests.AllE2ETests, + //e2etests.TestBlockHeadersName, + e2etests.TestMyTestName, ); err != nil { return fmt.Errorf("misc tests failed: %v", err) } diff --git a/cmd/zetae2e/local/utils.go b/cmd/zetae2e/local/utils.go index e190b45df1..f59782183c 100644 --- a/cmd/zetae2e/local/utils.go +++ b/cmd/zetae2e/local/utils.go @@ -2,6 +2,7 @@ package local import ( "context" + "path/filepath" "time" @@ -10,9 +11,9 @@ import ( "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/app" zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -48,11 +49,11 @@ func setCosmosConfig() { func initTestRunner( name string, conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, userAddress ethcommon.Address, userPrivKey string, logger *runner.Logger, -) (*runner.SmokeTestRunner, error) { +) (*runner.E2ERunner, error) { // initialize runner for test testRunner, err := zetae2econfig.RunnerFromConfig( deployerRunner.Ctx, diff --git a/cmd/zetae2e/local/zeta.go b/cmd/zetae2e/local/zeta.go index bc0f5a46bc..ac7243f7fb 100644 --- a/cmd/zetae2e/local/zeta.go +++ b/cmd/zetae2e/local/zeta.go @@ -6,15 +6,15 @@ import ( "time" "github.com/fatih/color" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" ) -// zetaTestRoutine runs Zeta transfer and message passing related smoke tests +// zetaTestRoutine runs Zeta transfer and message passing related e2e tests func zetaTestRoutine( conf config.Config, - deployerRunner *runner.SmokeTestRunner, + deployerRunner *runner.E2ERunner, verbose bool, ) func() error { return func() (err error) { @@ -57,12 +57,12 @@ func zetaTestRoutine( zetaRunner.WaitForMinedCCTX(txEtherDeposit) // run zeta test - if err := zetaRunner.RunSmokeTestsFromNames( - smoketests.AllSmokeTests, - smoketests.TestZetaWithdrawName, - smoketests.TestMessagePassingName, - smoketests.TestMessagePassingRevertFailName, - smoketests.TestMessagePassingRevertSuccessName, + if err := zetaRunner.RunE2ETestsFromNames( + e2etests.AllE2ETests, + e2etests.TestZetaWithdrawName, + e2etests.TestMessagePassingName, + e2etests.TestMessagePassingRevertFailName, + e2etests.TestMessagePassingRevertSuccessName, ); err != nil { return fmt.Errorf("zeta tests failed: %v", err) } diff --git a/cmd/zetae2e/run.go b/cmd/zetae2e/run.go index 6f98e78da6..954dfd9661 100644 --- a/cmd/zetae2e/run.go +++ b/cmd/zetae2e/run.go @@ -10,10 +10,10 @@ import ( "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/app" zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/smoketests" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/e2etests" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" ) const flagVerbose = "verbose" @@ -21,7 +21,7 @@ const flagVerbose = "verbose" const FungibleAdminMnemonic = "snow grace federal cupboard arrive fancy gym lady uniform rotate exercise either leave alien grass" // #nosec G101 - used for testing // NewRunCmd returns the run command -// which runs the smoketest from a config file describing the tests, networks, and accounts +// which runs the E2E from a config file describing the tests, networks, and accounts func NewRunCmd() *cobra.Command { cmd := &cobra.Command{ Use: "run [config-file]", @@ -103,8 +103,8 @@ func runE2ETest(cmd *cobra.Command, args []string) error { } //run tests - reports, err := testRunner.RunSmokeTestsFromNamesIntoReport( - smoketests.AllSmokeTests, + reports, err := testRunner.RunE2ETestsFromNamesIntoReport( + e2etests.AllE2ETests, conf.TestList..., ) if err != nil { diff --git a/cmd/zetae2e/show_tss.go b/cmd/zetae2e/show_tss.go index 84938396e3..79facdf4c5 100644 --- a/cmd/zetae2e/show_tss.go +++ b/cmd/zetae2e/show_tss.go @@ -4,14 +4,15 @@ import ( "context" "errors" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + ethcommon "github.com/ethereum/go-ethereum/common" "github.com/fatih/color" "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/app" zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" ) // NewShowTSSCmd returns the show TSS command diff --git a/cmd/zetae2e/stress.go b/cmd/zetae2e/stress.go index 1ef3dc6410..86703ef94b 100644 --- a/cmd/zetae2e/stress.go +++ b/cmd/zetae2e/stress.go @@ -4,25 +4,24 @@ import ( "context" "errors" "fmt" + "math/big" "os" "sort" "time" - "github.com/fatih/color" - zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" - "github.com/zeta-chain/zetacore/cmd/zetae2e/local" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/zeta-chain/zetacore/app" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" + "github.com/fatih/color" "github.com/spf13/cobra" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" + "github.com/zeta-chain/zetacore/app" + zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config" + "github.com/zeta-chain/zetacore/cmd/zetae2e/local" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" "google.golang.org/grpc" ) @@ -59,7 +58,7 @@ func NewStressTestCmd() *cobra.Command { StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "LOCAL", "--network TESTNET") StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") StressCmd.Flags().BoolVar(&stressTestArgs.contractsDeployed, "contracts-deployed", false, "--contracts-deployed=false") - StressCmd.Flags().StringVar(&stressTestArgs.config, local.FlagConfigFile, "", "config file to use for the smoketest") + StressCmd.Flags().StringVar(&stressTestArgs.config, local.FlagConfigFile, "", "config file to use for the E2E test") StressCmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging") local.DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) @@ -70,11 +69,11 @@ func NewStressTestCmd() *cobra.Command { func StressTest(cmd *cobra.Command, _ []string) { testStartTime := time.Now() defer func() { - fmt.Println("Smoke test took", time.Since(testStartTime)) + fmt.Println("E2E test took", time.Since(testStartTime)) }() go func() { time.Sleep(StressTestTimeout) - fmt.Println("Smoke test timed out after", StressTestTimeout) + fmt.Println("E2E test timed out after", StressTestTimeout) os.Exit(1) }() @@ -83,7 +82,7 @@ func StressTest(cmd *cobra.Command, _ []string) { cosmosConf.SetBech32PrefixForAccount(app.Bech32PrefixAccAddr, app.Bech32PrefixAccPub) cosmosConf.Seal() - // initialize smoke tests config + // initialize E2E tests config conf, err := local.GetConfig(cmd) if err != nil { panic(err) @@ -135,8 +134,8 @@ func StressTest(cmd *cobra.Command, _ []string) { } logger := runner.NewLogger(verbose, color.FgWhite, "setup") - // initialize smoke test runner - smokeTest, err := zetae2econfig.RunnerFromConfig( + // initialize E2E test runner + e2eTest, err := zetae2econfig.RunnerFromConfig( ctx, "deployer", cancel, @@ -152,27 +151,27 @@ func StressTest(cmd *cobra.Command, _ []string) { } // setup TSS addresses - if err := smokeTest.SetTSSAddresses(); err != nil { + if err := e2eTest.SetTSSAddresses(); err != nil { panic(err) } - smokeTest.SetupEVM(stressTestArgs.contractsDeployed) + e2eTest.SetupEVM(stressTestArgs.contractsDeployed) // If stress test is running on local docker environment if stressTestArgs.network == "LOCAL" { // deploy and set zevm contract - smokeTest.SetZEVMContracts() + e2eTest.SetZEVMContracts() // deposit on ZetaChain - smokeTest.DepositEther(false) - smokeTest.DepositZeta() + e2eTest.DepositEther(false) + e2eTest.DepositZeta() } else if stressTestArgs.network == "TESTNET" { - ethZRC20Addr, err := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) + ethZRC20Addr, err := e2eTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) if err != nil { panic(err) } - smokeTest.ETHZRC20Addr = ethZRC20Addr - smokeTest.ETHZRC20, err = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.ZevmClient) + e2eTest.ETHZRC20Addr = ethZRC20Addr + e2eTest.ETHZRC20, err = zrc20.NewZRC20(e2eTest.ETHZRC20Addr, e2eTest.ZevmClient) if err != nil { panic(err) } @@ -182,7 +181,7 @@ func StressTest(cmd *cobra.Command, _ []string) { } // Check zrc20 balance of Deployer address - ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress) + ethZRC20Balance, err := e2eTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress) if err != nil { panic(err) } @@ -190,27 +189,27 @@ func StressTest(cmd *cobra.Command, _ []string) { //Pre-approve ETH withdraw on ZEVM fmt.Printf("approving ETH ZRC20...\n") - ethZRC20 := smokeTest.ETHZRC20 - tx, err := ethZRC20.Approve(smokeTest.ZevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) + ethZRC20 := e2eTest.ETHZRC20 + tx, err := ethZRC20.Approve(e2eTest.ZevmAuth, e2eTest.ETHZRC20Addr, big.NewInt(1e18)) if err != nil { panic(err) } - receipt := utils.MustWaitForTxReceipt(ctx, smokeTest.ZevmClient, tx, logger, smokeTest.ReceiptTimeout) + receipt := utils.MustWaitForTxReceipt(ctx, e2eTest.ZevmClient, tx, logger, e2eTest.ReceiptTimeout) fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level - blockNum, err := smokeTest.ZevmClient.BlockNumber(context.Background()) + blockNum, err := e2eTest.ZevmClient.BlockNumber(context.Background()) if err != nil { panic(err) } - // #nosec G701 smoketest - always in range - nonce, err := smokeTest.ZevmClient.NonceAt(context.Background(), local.DeployerAddress, big.NewInt(int64(blockNum))) + // #nosec G701 e2eTest - always in range + nonce, err := e2eTest.ZevmClient.NonceAt(context.Background(), local.DeployerAddress, big.NewInt(int64(blockNum))) if err != nil { panic(err) } - // #nosec G701 smoketest - always in range + // #nosec G701 e2e - always in range zevmNonce = big.NewInt(int64(nonce)) // -------------- TEST BEGINS ------------------ @@ -219,31 +218,31 @@ func StressTest(cmd *cobra.Command, _ []string) { fmt.Println(" 1. Periodically Withdraw ETH from ZEVM to EVM - goerli") fmt.Println(" 2. Display Network metrics to monitor performance [Num Pending outbound tx], [Num Trackers]") - smokeTest.WG.Add(2) - go WithdrawCCtx(smokeTest) // Withdraw USDT from ZEVM to EVM - goerli - go EchoNetworkMetrics(smokeTest) // Display Network metrics periodically to monitor performance + e2eTest.WG.Add(2) + go WithdrawCCtx(e2eTest) // Withdraw USDT from ZEVM to EVM - goerli + go EchoNetworkMetrics(e2eTest) // Display Network metrics periodically to monitor performance - smokeTest.WG.Wait() + e2eTest.WG.Wait() } // WithdrawCCtx withdraw USDT from ZEVM to EVM -func WithdrawCCtx(sm *runner.SmokeTestRunner) { +func WithdrawCCtx(runner *runner.E2ERunner) { ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) for { select { case <-ticker.C: - WithdrawETHZRC20(sm) + WithdrawETHZRC20(runner) } } } -func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { +func EchoNetworkMetrics(runner *runner.E2ERunner) { ticker := time.NewTicker(time.Second * StatInterval) var queue = make([]uint64, 0) var numTicks = 0 var totalMinedTxns = uint64(0) var previousMinedTxns = uint64(0) - chainID, err := getChainID(sm.GoerliClient) + chainID, err := getChainID(runner.GoerliClient) if err != nil { panic(err) @@ -254,7 +253,7 @@ func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { case <-ticker.C: numTicks++ // Get all pending outbound transactions - cctxResp, err := sm.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ + cctxResp, err := runner.CctxClient.CctxListPending(context.Background(), &crosschaintypes.QueryListCctxPendingRequest{ ChainId: chainID.Int64(), }) if err != nil { @@ -271,7 +270,7 @@ func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { } // // Get all trackers - trackerResp, err := sm.CctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) + trackerResp, err := runner.CctxClient.OutTxTrackerAll(context.Background(), &crosschaintypes.QueryAllOutTxTrackerRequest{}) if err != nil { continue } @@ -300,15 +299,15 @@ func EchoNetworkMetrics(sm *runner.SmokeTestRunner) { } } -func WithdrawETHZRC20(sm *runner.SmokeTestRunner) { +func WithdrawETHZRC20(runner *runner.E2ERunner) { defer func() { zevmNonce.Add(zevmNonce, big.NewInt(1)) }() - ethZRC20 := sm.ETHZRC20 + ethZRC20 := runner.ETHZRC20 - sm.ZevmAuth.Nonce = zevmNonce - _, err := ethZRC20.Withdraw(sm.ZevmAuth, local.DeployerAddress.Bytes(), big.NewInt(100)) + runner.ZevmAuth.Nonce = zevmNonce + _, err := ethZRC20.Withdraw(runner.ZevmAuth, local.DeployerAddress.Bytes(), big.NewInt(100)) if err != nil { panic(err) } diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..647094cf84 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,74 @@ +coverage: + round: down + precision: 2 + status: + project: + default: + threshold: 1% # allow this much decrease on project + zetacore: + if_ci_failed: error + target: 60% + flags: + - zetacore + zetaclient: + if_ci_failed: error + target: 60% + flags: + - zetaclient + common: + if_ci_failed: error + target: 60% + flags: + - common + +comment: + layout: "reach, diff, files" + behavior: default + require_changes: true + +flags: + zetacore: + carryforward: true + paths: + - "x/" + zetaclient: + carryforward: true + paths: + - "zetaclient/" + common: + carryforward: true + paths: + - "common/" + +ignore: + - "x/**/client/" + - "x/**/keeper/keeper.go" + - "x/**/keeper/msg_server.go" + - "x/**/keeper/grpc_query_params.go" + - "x/**/types/codec.go" + - "x/**/types/errors.go" + - "x/**/types/keys.go" + - "x/**/types/key_*.go" + - "x/**/types/types.go" + - "x/**/types/expected_keepers.go" + - "x/**/module.go" + - "x/**/module_simulation.go" + - "x/**/simulation/" + - "*.proto" + - "*.md" + - "*.yml" + - "*.yaml" + - "*.pb.go" + - "*.pb.gw.go" + - "*.json" + - ".github/" + - "app/" + - "cmd/" + - "contrib/" + - "docs/" + - "rpc/" + - "proto/" + - "scripts/" + - "server/" + - "testutil/" + - "typescript/" \ No newline at end of file diff --git a/contrib/localnet/README.md b/contrib/localnet/README.md index 96143b06d5..17a2ae3d03 100644 --- a/contrib/localnet/README.md +++ b/contrib/localnet/README.md @@ -2,128 +2,68 @@ This directory contains a set of scripts to help you quickly set up a local ZetaChain network for development and testing purposes. The scripts are based on the Docker -and [Docker Compose](https://docs.docker.com/compose/). - -As a smoke test (sanity integration tests), the setup aims -at fully automatic, only requiring a few image building steps -and docker compose launch. +and Docker Compose. As a development testing environment, the setup aims to be flexible, close to real world, and with fast turnaround -between edit code -> compile -> test results. - -This is primarily tested on a recent Linux distribution such -as Ubuntu 22.04 LTS, though macOS should also work (not tested). +between edit code -> compile -> test results. -The docker-compose.yml file defines a network with: +The `docker-compose.yml` file defines a network with: * 2 zetacore nodes * 2 zetaclient nodes * 1 go-ethereum private net node (act as GOERLI testnet, with chainid 1337) * 1 bitcoin core private node (planned; not yet done) -* 1 orchestrator node which coordinates smoke tests. +* 1 orchestrator node which coordinates E2E tests. -## Prerequisites -- [Docker](https://docs.docker.com/install/) -- [Docker Compose](https://docs.docker.com/compose/install/) -- [Git](https://git-scm.com/downloads) -- [Go](https://golang.org/doc/install) -- [jq](https://stedolan.github.io/jq/download/) - -## Steps - -### Build zetanode -```bash -$ make zetanode -``` +The following Docker compose files can extend the default localnet setup: -This Makefile rule builds the zetanode image. **Rebuild if zetacored/zetaclientd code is updated**. -```bash -# in zeta-node/ -$ docker build -t zetanode . -``` +- `docker-compose-stresstest.yml`: Spin up more nodes and clients for testing performance of the network. +- `docker-compose-upgrade.yml`: Spin up a network with with a upgrade proposal defined at a specific height. -### Smoke Test Dev & Test Cycle -The smoke test is in the directory /contrib/localnet/orchestrator/smoketest. -It's a Go program that performs various operations on the localnet. +Finally, `docker-compose-monitoring.yml` can be run separately to spin up a local grafana and prometheus setup to monitor the network. -The above `make zetanode` should already produced the orchestrator image. +## Running Localnet -### Run smoke test +Running the localnet requires `zetanode` Docker image. The following command should be run at the root of the repo: -Now we have built all the docker images; we can run the smoke test with make command: -```bash -# in zeta-node/ -make start-smoketest ``` -which does the following docker compose command: -```bash -# in zeta-node/contrib/localnet/orchestrator -$ docker compose up -d +make zetanode ``` -The most straightforward log to observe is the orchestrator log. -If everything works fine, it should finish without panic, and with -a message "smoketest done". +Localnet can be started with Docker Compose: -To stop the tests, -```bash -# in zeta-node/ -make stop-smoketest -``` -which does the following docker compose command: -```bash -# in zeta-node/contrib/localnet/orchestrator -$ docker compose down --remove-orphans ``` -### Run monitoring setup -Before starting the monitoring setup, make sure the Zetacore API is up at http://localhost:1317. -You can also add any additional ETH addresses to monitor in zeta-node/contrib/localnet/grafana/addresses.txt file -```bash -# in zeta-node/ -make start-monitoring -``` -which does the following docker compose command: -```bash -# in zeta-node/contrib/localnet/ -$ docker compose -f docker-compose-monitoring.yml up -d -``` -### Grafana credentials and dashboards -The Grafana default credentials are admin:admin. The dashboards are located at http://localhost:3000. -### Stop monitoring setup -```bash -# in zeta-node/ -make stop-monitoring -``` -which does the following docker compose command: -```bash -# in zeta-node/contrib/localnet/ -$ docker compose -f docker-compose-monitoring.yml down --remove-orphans +docker-compose up -d ``` -## Useful data +To stop the localnet: -- On GOERLI (private ETH net), the deployer account is pre-funded with Ether. -[Deployer Address and Private Key](orchestrator/smoketest/main.go) +``` +docker-compose down +``` -- TSS Address (on ETH): 0xF421292cb0d3c97b90EEEADfcD660B893592c6A2 +## Orchestrator +The `orchestrator` directory contains the orchestrator node which coordinates E2E tests. The orchestrator is responsible for: +- Initializing accounts on the local Ethereum network. +- Using `zetae2e` CLI to run the tests. +- Restarting ZetaClient during upgrade tests. -## Add more smoke tests -The smoke test (integration tests) are located in the -orchestrator/smoketest directory. The orchestrator is a Go program. +## Scripts -## LocalNet Governance Proposals +The `scripts` directory mainly contains the following scripts: -Localnet can be used for testing the creation and execution of governance propoosals. +- `start-zetacored.sh`: Used by zetacore images to bootstrap genesis and start the nodes. +- `start-zetaclientd.sh`: Used by zetaclient images to setup TSS and start the clients. -Exec into the zetacored0 docker container and run the script to automatically generate proposals in a variety of states and then extends the voting window to one hour, allowing you time to view a proposal in a pending state. -``` -docker exec -it zetacore0 bash -/root/gov-proposals-testing.sh -``` +## Prerequisites -## References -[Setup testnet reference](https://www.notion.so/zetachain/Set-up-athens-1-like-testnet-to-test-your-PRs-ac523eb5dd5d4e73902072ab7d85fa2f) +The following are required to run the localnet: +- [Docker](https://docs.docker.com/install/) +- [Docker Compose](https://docs.docker.com/compose/install/) +- [Git](https://git-scm.com/downloads) +- [Go](https://golang.org/doc/install) +- [jq](https://stedolan.github.io/jq/download/) diff --git a/contrib/localnet/docker-compose-genesis.yml b/contrib/localnet/docker-compose-genesis.yml deleted file mode 100644 index 9b0cd1d6a4..0000000000 --- a/contrib/localnet/docker-compose-genesis.yml +++ /dev/null @@ -1,77 +0,0 @@ -version: "3" - -networks: - mynetwork: - ipam: - config: - - subnet: 172.20.0.0/24 - - -services: - zetacore0: - image: zetanode:latest - container_name: zetacore0 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetacore0 - ports: - - "1317:1317" - - "9545:8545" - - "9546:8546" - networks: - mynetwork: - ipv4_address: 172.20.0.11 - entrypoint: ["/root/genesis.sh", "2"] # Need to specify that there are 2 nodes - - - zetacore1: - image: zetanode:latest - container_name: zetacore1 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetacore1 - networks: - mynetwork: - ipv4_address: 172.20.0.12 - entrypoint: ["/root/genesis.sh", "2"] - - zetaclient0: - image: zetanode:latest - container_name: zetaclient0 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient0 - networks: - mynetwork: - ipv4_address: 172.20.0.21 - entrypoint: /root/start-zetaclientd-genesis.sh - environment: - - ETHDEV_ENDPOINT=http://eth:8545 - - zetaclient1: - image: zetanode:latest - container_name: zetaclient1 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient1 - networks: - mynetwork: - ipv4_address: 172.20.0.22 - entrypoint: /root/start-zetaclientd-genesis.sh - environment: - - ETHDEV_ENDPOINT=http://eth:8545 - - eth: - image: ethereum/client-go:v1.10.26 - container_name: eth - hostname: eth - ports: - - "8545:8545" - networks: - mynetwork: - ipv4_address: 172.20.0.100 - entrypoint: [ "geth", "--dev", "--http", "--http.addr", "172.20.0.100", "--http.vhosts", "*", "--http.api", "eth,web3,net", "--http.corsdomain", "https://remix.ethereum.org", "--dev.period", "2" ] \ No newline at end of file diff --git a/contrib/localnet/docker-compose-p2p-diag.yml b/contrib/localnet/docker-compose-p2p-diag.yml deleted file mode 100644 index 47385caf13..0000000000 --- a/contrib/localnet/docker-compose-p2p-diag.yml +++ /dev/null @@ -1,64 +0,0 @@ -version: "3" - -networks: - mynetwork: - ipam: - config: - - subnet: 172.20.0.0/24 - - -services: - - zetaclient0: - image: zetanode:latest - container_name: zetaclient0 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient0 - networks: - mynetwork: - ipv4_address: 172.20.0.21 - entrypoint: /root/start-zetaclientd-p2p-diag.sh - - - zetaclient1: - image: zetanode:latest - container_name: zetaclient1 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient1 - networks: - mynetwork: - ipv4_address: 172.20.0.22 - entrypoint: /root/start-zetaclientd-p2p-diag.sh - - zetaclient2: - image: zetanode:latest - container_name: zetaclient2 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient2 - networks: - mynetwork: - ipv4_address: 172.20.0.23 - entrypoint: /root/start-zetaclientd-p2p-diag.sh - environment: - - MYIP=172.20.0.55 - - - zetaclient3: - image: zetanode:latest - container_name: zetaclient3 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient3 - networks: - mynetwork: - ipv4_address: 172.20.0.24 - entrypoint: /root/start-zetaclientd-p2p-diag.sh - - diff --git a/contrib/localnet/docker-compose-setup-only.yml b/contrib/localnet/docker-compose-setup-only.yml new file mode 100644 index 0000000000..ed210c3264 --- /dev/null +++ b/contrib/localnet/docker-compose-setup-only.yml @@ -0,0 +1,22 @@ +version: "3" + +# This docker-compose file overrides the orcherstrator service to use the setup only option +# It is used to setup the localnet environment without running tests + +services: + orchestrator: + image: orchestrator:latest + tty: true + container_name: orchestrator + build: + context: ../../. + dockerfile: contrib/localnet/orchestrator/Dockerfile + depends_on: + - zetacore0 + - eth + hostname: orchestrator + networks: + mynetwork: + ipv4_address: 172.20.0.2 + entrypoint: ["/work/start.sh", "local", "setup-only"] + diff --git a/contrib/localnet/docker-compose-stateful.yml b/contrib/localnet/docker-compose-stateful.yml deleted file mode 100644 index d577d96b2d..0000000000 --- a/contrib/localnet/docker-compose-stateful.yml +++ /dev/null @@ -1,109 +0,0 @@ -version: "3" - -networks: - mynetwork: - ipam: - config: - - subnet: 172.20.0.0/24 - - -services: - zetacore0: - image: zetanode:latest - container_name: zetacore0 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetacore0 - ports: - - "1317:1317" - - "9545:8545" - - "9546:8546" - networks: - mynetwork: - ipv4_address: 172.20.0.11 - entrypoint: ["/root/genesis-stateful.sh", "2"] # Need to specify that there are 2 nodes - - - zetacore1: - image: zetanode:latest - container_name: zetacore1 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetacore1 - networks: - mynetwork: - ipv4_address: 172.20.0.12 - entrypoint: ["/root/genesis-stateful.sh", "2"] - - zetaclient0: - image: zetanode:latest - container_name: zetaclient0 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient0 - networks: - mynetwork: - ipv4_address: 172.20.0.21 - entrypoint: /root/start-zetaclientd-background.sh - environment: - - ETHDEV_ENDPOINT=http://eth:8545 - - zetaclient1: - image: zetanode:latest - container_name: zetaclient1 - build: - context: ../../. - dockerfile: Dockerfile - hostname: zetaclient1 - networks: - mynetwork: - ipv4_address: 172.20.0.22 - entrypoint: /root/start-zetaclientd-background.sh - environment: - - ETHDEV_ENDPOINT=http://eth:8545 - - bitcoin: - image: ruimarinho/bitcoin-core:22 # version 23 is not working with btcd 0.22.0 due to change in createwallet rpc - container_name: bitcoin - hostname: bitcoin - networks: - mynetwork: - ipv4_address: 172.20.0.101 - ports: - - "18443:18443" - command: - -printtoconsole - -regtest=1 - -rpcallowip=172.20.0.0/16 - -rpcbind=0.0.0.0 - -rpcauth=smoketest:63acf9b8dccecce914d85ff8c044b78b$$5892f9bbc84f4364e79f0970039f88bdd823f168d4acc76099ab97b14a766a99 - -txindex=1 - - eth: - image: ethereum/client-go:v1.10.26 - container_name: eth - hostname: eth - ports: - - "8545:8545" - networks: - mynetwork: - ipv4_address: 172.20.0.100 - entrypoint: [ "geth", "--dev", "--http", "--http.addr", "172.20.0.100", "--http.vhosts", "*", "--http.api", "eth,web3,net", "--http.corsdomain", "https://remix.ethereum.org", "--dev.period", "2" ] - - orchestrator: - image: orchestrator:latest - container_name: orchestrator - build: - context: ../../. - dockerfile: contrib/localnet/orchestrator/Dockerfile - depends_on: - - zetacore0 - - eth - hostname: orchestrator - networks: - mynetwork: - ipv4_address: 172.20.0.2 - entrypoint: [ "/work/start-upgrade.sh", "local"] diff --git a/contrib/localnet/docker-compose-stresstest.yml b/contrib/localnet/docker-compose-stresstest.yml index ec03d8cdf1..07cb1820f4 100644 --- a/contrib/localnet/docker-compose-stresstest.yml +++ b/contrib/localnet/docker-compose-stresstest.yml @@ -1,11 +1,9 @@ version: "3" -networks: - mynetwork: - ipam: - config: - - subnet: 172.20.0.0/24 - +# This docker-compose redefine the services: +# - ZetaChain with 4 nodes to test performance +# - ZetaChain observer set with 4 clients to test performance +# - Orchestrator call stress commands services: zetacore0: @@ -22,8 +20,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.11 - entrypoint: ["/root/genesis.sh", "4"] - + entrypoint: ["/root/start-zetacored.sh", "4"] + environment: + - HOTKEY_BACKEND=test zetacore1: image: zetanode:latest @@ -35,7 +34,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.12 - entrypoint: ["/root/genesis.sh", "4"] + entrypoint: ["/root/start-zetacored.sh", "4"] + environment: + - HOTKEY_BACKEND=test zetacore2: image: zetanode:latest @@ -47,7 +48,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.13 - entrypoint: [ "/root/genesis.sh", "4" ] + entrypoint: [ "/root/start-zetacored.sh", "4" ] + environment: + - HOTKEY_BACKEND=test zetacore3: image: zetanode:latest @@ -59,7 +62,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.14 - entrypoint: [ "/root/genesis.sh", "4" ] + entrypoint: [ "/root/start-zetacored.sh", "4" ] + environment: + - HOTKEY_BACKEND=test zetaclient0: image: zetanode:latest @@ -73,10 +78,10 @@ services: ipv4_address: 172.20.0.21 ports: - "8123:8123" - - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: /root/start-zetaclientd.sh environment: - ETHDEV_ENDPOINT=http://eth:8545 + - HOTKEY_BACKEND=test zetaclient1: image: zetanode:latest @@ -88,9 +93,10 @@ services: networks: mynetwork: ipv4_address: 172.20.0.22 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: /root/start-zetaclientd.sh environment: - ETHDEV_ENDPOINT=http://eth:8545 + - HOTKEY_BACKEND=test zetaclient2: image: zetanode:latest @@ -102,9 +108,10 @@ services: networks: mynetwork: ipv4_address: 172.20.0.23 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: /root/start-zetaclientd.sh environment: - ETHDEV_ENDPOINT=http://eth:8545 + - HOTKEY_BACKEND=test zetaclient3: image: zetanode:latest @@ -116,37 +123,10 @@ services: networks: mynetwork: ipv4_address: 172.20.0.24 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: /root/start-zetaclientd.sh environment: - ETHDEV_ENDPOINT=http://eth:8545 - - eth: - image: ethereum/client-go:v1.10.26 - container_name: eth - hostname: eth - ports: - - "8545:8545" - networks: - mynetwork: - ipv4_address: 172.20.0.100 - entrypoint: [ "geth", "--dev", "--http", "--http.addr", "172.20.0.100", "--http.vhosts", "*", "--http.api", "eth,web3,net", "--http.corsdomain", "https://remix.ethereum.org", "--dev.period", "2" ] - - bitcoin: - image: ruimarinho/bitcoin-core:22 # version 23 is not working with btcd 0.22.0 due to change in createwallet rpc - container_name: bitcoin - hostname: bitcoin - networks: - mynetwork: - ipv4_address: 172.20.0.101 - ports: - - "18443:18443" - command: - -printtoconsole - -regtest=1 - -rpcallowip=172.20.0.0/16 - -rpcbind=0.0.0.0 - -rpcauth=smoketest:63acf9b8dccecce914d85ff8c044b78b$5892f9bbc84f4364e79f0970039f88bdd823f168d4acc76099ab97b14a766a99 - -txindex=1 + - HOTKEY_BACKEND=test orchestrator: image: orchestrator:latest diff --git a/contrib/localnet/docker-compose-upgrade.yml b/contrib/localnet/docker-compose-upgrade.yml index be019ee690..c55f847e43 100644 --- a/contrib/localnet/docker-compose-upgrade.yml +++ b/contrib/localnet/docker-compose-upgrade.yml @@ -1,24 +1,11 @@ version: "3" -networks: - mynetwork: - ipam: - config: - - subnet: 172.20.0.0/24 - +# This docker-compose redefine the services: +# - ZetaChain with 2 nodes (zetacore0, zetacore1) using the upgrade option for cosmovisor +# - ZetaChain observer set with 2 clients (zetaclient0, zetaclient1) using the background option +# - Orchestrator with upgrade option services: - rosetta: - image: zetanode:latest - container_name: rosetta - hostname: rosetta - ports: - - "8080:8080" - networks: - mynetwork: - ipv4_address: 172.20.0.200 - entrypoint: ["zetacored", "rosetta", "--tendermint", "zetacore0:26657", "--grpc", "zetacore0:9090", "--network", "athens_101-1", "--blockchain", "zetacore"] - zetacore0: image: zetanode:latest container_name: zetacore0 @@ -33,8 +20,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.11 - entrypoint: ["/root/genesis-upgrade.sh", "2"] - + entrypoint: ["/root/start-zetacored.sh", "2", "upgrade"] + environment: + - HOTKEY_BACKEND=test zetacore1: image: zetanode:latest @@ -46,8 +34,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.12 - entrypoint: ["/root/genesis-upgrade.sh", "2"] - + entrypoint: ["/root/start-zetacored.sh", "2", "upgrade"] + environment: + - HOTKEY_BACKEND=test zetaclient0: image: zetanode:latest @@ -59,8 +48,9 @@ services: networks: mynetwork: ipv4_address: 172.20.0.21 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: ["/root/start-zetaclientd.sh", "background"] environment: + - HOTKEY_BACKEND=test - ETHDEV_ENDPOINT=http://eth:8545 zetaclient1: @@ -73,38 +63,11 @@ services: networks: mynetwork: ipv4_address: 172.20.0.22 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: ["/root/start-zetaclientd.sh", "background"] environment: + - HOTKEY_BACKEND=test - ETHDEV_ENDPOINT=http://eth:8545 - eth: - image: ethereum/client-go:v1.10.26 - container_name: eth - hostname: eth - ports: - - "8545:8545" - networks: - mynetwork: - ipv4_address: 172.20.0.100 - entrypoint: ["geth", "--dev", "--http", "--http.addr", "172.20.0.100", "--http.vhosts", "*", "--http.api", "eth,web3,net", "--http.corsdomain", "https://remix.ethereum.org", "--dev.period", "2"] - - bitcoin: - image: ruimarinho/bitcoin-core:22 # version 23 is not working with btcd 0.22.0 due to change in createwallet rpc - container_name: bitcoin - hostname: bitcoin - networks: - mynetwork: - ipv4_address: 172.20.0.101 - ports: - - "18443:18443" - command: - -printtoconsole - -regtest=1 - -rpcallowip=172.20.0.0/16 - -rpcbind=0.0.0.0 - -rpcauth=smoketest:63acf9b8dccecce914d85ff8c044b78b$5892f9bbc84f4364e79f0970039f88bdd823f168d4acc76099ab97b14a766a99 - -txindex=1 - orchestrator: image: orchestrator:latest container_name: orchestrator @@ -118,5 +81,4 @@ services: networks: mynetwork: ipv4_address: 172.20.0.2 - entrypoint: ["/work/start.sh", "local"] - + entrypoint: ["/work/start.sh", "local", "upgrade"] diff --git a/contrib/localnet/docker-compose.yml b/contrib/localnet/docker-compose.yml index 14f1435776..c43d77ff8b 100644 --- a/contrib/localnet/docker-compose.yml +++ b/contrib/localnet/docker-compose.yml @@ -1,5 +1,14 @@ version: "3" +# This docker-compose file configures the localnet environment +# it contains the following services: +# - ZetaChain with 2 nodes (zetacore0, zetacore1) +# - A observer set with 2 clients (zetaclient0, zetaclient1) +# - An Ethereum node (eth) +# - A Bitcoin node (bitcoin) +# - A Rosetta API (rosetta) +# - An orchestrator to manage interaction with the localnet (orchestrator) + networks: mynetwork: ipam: @@ -33,7 +42,7 @@ services: networks: mynetwork: ipv4_address: 172.20.0.11 - entrypoint: ["/root/genesis.sh", "2"] + entrypoint: ["/root/start-zetacored.sh", "2"] environment: - HOTKEY_BACKEND=file - HOTKEY_PASSWORD=password # test purposes only @@ -48,7 +57,7 @@ services: networks: mynetwork: ipv4_address: 172.20.0.12 - entrypoint: ["/root/genesis.sh", "2"] + entrypoint: ["/root/start-zetacored.sh", "2"] environment: - HOTKEY_BACKEND=file - HOTKEY_PASSWORD=password # test purposes only @@ -63,7 +72,7 @@ services: networks: mynetwork: ipv4_address: 172.20.0.21 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: /root/start-zetaclientd.sh environment: - ETHDEV_ENDPOINT=http://eth:8545 - HOTKEY_BACKEND=file @@ -79,7 +88,7 @@ services: networks: mynetwork: ipv4_address: 172.20.0.22 - entrypoint: /root/start-zetaclientd-genesis.sh + entrypoint: /root/start-zetaclientd.sh environment: - ETHDEV_ENDPOINT=http://eth:8545 - HOTKEY_BACKEND=file @@ -110,7 +119,7 @@ services: -regtest=1 -rpcallowip=172.20.0.0/16 -rpcbind=0.0.0.0 - -rpcauth=smoketest:63acf9b8dccecce914d85ff8c044b78b$$5892f9bbc84f4364e79f0970039f88bdd823f168d4acc76099ab97b14a766a99 + -rpcauth=e2e:63acf9b8dccecce914d85ff8c044b78b$$5892f9bbc84f4364e79f0970039f88bdd823f168d4acc76099ab97b14a766a99 -txindex=1 orchestrator: diff --git a/contrib/localnet/eth/start.sh b/contrib/localnet/eth/start.sh deleted file mode 100644 index 13f47935d9..0000000000 --- a/contrib/localnet/eth/start.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh - diff --git a/contrib/localnet/node.sh b/contrib/localnet/node.sh deleted file mode 100755 index 73dcacf9eb..0000000000 --- a/contrib/localnet/node.sh +++ /dev/null @@ -1,6 +0,0 @@ -if [ $# -ne 1 ] -then - echo "Usage: node.sh " - exit 1 -fi -ssh -i z.pem -oStrictHostKeyChecking=no -p "702$1" alpine@0.0.0.0 diff --git a/contrib/localnet/orchestrator/Dockerfile b/contrib/localnet/orchestrator/Dockerfile index c6557e6cd8..5e579916cc 100644 --- a/contrib/localnet/orchestrator/Dockerfile +++ b/contrib/localnet/orchestrator/Dockerfile @@ -12,7 +12,6 @@ COPY --from=zeta /root/.ssh/localtest.pem.pub /root/.ssh/authorized_keys COPY --from=zeta /root/.ssh/localtest.pem /root/.ssh/localtest.pem COPY contrib/localnet/orchestrator/start.sh /work/ -COPY contrib/localnet/orchestrator/start-upgrade.sh /work/ COPY contrib/localnet/orchestrator/restart-zetaclientd.sh /work/ RUN chmod +x /work/*.sh diff --git a/contrib/localnet/orchestrator/Dockerfile-upgrade.fastbuild b/contrib/localnet/orchestrator/Dockerfile-upgrade.fastbuild deleted file mode 100644 index 5cbccbc0a6..0000000000 --- a/contrib/localnet/orchestrator/Dockerfile-upgrade.fastbuild +++ /dev/null @@ -1,22 +0,0 @@ -FROM zetanode:latest as zeta -FROM ethereum/client-go:v1.10.26 as geth -FROM golang:1.20-alpine as orchestrator - -RUN apk --no-cache add jq curl bash make git build-base openssh - -COPY --from=zeta /usr/local/bin/zetacored /usr/local/bin/ -COPY --from=zeta /usr/local/bin/zetaclientd /usr/local/bin/ -COPY --from=geth /usr/local/bin/geth /usr/local/bin/ - -COPY --from=zeta /root/.ssh/localtest.pem.pub /root/.ssh/authorized_keys -COPY --from=zeta /root/.ssh/localtest.pem /root/.ssh/localtest.pem - -COPY contrib/localnet/orchestrator/start.sh /work/ -COPY contrib/localnet/orchestrator/start-upgrade.sh /work/ -COPY contrib/localnet/orchestrator/restart-zetaclientd.sh /work/ -RUN chmod +x /work/*.sh - -COPY --from=zeta /usr/local/bin/zetae2e /usr/local/bin/ -RUN chmod +x /usr/local/bin/zetae2e - -WORKDIR /work diff --git a/contrib/localnet/orchestrator/Dockerfile.fastbuild b/contrib/localnet/orchestrator/Dockerfile.fastbuild index 9357d5d90f..198205c000 100644 --- a/contrib/localnet/orchestrator/Dockerfile.fastbuild +++ b/contrib/localnet/orchestrator/Dockerfile.fastbuild @@ -2,7 +2,7 @@ FROM zetanode:latest as zeta FROM ethereum/client-go:v1.10.26 as geth FROM golang:1.20-alpine as orchestrator -RUN apk --no-cache add jq curl bash make git build-base +RUN apk --no-cache add jq curl bash make git build-base openssh COPY --from=zeta /usr/local/bin/zetacored /usr/local/bin/ COPY --from=zeta /usr/local/bin/zetaclientd /usr/local/bin/ @@ -12,10 +12,10 @@ COPY --from=zeta /root/.ssh/localtest.pem.pub /root/.ssh/authorized_keys COPY --from=zeta /root/.ssh/localtest.pem /root/.ssh/localtest.pem COPY contrib/localnet/orchestrator/start.sh /work/ -RUN chmod +x /work/start.sh - +COPY contrib/localnet/orchestrator/restart-zetaclientd.sh /work/ +RUN chmod +x /work/*.sh COPY --from=zeta /usr/local/bin/zetae2e /usr/local/bin/ RUN chmod +x /usr/local/bin/zetae2e -WORKDIR /work \ No newline at end of file +WORKDIR /work diff --git a/contrib/localnet/orchestrator/restart-zetaclientd.sh b/contrib/localnet/orchestrator/restart-zetaclientd.sh index 207eebf4aa..9b8f24e49f 100644 --- a/contrib/localnet/orchestrator/restart-zetaclientd.sh +++ b/contrib/localnet/orchestrator/restart-zetaclientd.sh @@ -1,5 +1,9 @@ #!/bin/bash +# This script is used to restart zetaclientd after an upgrade +# It waits for the upgrade height to be reached and then restarts the zetaclientd on all nodes in the network +# It interacts with the network using the zetaclientd binary + clibuilder() { echo "" diff --git a/contrib/localnet/orchestrator/smoketest/runner/evm.go b/contrib/localnet/orchestrator/smoketest/runner/evm.go deleted file mode 100644 index cd922ed673..0000000000 --- a/contrib/localnet/orchestrator/smoketest/runner/evm.go +++ /dev/null @@ -1,256 +0,0 @@ -package runner - -import ( - "math/big" - "time" - - ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/common/ethereum" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" -) - -var blockHeaderETHTimeout = 5 * time.Minute - -// WaitForTxReceiptOnEvm waits for a tx receipt on EVM -func (sm *SmokeTestRunner) WaitForTxReceiptOnEvm(tx *ethtypes.Transaction) { - defer func() { - sm.Unlock() - }() - sm.Lock() - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } -} - -// MintUSDTOnEvm mints USDT on EVM -// amountUSDT is a multiple of 1e18 -func (sm *SmokeTestRunner) MintUSDTOnEvm(amountUSDT int64) { - defer func() { - sm.Unlock() - }() - sm.Lock() - - amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(amountUSDT)) - - tx, err := sm.USDTERC20.Mint(sm.GoerliAuth, amount) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("mint failed") - } - sm.Logger.Info("Mint receipt tx hash: %s", tx.Hash().Hex()) -} - -// SendUSDTOnEvm sends USDT to an address on EVM -// this allows the USDT contract deployer to funds other accounts on EVM -// amountUSDT is a multiple of 1e18 -func (sm *SmokeTestRunner) SendUSDTOnEvm(address ethcommon.Address, amountUSDT int64) *ethtypes.Transaction { - // the deployer might be sending USDT in different goroutines - defer func() { - sm.Unlock() - }() - sm.Lock() - - amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(amountUSDT)) - - // transfer - tx, err := sm.USDTERC20.Transfer(sm.GoerliAuth, address, amount) - if err != nil { - panic(err) - } - return tx -} - -func (sm *SmokeTestRunner) DepositERC20() ethcommon.Hash { - sm.Logger.Print("⏳ depositing ERC20 into ZEVM") - - return sm.DepositERC20WithAmountAndMessage(big.NewInt(1e18), []byte{}) -} - -func (sm *SmokeTestRunner) DepositERC20WithAmountAndMessage(amount *big.Int, msg []byte) ethcommon.Hash { - // reset allowance, necessary for USDT - tx, err := sm.USDTERC20.Approve(sm.GoerliAuth, sm.ERC20CustodyAddr, big.NewInt(0)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - sm.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) - - tx, err = sm.USDTERC20.Approve(sm.GoerliAuth, sm.ERC20CustodyAddr, amount) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - sm.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) - - tx, err = sm.ERC20Custody.Deposit(sm.GoerliAuth, sm.DeployerAddress.Bytes(), sm.USDTERC20Addr, amount, msg) - sm.Logger.Print("TX: %v", tx) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit failed") - } - sm.Logger.Info("Deposit receipt tx hash: %s, status %d", receipt.TxHash.Hex(), receipt.Status) - for _, log := range receipt.Logs { - event, err := sm.ERC20Custody.ParseDeposited(*log) - if err != nil { - continue - } - sm.Logger.Info("Deposited event:") - sm.Logger.Info(" Recipient address: %x", event.Recipient) - sm.Logger.Info(" ERC20 address: %s", event.Asset.Hex()) - sm.Logger.Info(" Amount: %d", event.Amount) - sm.Logger.Info(" Message: %x", event.Message) - } - return tx.Hash() -} - -// DepositEther sends Ethers into ZEVM -func (sm *SmokeTestRunner) DepositEther(testHeader bool) ethcommon.Hash { - return sm.DepositEtherWithAmount(testHeader, big.NewInt(1000000000000000000)) // in wei (1 eth) -} - -// DepositEtherWithAmount sends Ethers into ZEVM -func (sm *SmokeTestRunner) DepositEtherWithAmount(testHeader bool, amount *big.Int) ethcommon.Hash { - sm.Logger.Print("⏳ depositing Ethers into ZEVM") - - signedTx, err := sm.SendEther(sm.TSSAddress, amount, nil) - if err != nil { - panic(err) - } - sm.Logger.EVMTransaction(*signedTx, "send to TSS") - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit failed") - } - sm.Logger.EVMReceipt(*receipt, "send to TSS") - - // due to the high block throughput in localnet, ZetaClient might catch up slowly with the blocks - // to optimize block header proof test, this test is directly executed here on the first deposit instead of having a separate test - if testHeader { - sm.ProveEthTransaction(receipt) - } - - return signedTx.Hash() -} - -// SendEther sends ethers to the TSS on Goerli -func (sm *SmokeTestRunner) SendEther(_ ethcommon.Address, value *big.Int, data []byte) (*ethtypes.Transaction, error) { - goerliClient := sm.GoerliClient - - nonce, err := goerliClient.PendingNonceAt(sm.Ctx, sm.DeployerAddress) - if err != nil { - return nil, err - } - - gasLimit := uint64(30000) // in units - gasPrice, err := goerliClient.SuggestGasPrice(sm.Ctx) - if err != nil { - return nil, err - } - - tx := ethtypes.NewTransaction(nonce, sm.TSSAddress, value, gasLimit, gasPrice, data) - chainID, err := goerliClient.NetworkID(sm.Ctx) - if err != nil { - return nil, err - } - - deployerPrivkey, err := crypto.HexToECDSA(sm.DeployerPrivateKey) - if err != nil { - return nil, err - } - - signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - return nil, err - } - err = goerliClient.SendTransaction(sm.Ctx, signedTx) - if err != nil { - return nil, err - } - - return signedTx, nil -} - -// ProveEthTransaction proves an ETH transaction on ZetaChain -func (sm *SmokeTestRunner) ProveEthTransaction(receipt *ethtypes.Receipt) { - startTime := time.Now() - - txHash := receipt.TxHash - blockHash := receipt.BlockHash - - // #nosec G701 smoketest - always in range - txIndex := int(receipt.TransactionIndex) - - block, err := sm.GoerliClient.BlockByHash(sm.Ctx, blockHash) - if err != nil { - panic(err) - } - for { - // check timeout - if time.Since(startTime) > blockHeaderETHTimeout { - panic("timeout waiting for block header") - } - - _, err := sm.ObserverClient.GetBlockHeaderByHash(sm.Ctx, &observertypes.QueryGetBlockHeaderByHashRequest{ - BlockHash: blockHash.Bytes(), - }) - if err != nil { - sm.Logger.Info("WARN: block header not found; retrying... error: %s", err.Error()) - } else { - sm.Logger.Info("OK: block header found") - break - } - - time.Sleep(2 * time.Second) - } - - trie := ethereum.NewTrie(block.Transactions()) - if trie.Hash() != block.Header().TxHash { - panic("tx root hash & block tx root mismatch") - } - txProof, err := trie.GenerateProof(txIndex) - if err != nil { - panic("error generating txProof") - } - val, err := txProof.Verify(block.TxHash(), txIndex) - if err != nil { - panic("error verifying txProof") - } - var txx ethtypes.Transaction - err = txx.UnmarshalBinary(val) - if err != nil { - panic("error unmarshalling txProof'd tx") - } - res, err := sm.ObserverClient.Prove(sm.Ctx, &observertypes.QueryProveRequest{ - BlockHash: blockHash.Hex(), - TxIndex: int64(txIndex), - TxHash: txHash.Hex(), - Proof: common.NewEthereumProof(txProof), - ChainId: common.GoerliLocalnetChain().ChainId, - }) - if err != nil { - panic(err) - } - if !res.Valid { - panic("txProof invalid") // FIXME: don't do this in production - } - sm.Logger.Info("OK: txProof verified") -} diff --git a/contrib/localnet/orchestrator/smoketest/runner/setup_evm.go b/contrib/localnet/orchestrator/smoketest/runner/setup_evm.go deleted file mode 100644 index 135dcd3119..0000000000 --- a/contrib/localnet/orchestrator/smoketest/runner/setup_evm.go +++ /dev/null @@ -1,186 +0,0 @@ -package runner - -import ( - "math/big" - "time" - - "github.com/zeta-chain/zetacore/zetaclient/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol" - zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol" - zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/config" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/erc20" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/testdapp" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -const ( - ContractsConfigFile = "contracts.toml" -) - -// SetEVMContractsFromConfig set EVM contracts for smoke test from the config -func (sm *SmokeTestRunner) SetEVMContractsFromConfig() { - conf, err := config.ReadConfig(ContractsConfigFile) - if err != nil { - panic(err) - } - - // Set ZetaEthAddr - sm.ZetaEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ZetaEthAddress) - sm.ZetaEth, err = zetaeth.NewZetaEth(sm.ZetaEthAddr, sm.GoerliClient) - if err != nil { - panic(err) - } - - // Set ConnectorEthAddr - sm.ConnectorEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ConnectorEthAddr) - sm.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(sm.ConnectorEthAddr, sm.GoerliClient) - if err != nil { - panic(err) - } -} - -// SetupEVM setup contracts on EVM for smoke test -func (sm *SmokeTestRunner) SetupEVM(contractsDeployed bool) { - sm.Logger.Print("⚙️ setting up Goerli network") - startTime := time.Now() - defer func() { - sm.Logger.Info("EVM setup took %s\n", time.Since(startTime)) - }() - - // TODO: put this logic outside of this function - // We use this config to be consistent with the old implementation - // https://github.com/zeta-chain/node-private/issues/41 - if contractsDeployed { - sm.SetEVMContractsFromConfig() - return - } - conf := config.DefaultConfig() - - sm.Logger.InfoLoud("Deploy ZetaETH ConnectorETH ERC20Custody USDT\n") - - // donate to the TSS address to avoid account errors because deploying gas token ZRC20 will automatically mint - // gas token on ZetaChain to initialize the pool - txDonation, err := sm.SendEther(sm.TSSAddress, big.NewInt(101000000000000000), []byte(evm.DonationMessage)) - if err != nil { - panic(err) - } - - sm.Logger.Info("Deploying ZetaEth contract") - zetaEthAddr, txZetaEth, ZetaEth, err := zetaeth.DeployZetaEth( - sm.GoerliAuth, - sm.GoerliClient, - sm.DeployerAddress, - big.NewInt(21_000_000_000), - ) - if err != nil { - panic(err) - } - sm.ZetaEth = ZetaEth - sm.ZetaEthAddr = zetaEthAddr - conf.Contracts.EVM.ZetaEthAddress = zetaEthAddr.String() - sm.Logger.Info("ZetaEth contract address: %s, tx hash: %s", zetaEthAddr.Hex(), zetaEthAddr.Hash().Hex()) - - sm.Logger.Info("Deploying ZetaConnectorEth contract") - connectorEthAddr, txConnector, ConnectorEth, err := zetaconnectoreth.DeployZetaConnectorEth( - sm.GoerliAuth, - sm.GoerliClient, - zetaEthAddr, - sm.TSSAddress, - sm.DeployerAddress, - sm.DeployerAddress, - ) - if err != nil { - panic(err) - } - sm.ConnectorEth = ConnectorEth - sm.ConnectorEthAddr = connectorEthAddr - conf.Contracts.EVM.ConnectorEthAddr = connectorEthAddr.String() - - sm.Logger.Info("ZetaConnectorEth contract address: %s, tx hash: %s", connectorEthAddr.Hex(), txConnector.Hash().Hex()) - - sm.Logger.Info("Deploying ERC20Custody contract") - erc20CustodyAddr, txCustody, ERC20Custody, err := erc20custody.DeployERC20Custody( - sm.GoerliAuth, - sm.GoerliClient, - sm.DeployerAddress, - sm.DeployerAddress, - big.NewInt(0), - big.NewInt(1e18), - ethcommon.HexToAddress("0x"), - ) - if err != nil { - panic(err) - } - sm.ERC20CustodyAddr = erc20CustodyAddr - sm.ERC20Custody = ERC20Custody - sm.Logger.Info("ERC20Custody contract address: %s, tx hash: %s", erc20CustodyAddr.Hex(), txCustody.Hash().Hex()) - - sm.Logger.Info("Deploying USDT contract") - usdtAddr, txUSDT, usdt, err := erc20.DeployUSDT(sm.GoerliAuth, sm.GoerliClient, "USDT", "USDT", 6) - if err != nil { - panic(err) - } - sm.USDTERC20 = usdt - sm.USDTERC20Addr = usdtAddr - sm.Logger.Info("USDT contract address: %s, tx hash: %s", usdtAddr.Hex(), txUSDT.Hash().Hex()) - - // deploy TestDApp contract - appAddr, txApp, _, err := testdapp.DeployTestDApp(sm.GoerliAuth, sm.GoerliClient, sm.ConnectorEthAddr, sm.ZetaEthAddr) - if err != nil { - panic(err) - } - sm.TestDAppAddr = appAddr - sm.Logger.Info("TestDApp contract address: %s, tx hash: %s", appAddr.Hex(), txApp.Hash().Hex()) - - // check contract deployment receipt - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txDonation, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("GOERLI donation tx failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txZetaEth, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("ZetaEth deployment failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txConnector, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("ZetaConnectorEth deployment failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txCustody, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("ERC20Custody deployment failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txUSDT, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("USDT deployment failed") - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txApp, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("TestDApp deployment failed") - } - - // initialize custody contract - sm.Logger.Info("Whitelist USDT") - txWhitelist, err := ERC20Custody.Whitelist(sm.GoerliAuth, usdtAddr) - if err != nil { - panic(err) - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txWhitelist, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("USDT whitelist failed") - } - - sm.Logger.Info("Set TSS address") - txCustody, err = ERC20Custody.UpdateTSSAddress(sm.GoerliAuth, sm.TSSAddress) - if err != nil { - panic(err) - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txCustody, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("USDT update TSS address failed") - } - sm.Logger.Info("TSS set receipt tx hash: %s", txCustody.Hash().Hex()) - - // save config containing contract addresses - // TODO: put this logic outside of this function in a general config - // We use this config to be consistent with the old implementation - // https://github.com/zeta-chain/node-private/issues/41 - if err := config.WriteConfig(ContractsConfigFile, conf); err != nil { - panic(err) - } -} diff --git a/contrib/localnet/orchestrator/smoketest/runner/setup_zeta.go b/contrib/localnet/orchestrator/smoketest/runner/setup_zeta.go deleted file mode 100644 index b40056f707..0000000000 --- a/contrib/localnet/orchestrator/smoketest/runner/setup_zeta.go +++ /dev/null @@ -1,199 +0,0 @@ -package runner - -import ( - "math/big" - "time" - - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/connectorzevm.sol" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/wzeta.sol" - - "github.com/btcsuite/btcutil" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" - "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-core/contracts/uniswapv2factory.sol" - uniswapv2router "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-periphery/contracts/uniswapv2router02.sol" - "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/contextapp" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/zevmswap" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" -) - -// SetTSSAddresses set TSS addresses from information queried from ZetaChain -func (sm *SmokeTestRunner) SetTSSAddresses() error { - sm.Logger.Print("⚙️ setting up TSS address") - - btcChainID, err := common.GetBTCChainIDFromChainParams(sm.BitcoinParams) - if err != nil { - return err - } - - res := &observertypes.QueryGetTssAddressResponse{} - for i := 0; ; i++ { - res, err = sm.ObserverClient.GetTssAddress(sm.Ctx, &observertypes.QueryGetTssAddressRequest{ - BitcoinChainId: btcChainID, - }) - if err != nil { - if i%10 == 0 { - sm.Logger.Info("ObserverClient.TSS error %s", err.Error()) - sm.Logger.Info("TSS not ready yet, waiting for TSS to be appear in zetacore network...") - } - time.Sleep(1 * time.Second) - continue - } - break - } - - tssAddress := ethcommon.HexToAddress(res.Eth) - - btcTSSAddress, err := btcutil.DecodeAddress(res.Btc, sm.BitcoinParams) - if err != nil { - panic(err) - } - - sm.TSSAddress = tssAddress - sm.BTCTSSAddress = btcTSSAddress - - return nil -} - -// SetZEVMContracts set contracts for the ZEVM -func (sm *SmokeTestRunner) SetZEVMContracts() { - sm.Logger.Print("⚙️ deploying system contracts and ZRC20s on ZEVM") - startTime := time.Now() - defer func() { - sm.Logger.Info("System contract deployments took %s\n", time.Since(startTime)) - }() - - // deploy system contracts and ZRC20 contracts on ZetaChain - uniswapV2FactoryAddr, uniswapV2RouterAddr, zevmConnectorAddr, wzetaAddr, usdtZRC20Addr, err := sm.ZetaTxServer.DeploySystemContractsAndZRC20( - utils.FungibleAdminName, - sm.USDTERC20Addr.Hex(), - ) - if err != nil { - panic(err) - } - - // Set USDTZRC20Addr - sm.USDTZRC20Addr = ethcommon.HexToAddress(usdtZRC20Addr) - sm.USDTZRC20, err = zrc20.NewZRC20(sm.USDTZRC20Addr, sm.ZevmClient) - if err != nil { - panic(err) - } - - // UniswapV2FactoryAddr - sm.UniswapV2FactoryAddr = ethcommon.HexToAddress(uniswapV2FactoryAddr) - sm.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(sm.UniswapV2FactoryAddr, sm.ZevmClient) - if err != nil { - panic(err) - } - - // UniswapV2RouterAddr - sm.UniswapV2RouterAddr = ethcommon.HexToAddress(uniswapV2RouterAddr) - sm.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(sm.UniswapV2RouterAddr, sm.ZevmClient) - if err != nil { - panic(err) - } - - // ZevmConnectorAddr - sm.ConnectorZEVMAddr = ethcommon.HexToAddress(zevmConnectorAddr) - sm.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(sm.ConnectorZEVMAddr, sm.ZevmClient) - if err != nil { - panic(err) - } - - // WZetaAddr - sm.WZetaAddr = ethcommon.HexToAddress(wzetaAddr) - sm.WZeta, err = wzeta.NewWETH9(sm.WZetaAddr, sm.ZevmClient) - if err != nil { - panic(err) - } - - // query system contract address from the chain - systemContractRes, err := sm.FungibleClient.SystemContract( - sm.Ctx, - &fungibletypes.QueryGetSystemContractRequest{}, - ) - if err != nil { - panic(err) - } - systemContractAddr := ethcommon.HexToAddress(systemContractRes.SystemContract.SystemContract) - - SystemContract, err := systemcontract.NewSystemContract( - systemContractAddr, - sm.ZevmClient, - ) - if err != nil { - panic(err) - } - - sm.SystemContract = SystemContract - sm.SystemContractAddr = systemContractAddr - - // set ZRC20 contracts - sm.SetupETHZRC20() - sm.SetupBTCZRC20() - - // deploy ZEVMSwapApp and ContextApp - zevmSwapAppAddr, txZEVMSwapApp, zevmSwapApp, err := zevmswap.DeployZEVMSwapApp( - sm.ZevmAuth, - sm.ZevmClient, - sm.UniswapV2RouterAddr, - sm.SystemContractAddr, - ) - if err != nil { - panic(err) - } - - contextAppAddr, txContextApp, contextApp, err := contextapp.DeployContextApp(sm.ZevmAuth, sm.ZevmClient) - if err != nil { - panic(err) - } - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txZEVMSwapApp, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("ZEVMSwapApp deployment failed") - } - sm.ZEVMSwapAppAddr = zevmSwapAppAddr - sm.ZEVMSwapApp = zevmSwapApp - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txContextApp, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("ContextApp deployment failed") - } - sm.ContextAppAddr = contextAppAddr - sm.ContextApp = contextApp -} - -func (sm *SmokeTestRunner) SetupETHZRC20() { - ethZRC20Addr, err := sm.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(common.GoerliLocalnetChain().ChainId)) - if err != nil { - panic(err) - } - if (ethZRC20Addr == ethcommon.Address{}) { - panic("eth zrc20 not found") - } - sm.ETHZRC20Addr = ethZRC20Addr - ethZRC20, err := zrc20.NewZRC20(ethZRC20Addr, sm.ZevmClient) - if err != nil { - panic(err) - } - sm.ETHZRC20 = ethZRC20 -} - -func (sm *SmokeTestRunner) SetupBTCZRC20() { - BTCZRC20Addr, err := sm.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(common.BtcRegtestChain().ChainId)) - if err != nil { - panic(err) - } - sm.BTCZRC20Addr = BTCZRC20Addr - sm.Logger.Info("BTCZRC20Addr: %s", BTCZRC20Addr.Hex()) - BTCZRC20, err := zrc20.NewZRC20(BTCZRC20Addr, sm.ZevmClient) - if err != nil { - panic(err) - } - sm.BTCZRC20 = BTCZRC20 -} diff --git a/contrib/localnet/orchestrator/smoketest/runner/zeta.go b/contrib/localnet/orchestrator/smoketest/runner/zeta.go deleted file mode 100644 index c2405b21de..0000000000 --- a/contrib/localnet/orchestrator/smoketest/runner/zeta.go +++ /dev/null @@ -1,111 +0,0 @@ -package runner - -import ( - "fmt" - "math/big" - - ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -// WaitForMinedCCTX waits for a cctx to be mined from a tx -func (sm *SmokeTestRunner) WaitForMinedCCTX(txHash ethcommon.Hash) { - defer func() { - sm.Unlock() - }() - sm.Lock() - - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, txHash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf("expected cctx status to be mined; got %s, message: %s", - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage), - ) - } -} - -// SendZetaOnEvm sends ZETA to an address on EVM -// this allows the ZETA contract deployer to funds other accounts on EVM -func (sm *SmokeTestRunner) SendZetaOnEvm(address ethcommon.Address, zetaAmount int64) *ethtypes.Transaction { - // the deployer might be sending ZETA in different goroutines - defer func() { - sm.Unlock() - }() - sm.Lock() - - amount := big.NewInt(1e18) - amount = amount.Mul(amount, big.NewInt(zetaAmount)) - tx, err := sm.ZetaEth.Transfer(sm.GoerliAuth, address, amount) - if err != nil { - panic(err) - } - return tx -} - -// DepositZeta deposits ZETA on ZetaChain from the ZETA smart contract on EVM -func (sm *SmokeTestRunner) DepositZeta() ethcommon.Hash { - amount := big.NewInt(1e18) - amount = amount.Mul(amount, big.NewInt(100)) // 100 Zeta - - return sm.DepositZetaWithAmount(amount) -} - -// DepositZetaWithAmount deposits ZETA on ZetaChain from the ZETA smart contract on EVM with the specified amount -func (sm *SmokeTestRunner) DepositZetaWithAmount(amount *big.Int) ethcommon.Hash { - tx, err := sm.ZetaEth.Approve(sm.GoerliAuth, sm.ConnectorEthAddr, amount) - if err != nil { - panic(err) - } - sm.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "approve") - if receipt.Status != 1 { - panic("approve tx failed") - } - - // query the chain ID using zevm client - zetaChainID, err := sm.ZevmClient.ChainID(sm.Ctx) - if err != nil { - panic(err) - } - - tx, err = sm.ConnectorEth.Send(sm.GoerliAuth, zetaconnectoreth.ZetaInterfacesSendInput{ - // TODO: allow user to specify destination chain id - // https://github.com/zeta-chain/node-private/issues/41 - DestinationChainId: zetaChainID, - DestinationAddress: sm.DeployerAddress.Bytes(), - DestinationGasLimit: big.NewInt(250_000), - Message: nil, - ZetaValueAndGas: amount, - ZetaParams: nil, - }) - if err != nil { - panic(err) - } - sm.Logger.Info("Send tx hash: %s", tx.Hash().Hex()) - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "send") - if receipt.Status != 1 { - panic(fmt.Sprintf("expected tx receipt status to be 1; got %d", receipt.Status)) - } - - sm.Logger.Info(" Logs:") - for _, log := range receipt.Logs { - sentLog, err := sm.ConnectorEth.ParseZetaSent(*log) - if err == nil { - sm.Logger.Info(" Connector: %s", sm.ConnectorEthAddr.String()) - sm.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) - sm.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) - sm.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) - sm.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) - sm.Logger.Info(" Block Num: %d", log.BlockNumber) - } - } - - return tx.Hash() -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_bitcoin_deposit.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_bitcoin_deposit.go deleted file mode 100644 index c16834725b..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_bitcoin_deposit.go +++ /dev/null @@ -1,27 +0,0 @@ -package smoketests - -import ( - "fmt" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func TestBitcoinDeposit(sm *runner.SmokeTestRunner) { - - sm.SetBtcAddress(sm.Name, false) - - txHash := sm.DepositBTCWithAmount(0.001) - - // wait for the cctx to be mined - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, txHash.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "deposit") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected mined status; got %s, message: %s", - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage), - ) - } -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_bitcoin_withdraw.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_bitcoin_withdraw.go deleted file mode 100644 index 02a84e8403..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_bitcoin_withdraw.go +++ /dev/null @@ -1,228 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -func TestBitcoinWithdraw(sm *runner.SmokeTestRunner) { - // withdraw 0.1 BTC from ZRC20 to BTC address - // first, approve the ZRC20 contract to spend 1 BTC from the deployer address - WithdrawBitcoin(sm) -} - -func WithdrawBitcoin(sm *runner.SmokeTestRunner) { - amount := big.NewInt(0.1 * btcutil.SatoshiPerBitcoin) - - // approve the ZRC20 contract to spend 1 BTC from the deployer address - tx, err := sm.BTCZRC20.Approve(sm.ZevmAuth, sm.BTCZRC20Addr, big.NewInt(amount.Int64()*2)) // approve more to cover withdraw fee - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic(fmt.Errorf("approve receipt status is not 1")) - } - - // mine blocks - stop := sm.MineBlocks() - - // withdraw 0.1 BTC from ZRC20 to BTC address - tx, err = sm.BTCZRC20.Withdraw(sm.ZevmAuth, []byte(sm.BTCDeployerAddress.EncodeAddress()), amount) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic(fmt.Errorf("withdraw receipt status is not 1")) - } - - // mine 10 blocks to confirm the withdraw tx - _, err = sm.BtcRPCClient.GenerateToAddress(10, sm.BTCDeployerAddress, nil) - if err != nil { - panic(err) - } - - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, receipt.TxHash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - outTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash - hash, err := chainhash.NewHashFromStr(outTxHash) - if err != nil { - panic(err) - } - - rawTx, err := sm.BtcRPCClient.GetRawTransactionVerbose(hash) - if err != nil { - panic(err) - } - sm.Logger.Info("raw tx:") - sm.Logger.Info(" TxIn: %d", len(rawTx.Vin)) - for idx, txIn := range rawTx.Vin { - sm.Logger.Info(" TxIn %d:", idx) - sm.Logger.Info(" TxID:Vout: %s:%d", txIn.Txid, txIn.Vout) - sm.Logger.Info(" ScriptSig: %s", txIn.ScriptSig.Hex) - } - sm.Logger.Info(" TxOut: %d", len(rawTx.Vout)) - for _, txOut := range rawTx.Vout { - sm.Logger.Info(" TxOut %d:", txOut.N) - sm.Logger.Info(" Value: %.8f", txOut.Value) - sm.Logger.Info(" ScriptPubKey: %s", txOut.ScriptPubKey.Hex) - } - - // stop mining - stop <- struct{}{} -} - -// WithdrawBitcoinMultipleTimes ... -// TODO: define smoke test -// https://github.com/zeta-chain/node-private/issues/79 -//func WithdrawBitcoinMultipleTimes(sm *runner.SmokeTestRunner, repeat int64) { -// totalAmount := big.NewInt(int64(0.1 * 1e8)) -// -// // #nosec G701 smoketest - always in range -// amount := big.NewInt(int64(0.1 * 1e8 / float64(repeat))) -// -// // check if the deposit is successful -// BTCZRC20Addr, err := sm.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(common.BtcRegtestChain().ChainId)) -// if err != nil { -// panic(err) -// } -// sm.Logger.Info("BTCZRC20Addr: %s", BTCZRC20Addr.Hex()) -// BTCZRC20, err := zrc20.NewZRC20(BTCZRC20Addr, sm.ZevmClient) -// if err != nil { -// panic(err) -// } -// balance, err := BTCZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) -// if err != nil { -// panic(err) -// } -// if balance.Cmp(totalAmount) < 0 { -// panic(fmt.Errorf("not enough balance in ZRC20 contract")) -// } -// // approve the ZRC20 contract to spend 1 BTC from the deployer address -// { -// // approve more to cover withdraw fee -// tx, err := BTCZRC20.Approve(sm.ZevmAuth, BTCZRC20Addr, totalAmount.Mul(totalAmount, big.NewInt(100))) -// if err != nil { -// panic(err) -// } -// receipt := config.MustWaitForTxReceipt(sm.ZevmClient, tx, sm.Logger) -// sm.Logger.Info("approve receipt: status %d", receipt.Status) -// if receipt.Status != 1 { -// panic(fmt.Errorf("approve receipt status is not 1")) -// } -// } -// go func() { -// for { -// time.Sleep(3 * time.Second) -// _, err = sm.BtcRPCClient.GenerateToAddress(1, sm.BTCDeployerAddress, nil) -// if err != nil { -// panic(err) -// } -// } -// }() -// // withdraw 0.1 BTC from ZRC20 to BTC address -// for i := int64(0); i < repeat; i++ { -// _, gasFee, err := BTCZRC20.WithdrawGasFee(&bind.CallOpts{}) -// if err != nil { -// panic(err) -// } -// sm.Logger.Info("withdraw gas fee: %d", gasFee) -// tx, err := BTCZRC20.Withdraw(sm.ZevmAuth, []byte(sm.BTCDeployerAddress.EncodeAddress()), amount) -// if err != nil { -// panic(err) -// } -// receipt := config.MustWaitForTxReceipt(sm.ZevmClient, tx, sm.Logger) -// sm.Logger.Info("withdraw receipt: status %d", receipt.Status) -// if receipt.Status != 1 { -// panic(fmt.Errorf("withdraw receipt status is not 1")) -// } -// _, err = sm.BtcRPCClient.GenerateToAddress(10, sm.BTCDeployerAddress, nil) -// if err != nil { -// panic(err) -// } -// cctx := config.WaitCctxMinedByInTxHash(receipt.TxHash.Hex(), sm.CctxClient, sm.Logger) -// outTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash -// hash, err := chainhash.NewHashFromStr(outTxHash) -// if err != nil { -// panic(err) -// } -// -// rawTx, err := sm.BtcRPCClient.GetRawTransactionVerbose(hash) -// if err != nil { -// panic(err) -// } -// sm.Logger.Info("raw tx:") -// sm.Logger.Info(" TxIn: %d", len(rawTx.Vin)) -// for idx, txIn := range rawTx.Vin { -// sm.Logger.Info(" TxIn %d:", idx) -// sm.Logger.Info(" TxID:Vout: %s:%d", txIn.Txid, txIn.Vout) -// sm.Logger.Info(" ScriptSig: %s", txIn.ScriptSig.Hex) -// } -// sm.Logger.Info(" TxOut: %d", len(rawTx.Vout)) -// for _, txOut := range rawTx.Vout { -// sm.Logger.Info(" TxOut %d:", txOut.N) -// sm.Logger.Info(" Value: %.8f", txOut.Value) -// sm.Logger.Info(" ScriptPubKey: %s", txOut.ScriptPubKey.Hex) -// } -// } -//} - -// DepositBTCRefund ... -// TODO: define smoke test -// https://github.com/zeta-chain/node-private/issues/79 -//func DepositBTCRefund(sm *runner.SmokeTestRunner) { -// sm.Logger.InfoLoud("Deposit BTC with invalid memo; should be refunded") -// btc := sm.BtcRPCClient -// utxos, err := sm.BtcRPCClient.ListUnspent() -// if err != nil { -// panic(err) -// } -// spendableAmount := 0.0 -// spendableUTXOs := 0 -// for _, utxo := range utxos { -// if utxo.Spendable { -// spendableAmount += utxo.Amount -// spendableUTXOs++ -// } -// } -// sm.Logger.Info("ListUnspent:") -// sm.Logger.Info(" spendableAmount: %f", spendableAmount) -// sm.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) -// sm.Logger.Info("Now sending two txs to TSS address...") -// _, err = sm.SendToTSSFromDeployerToDeposit(sm.BTCTSSAddress, 1.1, utxos[:2], btc, sm.BTCDeployerAddress) -// if err != nil { -// panic(err) -// } -// _, err = sm.SendToTSSFromDeployerToDeposit(sm.BTCTSSAddress, 0.05, utxos[2:4], btc, sm.BTCDeployerAddress) -// if err != nil { -// panic(err) -// } -// -// sm.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") -// -// // check if the deposit is successful -// initialBalance, err := sm.BTCZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) -// if err != nil { -// panic(err) -// } -// for { -// time.Sleep(3 * time.Second) -// balance, err := sm.BTCZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) -// if err != nil { -// panic(err) -// } -// diff := big.NewInt(0) -// diff.Sub(balance, initialBalance) -// if diff.Cmp(big.NewInt(1.15*btcutil.SatoshiPerBitcoin)) != 0 { -// sm.Logger.Info("waiting for BTC balance to show up in ZRC contract... current bal %d", balance) -// } else { -// sm.Logger.Info("BTC balance is in ZRC contract! Success") -// break -// } -// } -//} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_context.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_context.go deleted file mode 100644 index 63c266f311..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_context.go +++ /dev/null @@ -1,76 +0,0 @@ -package smoketests - -import ( - "bytes" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -// TestContextUpgrade tests sending ETH on ZetaChain and check context data -func TestContextUpgrade(sm *runner.SmokeTestRunner) { - value := big.NewInt(1000000000000000) // in wei (1 eth) - data := make([]byte, 0, 32) - data = append(data, sm.ContextAppAddr.Bytes()...) - data = append(data, []byte("filler")...) // just to make sure that this is a contract call; - - signedTx, err := sm.SendEther(sm.TSSAddress, value, data) - if err != nil { - panic(err) - } - - sm.Logger.Info("GOERLI tx sent: %s; to %s, nonce %d", signedTx.Hash().String(), signedTx.To().Hex(), signedTx.Nonce()) - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } - sm.Logger.Info("GOERLI tx receipt: %d", receipt.Status) - sm.Logger.Info(" tx hash: %s", receipt.TxHash.String()) - sm.Logger.Info(" to: %s", signedTx.To().String()) - sm.Logger.Info(" value: %d", signedTx.Value()) - sm.Logger.Info(" block num: %d", receipt.BlockNumber) - sm.Logger.Info(" data: %x", signedTx.Data()) - - found := false - for i := 0; i < 10; i++ { - eventIter, err := sm.ContextApp.FilterContextData(&bind.FilterOpts{ - Start: 0, - End: nil, - }) - if err != nil { - sm.Logger.Info("filter error: %s", err.Error()) - continue - } - for eventIter.Next() { - sm.Logger.Info("event: ContextData") - sm.Logger.Info(" origin: %x", eventIter.Event.Origin) - sm.Logger.Info(" sender: %s", eventIter.Event.Sender.Hex()) - sm.Logger.Info(" chainid: %d", eventIter.Event.ChainID) - sm.Logger.Info(" msgsender: %s", eventIter.Event.MsgSender.Hex()) - found = true - if bytes.Compare(eventIter.Event.Origin, sm.DeployerAddress.Bytes()) != 0 { - panic("origin mismatch") - } - chainID, err := sm.GoerliClient.ChainID(sm.Ctx) - if err != nil { - panic(err) - } - if eventIter.Event.ChainID.Cmp(chainID) != 0 { - panic("chainID mismatch") - } - - } - if found { - break - } - time.Sleep(2 * time.Second) - } - - if !found { - panic("event not found") - } - -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_crosschain_swap.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_crosschain_swap.go deleted file mode 100644 index 803d5b6a7c..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_crosschain_swap.go +++ /dev/null @@ -1,239 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - "time" - - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func TestCrosschainSwap(sm *runner.SmokeTestRunner) { - sm.ZevmAuth.GasLimit = 10000000 - - // TODO: move into setup and skip it if already initialized - // https://github.com/zeta-chain/node-private/issues/88 - // it is kept as is for now to be consistent with the old implementation - // if the tx fails due to already initialized, it will be ignored - _, err := sm.UniswapV2Factory.CreatePair(sm.ZevmAuth, sm.USDTZRC20Addr, sm.BTCZRC20Addr) - if err != nil { - sm.Logger.Print("ℹ️create pair error") - } - txUSDTApprove, err := sm.USDTZRC20.Approve(sm.ZevmAuth, sm.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - txBTCApprove, err := sm.BTCZRC20.Approve(sm.ZevmAuth, sm.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - - // Fund ZEVMSwapApp with gas ZRC20s - txTransferETH, err := sm.ETHZRC20.Transfer(sm.ZevmAuth, sm.ZEVMSwapAppAddr, big.NewInt(1e7)) - if err != nil { - panic(err) - } - txTransferBTC, err := sm.BTCZRC20.Transfer(sm.ZevmAuth, sm.ZEVMSwapAppAddr, big.NewInt(1e6)) - if err != nil { - panic(err) - } - - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txUSDTApprove, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("usdt approve failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txBTCApprove, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("btc approve failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txTransferETH, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("ETH ZRC20 transfer failed") - } - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txTransferBTC, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("BTC ZRC20 transfer failed") - } - - // Add 100 USDT liq and 0.001 BTC - txAddLiquidity, err := sm.UniswapV2Router.AddLiquidity( - sm.ZevmAuth, - sm.USDTZRC20Addr, - sm.BTCZRC20Addr, - big.NewInt(1e8), - big.NewInt(1e8), - big.NewInt(1e8), - big.NewInt(1e5), - sm.DeployerAddress, - big.NewInt(time.Now().Add(10*time.Minute).Unix()), - ) - if err != nil { - panic(fmt.Sprintf("Error liq %s", err.Error())) - } - - if receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, txAddLiquidity, sm.Logger, sm.ReceiptTimeout); receipt.Status != 1 { - panic("add liq receipt status is not 1") - } - - // msg would be [ZEVMSwapAppAddr, memobytes] - // memobytes is dApp specific; see the contracts/ZEVMSwapApp.sol for details - msg := []byte{} - msg = append(msg, sm.ZEVMSwapAppAddr.Bytes()...) - memobytes, err := sm.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, sm.BTCZRC20Addr, []byte(sm.BTCDeployerAddress.EncodeAddress())) - - if err != nil { - panic(err) - } - sm.Logger.Info("memobytes(%d) %x", len(memobytes), memobytes) - msg = append(msg, memobytes...) - - sm.Logger.Info("***** First test: USDT -> BTC") - // Should deposit USDT for swap, swap for BTC and withdraw BTC - txHash := sm.DepositERC20WithAmountAndMessage(big.NewInt(8e7), msg) - cctx1 := utils.WaitCctxMinedByInTxHash(sm.Ctx, txHash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - - // check the cctx status - if cctx1.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf("expected outbound mined status; got %s, message: %s", cctx1.CctxStatus.Status.String(), cctx1.CctxStatus.StatusMessage)) - } - - // mine 10 blocks to confirm the outbound tx - _, err = sm.BtcRPCClient.GenerateToAddress(10, sm.BTCDeployerAddress, nil) - if err != nil { - panic(err) - } - stop := sm.MineBlocks() - - // cctx1 index acts like the inTxHash for the second cctx (the one that withdraws BTC) - cctx2 := utils.WaitCctxMinedByInTxHash(sm.Ctx, cctx1.Index, sm.CctxClient, sm.Logger, sm.CctxTimeout) - - // check the cctx status - if cctx2.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx2.CctxStatus.Status.String(), - cctx2.CctxStatus.StatusMessage), - ) - } - - sm.Logger.Info("cctx2 outbound tx hash %s", cctx2.GetCurrentOutTxParam().OutboundTxHash) - - sm.Logger.Info("******* Second test: BTC -> USDT") - utxos, err := sm.BtcRPCClient.ListUnspent() - if err != nil { - panic(err) - } - sm.Logger.Info("#utxos %d", len(utxos)) - sm.Logger.Info("memo address %s", sm.USDTZRC20Addr) - memo, err := sm.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, sm.USDTZRC20Addr, sm.DeployerAddress.Bytes()) - if err != nil { - panic(err) - } - memo = append(sm.ZEVMSwapAppAddr.Bytes(), memo...) - sm.Logger.Info("memo length %d", len(memo)) - - txID, err := sm.SendToTSSFromDeployerWithMemo( - sm.BTCTSSAddress, - 0.01, - utxos[0:2], - sm.BtcRPCClient, - memo, - sm.BTCDeployerAddress, - ) - if err != nil { - panic(err) - } - sm.Logger.Info("Sent BTC to TSS txid %s; now mining 10 blocks for confirmation", txID) - _, err = sm.BtcRPCClient.GenerateToAddress(10, sm.BTCDeployerAddress, nil) - if err != nil { - panic(err) - } - - cctx3 := utils.WaitCctxMinedByInTxHash(sm.Ctx, txID.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx3.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx3.CctxStatus.Status.String(), - cctx3.CctxStatus.StatusMessage), - ) - } - sm.Logger.Info("cctx3 index %s", cctx3.Index) - sm.Logger.Info(" inbound tx hash %s", cctx3.InboundTxParams.InboundTxObservedHash) - sm.Logger.Info(" status %s", cctx3.CctxStatus.Status.String()) - sm.Logger.Info(" status msg: %s", cctx3.CctxStatus.StatusMessage) - - cctx4 := utils.WaitCctxMinedByInTxHash(sm.Ctx, cctx3.Index, sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx4.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx3.CctxStatus.Status.String(), - cctx3.CctxStatus.StatusMessage), - ) - } - sm.Logger.Info("cctx4 index %s", cctx4.Index) - sm.Logger.Info(" outbound tx hash %s", cctx4.GetCurrentOutTxParam().OutboundTxHash) - sm.Logger.Info(" status %s", cctx4.CctxStatus.Status.String()) - - { - sm.Logger.Info("******* Third test: BTC -> ETH with contract call reverted; should refund BTC") - utxos, err := sm.BtcRPCClient.ListUnspent() - if err != nil { - panic(err) - } - sm.Logger.Info("#utxos %d", len(utxos)) - // the following memo will result in a revert in the contract call as targetZRC20 is set to DeployerAddress - // which is apparently not a ZRC20 contract; the UNISWAP call will revert - memo, err := sm.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, sm.DeployerAddress, sm.DeployerAddress.Bytes()) - if err != nil { - panic(err) - } - memo = append(sm.ZEVMSwapAppAddr.Bytes(), memo...) - sm.Logger.Info("memo length %d", len(memo)) - - amount := 0.1 - txid, err := sm.SendToTSSFromDeployerWithMemo( - sm.BTCTSSAddress, - amount, - utxos[0:2], - sm.BtcRPCClient, - memo, - sm.BTCDeployerAddress, - ) - if err != nil { - panic(err) - } - sm.Logger.Info("Sent BTC to TSS txid %s; now mining 10 blocks for confirmation", txid) - _, err = sm.BtcRPCClient.GenerateToAddress(10, sm.BTCDeployerAddress, nil) - if err != nil { - panic(err) - } - - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, txid.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.Info("cctx3 index %s", cctx.Index) - sm.Logger.Info(" inbound tx hash %s", cctx.InboundTxParams.InboundTxObservedHash) - sm.Logger.Info(" status %s", cctx.CctxStatus.Status.String()) - sm.Logger.Info(" status msg: %s", cctx.CctxStatus.StatusMessage) - - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected reverted status; got %s", cctx.CctxStatus.Status.String())) - } - outTxHash, err := chainhash.NewHashFromStr(cctx.GetCurrentOutTxParam().OutboundTxHash) - if err != nil { - panic(err) - } - txraw, err := sm.BtcRPCClient.GetRawTransactionVerbose(outTxHash) - if err != nil { - panic(err) - } - sm.Logger.Info("out txid %s", txraw.Txid) - for _, vout := range txraw.Vout { - sm.Logger.Info(" vout %d", vout.N) - sm.Logger.Info(" value %f", vout.Value) - sm.Logger.Info(" scriptPubKey %s", vout.ScriptPubKey.Hex) - sm.Logger.Info(" p2wpkh address: %s", utils.ScriptPKToAddress(vout.ScriptPubKey.Hex, sm.BitcoinParams)) - } - } - - // stop mining - stop <- struct{}{} -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_donation.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_donation.go deleted file mode 100644 index d23699b0d4..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_donation.go +++ /dev/null @@ -1,25 +0,0 @@ -package smoketests - -import ( - "math/big" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - "github.com/zeta-chain/zetacore/zetaclient/evm" -) - -// TestDonationEther tests donation of ether to the tss address -func TestDonationEther(sm *runner.SmokeTestRunner) { - txDonation, err := sm.SendEther(sm.TSSAddress, big.NewInt(100000000000000000), []byte(evm.DonationMessage)) - if err != nil { - panic(err) - } - sm.Logger.EVMTransaction(*txDonation, "donation") - - // check contract deployment receipt - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, txDonation, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "donation") - if receipt.Status != 1 { - panic("donation tx failed") - } -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_deposit.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_deposit.go deleted file mode 100644 index 2c3a47eddf..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_deposit.go +++ /dev/null @@ -1,16 +0,0 @@ -package smoketests - -import ( - "math/big" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -func TestERC20Deposit(sm *runner.SmokeTestRunner) { - hash := sm.DepositERC20WithAmountAndMessage(big.NewInt(100000), []byte{}) - - // wait for the cctx to be mined - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, hash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "deposit") -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_multiple_deposits.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_multiple_deposits.go deleted file mode 100644 index 5af6a9f693..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_multiple_deposits.go +++ /dev/null @@ -1,77 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - testcontract "github.com/zeta-chain/zetacore/testutil/contracts" -) - -func TestMultipleERC20Deposit(sm *runner.SmokeTestRunner) { - initialBal, err := sm.USDTZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - txhash := MultipleDeposits(sm, big.NewInt(1e9), big.NewInt(3)) - cctxs := utils.WaitCctxsMinedByInTxHash(sm.Ctx, txhash.Hex(), sm.CctxClient, 3, sm.Logger, sm.CctxTimeout) - if len(cctxs) != 3 { - panic(fmt.Sprintf("cctxs length is not correct: %d", len(cctxs))) - } - - // check new balance is increased by 1e9 * 3 - bal, err := sm.USDTZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - diff := big.NewInt(0).Sub(bal, initialBal) - if diff.Int64() != 3e9 { - panic(fmt.Sprintf("balance difference is not correct: %d", diff.Int64())) - } -} - -func MultipleDeposits(sm *runner.SmokeTestRunner, amount, count *big.Int) ethcommon.Hash { - // deploy depositor - depositorAddr, _, depositor, err := testcontract.DeployDepositor(sm.GoerliAuth, sm.GoerliClient, sm.ERC20CustodyAddr) - if err != nil { - panic(err) - } - - fullAmount := big.NewInt(0).Mul(amount, count) - - // approve - tx, err := sm.USDTERC20.Approve(sm.GoerliAuth, depositorAddr, fullAmount) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - sm.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) - - // deposit - tx, err = depositor.RunDeposits(sm.GoerliAuth, sm.DeployerAddress.Bytes(), sm.USDTERC20Addr, amount, []byte{}, count) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposits failed") - } - sm.Logger.Info("Deposits receipt tx hash: %s", tx.Hash().Hex()) - - for _, log := range receipt.Logs { - event, err := sm.ERC20Custody.ParseDeposited(*log) - if err != nil { - continue - } - sm.Logger.Info("Multiple deposit event: ") - sm.Logger.Info(" Amount: %d, ", event.Amount) - } - sm.Logger.Info("gas limit %d", sm.ZevmAuth.GasLimit) - return tx.Hash() -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_multiple_withdraws.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_multiple_withdraws.go deleted file mode 100644 index 60fa01e6b4..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_multiple_withdraws.go +++ /dev/null @@ -1,78 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - testcontract "github.com/zeta-chain/zetacore/testutil/contracts" -) - -func TestMultipleWithdraws(sm *runner.SmokeTestRunner) { - // deploy withdrawer - withdrawerAddr, _, withdrawer, err := testcontract.DeployWithdrawer(sm.ZevmAuth, sm.ZevmClient) - if err != nil { - panic(err) - } - - // approve - tx, err := sm.USDTZRC20.Approve(sm.ZevmAuth, withdrawerAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - sm.Logger.Info("USDT ZRC20 approve receipt: status %d", receipt.Status) - - // approve gas token - tx, err = sm.ETHZRC20.Approve(sm.ZevmAuth, withdrawerAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve gas token failed") - } - sm.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) - - // check the balance - bal, err := sm.USDTZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - sm.Logger.Info("balance of deployer on USDT ZRC20: %d", bal) - - if bal.Int64() < 1000 { - panic("not enough USDT ZRC20 balance!") - } - - // withdraw - tx, err = withdrawer.RunWithdraws( - sm.ZevmAuth, - sm.DeployerAddress.Bytes(), - sm.USDTZRC20Addr, - big.NewInt(100), - big.NewInt(3), - ) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("withdraw failed") - } - - cctxs := utils.WaitCctxsMinedByInTxHash(sm.Ctx, tx.Hash().Hex(), sm.CctxClient, 3, sm.Logger, sm.CctxTimeout) - if len(cctxs) != 3 { - panic(fmt.Sprintf("cctxs length is not correct: %d", len(cctxs))) - } - - // verify the withdraw value - for _, cctx := range cctxs { - verifyTransferAmountFromCCTX(sm, cctx, 100) - } -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_refund.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_refund.go deleted file mode 100644 index e7728dda15..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_refund.go +++ /dev/null @@ -1,207 +0,0 @@ -package smoketests - -import ( - "errors" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func TestERC20DepositAndCallRefund(sm *runner.SmokeTestRunner) { - //Get the initial balance of the deployer - initialBal, err := sm.USDTZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - - sm.Logger.Info("Sending a deposit that should revert without a liquidity pool makes the cctx aborted") - - amount := big.NewInt(1e4) - - // send the deposit - inTxHash, err := sendInvalidUSDTDeposit(sm, amount) - if err != nil { - panic(err) - } - - // There is no liquidity pool, therefore the cctx should abort - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, inTxHash, sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "deposit") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_Aborted { - panic(fmt.Sprintf("expected cctx status to be Aborted; got %s", cctx.CctxStatus.Status)) - } - - if cctx.CctxStatus.IsAbortRefunded != false { - panic(fmt.Sprintf("expected cctx status to be not refunded; got %t", cctx.CctxStatus.IsAbortRefunded)) - } - - sm.Logger.Info("Refunding the cctx via admin") - msg := crosschaintypes.NewMsgRefundAbortedCCTX( - sm.ZetaTxServer.GetAccountAddress(0), - cctx.Index, - sm.DeployerAddress.String()) - _, err = sm.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } - - //Check that the erc20 in the aborted cctx was refunded on ZetaChain - newBalance, err := sm.USDTZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - expectedBalance := initialBal.Add(initialBal, amount) - if newBalance.Cmp(expectedBalance) != 0 { - panic(fmt.Sprintf("expected balance to be %s after refund; got %s", expectedBalance.String(), newBalance.String())) - } - sm.Logger.Info("CCTX has been aborted on ZetaChain") - - // test refund when there is a liquidity pool - sm.Logger.Info("Sending a deposit that should revert with a liquidity pool") - - sm.Logger.Info("Creating the liquidity pool USTD/ZETA") - err = createZetaERC20LiquidityPool(sm) - if err != nil { - panic(err) - } - sm.Logger.Info("Liquidity pool created") - - goerliBalance, err := sm.USDTERC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - - // send the deposit - amount = big.NewInt(1e7) - inTxHash, err = sendInvalidUSDTDeposit(sm, amount) - if err != nil { - panic(err) - } - goerliBalanceAfterSend := big.NewInt(0).Sub(goerliBalance, amount) - - // there is a liquidity pool, therefore the cctx should revert - cctx = utils.WaitCctxMinedByInTxHash(sm.Ctx, inTxHash, sm.CctxClient, sm.Logger, sm.CctxTimeout) - - // the revert tx creation will fail because the sender, used as the recipient, is not defined in the cctx - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_Reverted { - panic(fmt.Sprintf( - "expected cctx status to be PendingRevert; got %s, aborted message: %s", - cctx.CctxStatus.Status, - cctx.CctxStatus.StatusMessage, - )) - } - - // get revert tx - revertTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash - receipt, err := sm.GoerliClient.TransactionReceipt(sm.Ctx, ethcommon.HexToHash(revertTxHash)) - if err != nil { - panic(err) - } - if receipt.Status == 0 { - panic("expected the revert tx receipt to have status 1; got 0") - } - - // check that the erc20 in the reverted cctx was refunded on Goerli - goerliBalanceAfterRefund, err := sm.USDTERC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - // the new balance must be higher than the previous one because of the revert refund - if goerliBalanceAfterSend.Cmp(goerliBalanceAfterRefund) != -1 { - panic(fmt.Sprintf( - "expected balance to be higher after refund than after send %s < %s", - goerliBalanceAfterSend.String(), - goerliBalanceAfterRefund.String(), - )) - } - // it must also be lower than the previous balance + the amount because of the gas fee for the revert tx - if goerliBalanceAfterRefund.Cmp(goerliBalance) != -1 { - panic(fmt.Sprintf( - "expected balance to be lower after refund than before send %s < %s", - goerliBalanceAfterRefund.String(), - goerliBalance.String()), - ) - } - - sm.Logger.Info("ERC20 CCTX successfully reverted") - sm.Logger.Info("\tbalance before refund: %s", goerliBalance.String()) - sm.Logger.Info("\tamount: %s", amount.String()) - sm.Logger.Info("\tbalance after refund: %s", goerliBalanceAfterRefund.String()) -} - -func createZetaERC20LiquidityPool(sm *runner.SmokeTestRunner) error { - amount := big.NewInt(1e10) - txHash := sm.DepositERC20WithAmountAndMessage(amount, []byte{}) - utils.WaitCctxMinedByInTxHash(sm.Ctx, txHash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - - tx, err := sm.USDTZRC20.Approve(sm.ZevmAuth, sm.UniswapV2RouterAddr, big.NewInt(1e10)) - if err != nil { - return err - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - return errors.New("approve failed") - } - - previousValue := sm.ZevmAuth.Value - sm.ZevmAuth.Value = big.NewInt(1e10) - tx, err = sm.UniswapV2Router.AddLiquidityETH( - sm.ZevmAuth, - sm.USDTZRC20Addr, - amount, - big.NewInt(0), - big.NewInt(0), - sm.DeployerAddress, - big.NewInt(time.Now().Add(10*time.Minute).Unix()), - ) - sm.ZevmAuth.Value = previousValue - if err != nil { - return err - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - return fmt.Errorf("add liquidity failed") - } - - return nil -} - -func sendInvalidUSDTDeposit(sm *runner.SmokeTestRunner, amount *big.Int) (string, error) { - USDT := sm.USDTERC20 - tx, err := USDT.Approve(sm.GoerliAuth, sm.ERC20CustodyAddr, amount) - if err != nil { - return "", err - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) - - tx, err = sm.ERC20Custody.Deposit( - sm.GoerliAuth, - sm.DeployerAddress.Bytes(), - sm.USDTERC20Addr, - amount, - []byte("this is an invalid msg that will cause the contract to revert"), - ) - if err != nil { - return "", err - } - - sm.Logger.Info("GOERLI tx sent: %s; to %s, nonce %d", tx.Hash().String(), tx.To().Hex(), tx.Nonce()) - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - return "", errors.New("expected the tx receipt to have status 1; got 0") - } - sm.Logger.Info("GOERLI tx receipt: %d", receipt.Status) - sm.Logger.Info(" tx hash: %s", receipt.TxHash.String()) - sm.Logger.Info(" to: %s", tx.To().String()) - sm.Logger.Info(" value: %d", tx.Value()) - sm.Logger.Info(" block num: %d", receipt.BlockNumber) - - return tx.Hash().Hex(), nil -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_withdraw.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_withdraw.go deleted file mode 100644 index 793c718c12..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_erc20_withdraw.go +++ /dev/null @@ -1,72 +0,0 @@ -package smoketests - -import ( - "math/big" - - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func TestERC20Withdraw(sm *runner.SmokeTestRunner) { - // approve - tx, err := sm.ETHZRC20.Approve(sm.ZevmAuth, sm.USDTZRC20Addr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - sm.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) - - // withdraw - tx, err = sm.USDTZRC20.Withdraw(sm.ZevmAuth, sm.DeployerAddress.Bytes(), big.NewInt(1000)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status) - for _, log := range receipt.Logs { - event, err := sm.USDTZRC20.ParseWithdrawal(*log) - if err != nil { - continue - } - sm.Logger.Info( - " logs: from %s, to %x, value %d, gasfee %d", - event.From.Hex(), - event.To, - event.Value, - event.Gasfee, - ) - } - - // verify the withdraw value - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, receipt.TxHash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - verifyTransferAmountFromCCTX(sm, cctx, 1000) -} - -// verifyTransferAmountFromCCTX verifies the transfer amount from the CCTX on Goerli -func verifyTransferAmountFromCCTX(sm *runner.SmokeTestRunner, cctx *crosschaintypes.CrossChainTx, amount int64) { - sm.Logger.Info("outTx hash %s", cctx.GetCurrentOutTxParam().OutboundTxHash) - - receipt, err := sm.GoerliClient.TransactionReceipt( - sm.Ctx, - ethcommon.HexToHash(cctx.GetCurrentOutTxParam().OutboundTxHash), - ) - if err != nil { - panic(err) - } - sm.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status) - for _, log := range receipt.Logs { - event, err := sm.USDTERC20.ParseTransfer(*log) - if err != nil { - continue - } - sm.Logger.Info(" logs: from %s, to %s, value %d", event.From.Hex(), event.To.Hex(), event.Value) - if event.Value.Int64() != amount { - panic("value is not correct") - } - } -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_eth_deposit.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_eth_deposit.go deleted file mode 100644 index 44146e53cd..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_eth_deposit.go +++ /dev/null @@ -1,330 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - "strings" - - "cosmossdk.io/math" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - testcontract "github.com/zeta-chain/zetacore/testutil/contracts" - "github.com/zeta-chain/zetacore/x/crosschain/types" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" -) - -// TestEtherDeposit tests deposit of ethers -func TestEtherDeposit(sm *runner.SmokeTestRunner) { - hash := sm.DepositEtherWithAmount(false, big.NewInt(10000000000000000)) // in wei (0.01 eth) - - // wait for the cctx to be mined - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, hash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "deposit") -} - -// TestEtherDepositAndCall tests deposit of ethers calling a example contract -func TestEtherDepositAndCall(sm *runner.SmokeTestRunner) { - sm.Logger.Info("Deploying example contract") - exampleAddr, _, exampleContract, err := testcontract.DeployExample(sm.ZevmAuth, sm.ZevmClient) - if err != nil { - panic(err) - } - sm.Logger.Info("Example contract deployed") - - // preparing tx - goerliClient := sm.GoerliClient - value := big.NewInt(1e18) - gasLimit := uint64(23000) - gasPrice, err := goerliClient.SuggestGasPrice(sm.Ctx) - if err != nil { - panic(err) - } - nonce, err := goerliClient.PendingNonceAt(sm.Ctx, sm.DeployerAddress) - if err != nil { - panic(err) - } - - data := append(exampleAddr.Bytes(), []byte("hello sailors")...) - tx := ethtypes.NewTransaction(nonce, sm.TSSAddress, value, gasLimit, gasPrice, data) - chainID, err := goerliClient.NetworkID(sm.Ctx) - if err != nil { - panic(err) - } - deployerPrivkey, err := crypto.HexToECDSA(sm.DeployerPrivateKey) - if err != nil { - panic(err) - } - signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - panic(err) - } - - sm.Logger.Info("Sending a cross-chain call to example contract") - err = goerliClient.SendTransaction(sm.Ctx, signedTx) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("tx failed") - } - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf("expected cctx status to be mined; got %s", cctx.CctxStatus.Status)) - } - - // Checking example contract has been called, bar value should be set to amount - bar, err := exampleContract.Bar(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if bar.Cmp(value) != 0 { - panic(fmt.Sprintf("cross-chain call failed bar value %s should be equal to amount %s", bar.String(), value.String())) - } - sm.Logger.Info("Cross-chain call succeeded") - - sm.Logger.Info("Deploying reverter contract") - reverterAddr, _, _, err := testcontract.DeployReverter(sm.ZevmAuth, sm.ZevmClient) - if err != nil { - panic(err) - } - sm.Logger.Info("Example reverter deployed") - - // preparing tx for reverter - gasPrice, err = goerliClient.SuggestGasPrice(sm.Ctx) - if err != nil { - panic(err) - } - nonce, err = goerliClient.PendingNonceAt(sm.Ctx, sm.DeployerAddress) - if err != nil { - panic(err) - } - - data = append(reverterAddr.Bytes(), []byte("hello sailors")...) - tx = ethtypes.NewTransaction(nonce, sm.TSSAddress, value, gasLimit, gasPrice, data) - signedTx, err = ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - panic(err) - } - - sm.Logger.Info("Sending a cross-chain call to reverter contract") - err = goerliClient.SendTransaction(sm.Ctx, signedTx) - if err != nil { - panic(err) - } - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("tx failed") - } - cctx = utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected cctx status to be reverted; got %s", cctx.CctxStatus.Status)) - } - sm.Logger.Info("Cross-chain call to reverter reverted") - - // check the status message contains revert error hash in case of revert - // 0xbfb4ebcf is the hash of "Foo()" - if !strings.Contains(cctx.CctxStatus.StatusMessage, "0xbfb4ebcf") { - panic(fmt.Sprintf("expected cctx status message to contain revert reason; got %s", cctx.CctxStatus.StatusMessage)) - } -} - -func TestDepositAndCallRefund(sm *runner.SmokeTestRunner) { - goerliClient := sm.GoerliClient - - // in wei (10 eth) - value := big.NewInt(1e18) - value = value.Mul(value, big.NewInt(10)) - - nonce, err := goerliClient.PendingNonceAt(sm.Ctx, sm.DeployerAddress) - if err != nil { - panic(err) - } - - gasLimit := uint64(23000) // in units - gasPrice, err := goerliClient.SuggestGasPrice(sm.Ctx) - if err != nil { - panic(err) - } - - data := append(sm.BTCZRC20Addr.Bytes(), []byte("hello sailors")...) // this data - tx := ethtypes.NewTransaction(nonce, sm.TSSAddress, value, gasLimit, gasPrice, data) - chainID, err := goerliClient.NetworkID(sm.Ctx) - if err != nil { - panic(err) - } - deployerPrivkey, err := crypto.HexToECDSA(sm.DeployerPrivateKey) - if err != nil { - panic(err) - } - - signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - panic(err) - } - err = goerliClient.SendTransaction(sm.Ctx, signedTx) - if err != nil { - panic(err) - } - sm.Logger.Info("GOERLI tx sent: %s; to %s, nonce %d", signedTx.Hash().String(), signedTx.To().Hex(), signedTx.Nonce()) - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("GOERLI tx receipt: %d", receipt.Status) - sm.Logger.Info(" tx hash: %s", receipt.TxHash.String()) - sm.Logger.Info(" to: %s", signedTx.To().String()) - sm.Logger.Info(" value: %d", signedTx.Value()) - sm.Logger.Info(" block num: %d", receipt.BlockNumber) - - func() { - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.Info("cctx status message: %s", cctx.CctxStatus.StatusMessage) - revertTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash - sm.Logger.Info("GOERLI revert tx receipt: status %d", receipt.Status) - - tx, _, err := sm.GoerliClient.TransactionByHash(sm.Ctx, ethcommon.HexToHash(revertTxHash)) - if err != nil { - panic(err) - } - receipt, err := sm.GoerliClient.TransactionReceipt(sm.Ctx, ethcommon.HexToHash(revertTxHash)) - if err != nil { - panic(err) - } - - printTxInfo := func() { - // debug info when test fails - sm.Logger.Info(" tx: %+v", tx) - sm.Logger.Info(" receipt: %+v", receipt) - sm.Logger.Info("cctx http://localhost:1317/zeta-chain/crosschain/cctx/%s", cctx.Index) - } - - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - printTxInfo() - panic(fmt.Sprintf("expected cctx status to be PendingRevert; got %s", cctx.CctxStatus.Status)) - } - - if receipt.Status == 0 { - printTxInfo() - panic("expected the revert tx receipt to have status 1; got 0") - } - - if *tx.To() != sm.DeployerAddress { - printTxInfo() - panic(fmt.Sprintf("expected tx to %s; got %s", sm.DeployerAddress.Hex(), tx.To().Hex())) - } - - // the received value must be lower than the original value because of the paid fees for the revert tx - // we check that the value is still greater than 0 - if tx.Value().Cmp(value) != -1 || tx.Value().Cmp(big.NewInt(0)) != 1 { - printTxInfo() - panic(fmt.Sprintf("expected tx value %s; should be non-null and lower than %s", tx.Value().String(), value.String())) - } - - sm.Logger.Info("REVERT tx receipt: %d", receipt.Status) - sm.Logger.Info(" tx hash: %s", receipt.TxHash.String()) - sm.Logger.Info(" to: %s", tx.To().String()) - sm.Logger.Info(" value: %s", tx.Value().String()) - sm.Logger.Info(" block num: %d", receipt.BlockNumber) - }() -} - -// TestDepositEtherLiquidityCap tests depositing Ethers in a context where a liquidity cap is set -func TestDepositEtherLiquidityCap(sm *runner.SmokeTestRunner) { - supply, err := sm.ETHZRC20.TotalSupply(&bind.CallOpts{}) - if err != nil { - panic(err) - } - - // Set a liquidity cap slightly above the current supply - sm.Logger.Info("Setting a liquidity cap") - liquidityCap := math.NewUintFromBigInt(supply).Add(math.NewUint(1e16)) - msg := fungibletypes.NewMsgUpdateZRC20LiquidityCap( - sm.ZetaTxServer.GetAccountAddress(0), - sm.ETHZRC20Addr.Hex(), - liquidityCap, - ) - res, err := sm.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } - sm.Logger.Info("set liquidity cap tx hash: %s", res.TxHash) - - sm.Logger.Info("Depositing more than liquidity cap should make cctx reverted") - signedTx, err := sm.SendEther(sm.TSSAddress, big.NewInt(1e17), nil) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) - } - sm.Logger.Info("CCTX has been reverted") - - sm.Logger.Info("Depositing less than liquidity cap should still succeed") - initialBal, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - signedTx, err = sm.SendEther(sm.TSSAddress, big.NewInt(1e15), nil) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } - utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - expectedBalance := big.NewInt(0).Add(initialBal, big.NewInt(1e15)) - - bal, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - if bal.Cmp(expectedBalance) != 0 { - panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) - } - sm.Logger.Info("Deposit succeeded") - - sm.Logger.Info("Removing the liquidity cap") - msg = fungibletypes.NewMsgUpdateZRC20LiquidityCap( - sm.ZetaTxServer.GetAccountAddress(0), - sm.ETHZRC20Addr.Hex(), - math.ZeroUint(), - ) - res, err = sm.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } - sm.Logger.Info("remove liquidity cap tx hash: %s", res.TxHash) - initialBal, err = sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - signedTx, err = sm.SendEther(sm.TSSAddress, big.NewInt(1e17), nil) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } - utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - expectedBalance = big.NewInt(0).Add(initialBal, big.NewInt(1e17)) - - bal, err = sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - if bal.Cmp(expectedBalance) != 0 { - panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) - } - sm.Logger.Info("New deposit succeeded") -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_eth_withdraw.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_eth_withdraw.go deleted file mode 100644 index 1629eede7e..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_eth_withdraw.go +++ /dev/null @@ -1,46 +0,0 @@ -package smoketests - -import ( - "math/big" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -// TestEtherWithdraw tests the withdraw of ether -func TestEtherWithdraw(sm *runner.SmokeTestRunner) { - // approve - tx, err := sm.ETHZRC20.Approve(sm.ZevmAuth, sm.ETHZRC20Addr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - sm.Logger.EVMTransaction(*tx, "approve") - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - sm.Logger.EVMReceipt(*receipt, "approve") - - // withdraw - tx, err = sm.ETHZRC20.Withdraw(sm.ZevmAuth, sm.DeployerAddress.Bytes(), big.NewInt(100000)) - if err != nil { - panic(err) - } - sm.Logger.EVMTransaction(*tx, "withdraw") - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("withdraw failed") - } - sm.Logger.EVMReceipt(*receipt, "withdraw") - sm.Logger.ZRC20Withdrawal(sm.ETHZRC20, *receipt, "withdraw") - - // verify the withdraw value - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, receipt.TxHash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic("cctx status is not outbound mined") - } -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_message_passing.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_message_passing.go deleted file mode 100644 index ea6b5473bd..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_message_passing.go +++ /dev/null @@ -1,233 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - ethcommon "github.com/ethereum/go-ethereum/common" - zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/testdapp" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - cctxtypes "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func TestMessagePassing(sm *runner.SmokeTestRunner) { - chainID, err := sm.GoerliClient.ChainID(sm.Ctx) - if err != nil { - panic(err) - } - - sm.Logger.Info("Approving ConnectorEth to spend deployer's ZetaEth") - amount := big.NewInt(1e18) - amount = amount.Mul(amount, big.NewInt(10)) // 10 Zeta - auth := sm.GoerliAuth - tx, err := sm.ZetaEth.Approve(auth, sm.ConnectorEthAddr, amount) - if err != nil { - panic(err) - } - - sm.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } - sm.Logger.Info("Approve tx receipt: %d", receipt.Status) - sm.Logger.Info("Calling ConnectorEth.Send") - tx, err = sm.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ - DestinationChainId: chainID, - DestinationAddress: sm.DeployerAddress.Bytes(), - DestinationGasLimit: big.NewInt(400_000), - Message: nil, - ZetaValueAndGas: amount, - ZetaParams: nil, - }) - if err != nil { - panic(err) - } - - sm.Logger.Info("ConnectorEth.Send tx hash: %s", tx.Hash().Hex()) - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } - sm.Logger.Info("ConnectorEth.Send tx receipt: status %d", receipt.Status) - sm.Logger.Info(" Logs:") - for _, log := range receipt.Logs { - sentLog, err := sm.ConnectorEth.ParseZetaSent(*log) - if err == nil { - sm.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) - sm.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) - sm.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) - sm.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) - } - } - - sm.Logger.Info("Waiting for ConnectorEth.Send CCTX to be mined...") - sm.Logger.Info(" INTX hash: %s", receipt.TxHash.String()) - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, receipt.TxHash.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected cctx status to be %s; got %s, message %s", - cctxtypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } - receipt, err = sm.GoerliClient.TransactionReceipt(sm.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutTxParam().OutboundTxHash)) - if err != nil { - panic(err) - } - if receipt.Status != 1 { - panic("tx failed") - } - for _, log := range receipt.Logs { - event, err := sm.ConnectorEth.ParseZetaReceived(*log) - if err == nil { - sm.Logger.Info("Received ZetaSent event:") - sm.Logger.Info(" Dest Addr: %s", event.DestinationAddress) - sm.Logger.Info(" Zeta Value: %d", event.ZetaValue) - sm.Logger.Info(" src chainid: %d", event.SourceChainId) - if event.ZetaValue.Cmp(cctx.GetCurrentOutTxParam().Amount.BigInt()) != 0 { - panic("Zeta value mismatch") - } - } - } -} - -func TestMessagePassingRevertFail(sm *runner.SmokeTestRunner) { - chainID, err := sm.GoerliClient.ChainID(sm.Ctx) - if err != nil { - panic(err) - } - - amount := big.NewInt(1e18) - amount = amount.Mul(amount, big.NewInt(10)) // 10 Zeta - auth := sm.GoerliAuth - tx, err := sm.ZetaEth.Approve(auth, sm.ConnectorEthAddr, amount) - if err != nil { - panic(err) - } - sm.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } - sm.Logger.Info("Approve tx receipt: %d", receipt.Status) - sm.Logger.Info("Calling ConnectorEth.Send") - tx, err = sm.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ - DestinationChainId: chainID, - DestinationAddress: sm.DeployerAddress.Bytes(), - DestinationGasLimit: big.NewInt(400_000), - Message: []byte("revert"), // non-empty message will cause revert, because the dest address is not a contract - ZetaValueAndGas: amount, - ZetaParams: nil, - }) - if err != nil { - panic(err) - } - sm.Logger.Info("ConnectorEth.Send tx hash: %s", tx.Hash().Hex()) - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } - sm.Logger.Info("ConnectorEth.Send tx receipt: status %d", receipt.Status) - sm.Logger.Info(" Logs:") - for _, log := range receipt.Logs { - sentLog, err := sm.ConnectorEth.ParseZetaSent(*log) - if err == nil { - sm.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) - sm.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) - sm.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) - sm.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) - } - } - - // expect revert tx to fail - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, receipt.TxHash.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - receipt, err = sm.GoerliClient.TransactionReceipt(sm.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutTxParam().OutboundTxHash)) - if err != nil { - panic(err) - } - // expect revert tx to fail as well - if receipt.Status != 0 { - panic("expected revert tx to fail") - } - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Aborted { - panic("expected cctx to be aborted") - } -} - -func TestMessagePassingRevertSuccess(sm *runner.SmokeTestRunner) { - chainID, err := sm.GoerliClient.ChainID(sm.Ctx) - if err != nil { - panic(err) - } - - amount := big.NewInt(1e18) - amount = amount.Mul(amount, big.NewInt(10)) // 10 Zeta - auth := sm.GoerliAuth - - tx, err := sm.ZetaEth.Approve(auth, sm.TestDAppAddr, amount) - if err != nil { - panic(err) - } - sm.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } - sm.Logger.Info("Approve tx receipt: %d", receipt.Status) - - sm.Logger.Info("Calling TestDApp.SendHello on contract address %s", sm.TestDAppAddr.Hex()) - testDApp, err := testdapp.NewTestDApp(sm.TestDAppAddr, sm.GoerliClient) - if err != nil { - panic(err) - } - - res2, err := sm.BankClient.SupplyOf(sm.Ctx, &banktypes.QuerySupplyOfRequest{ - Denom: "azeta", - }) - if err != nil { - panic(err) - } - sm.Logger.Info("$$$ Before: SUPPLY OF AZETA: %d", res2.Amount.Amount) - - tx, err = testDApp.SendHelloWorld(auth, sm.TestDAppAddr, chainID, amount, true) - if err != nil { - panic(err) - } - sm.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("TestDApp.SendHello tx receipt: status %d", receipt.Status) - - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, receipt.TxHash.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Reverted { - panic("expected cctx to be reverted") - } - outTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash - receipt, err = sm.GoerliClient.TransactionReceipt(sm.Ctx, ethcommon.HexToHash(outTxHash)) - if err != nil { - panic(err) - } - for _, log := range receipt.Logs { - event, err := sm.ConnectorEth.ParseZetaReverted(*log) - if err == nil { - sm.Logger.Info("ZetaReverted event: ") - sm.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(event.DestinationAddress).Hex()) - sm.Logger.Info(" Dest Chain: %d", event.DestinationChainId) - sm.Logger.Info(" RemainingZetaValue: %d", event.RemainingZetaValue) - sm.Logger.Info(" Message: %x", event.Message) - } - } - res3, err := sm.BankClient.SupplyOf(sm.Ctx, &banktypes.QuerySupplyOfRequest{ - Denom: "azeta", - }) - if err != nil { - panic(err) - } - sm.Logger.Info("$$$ After: SUPPLY OF AZETA: %d", res3.Amount.Amount.BigInt()) - sm.Logger.Info("$$$ Diff: SUPPLY OF AZETA: %d", res3.Amount.Amount.Sub(res2.Amount.Amount).BigInt()) -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_mytest.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_mytest.go deleted file mode 100644 index 3e1091800f..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_mytest.go +++ /dev/null @@ -1,7 +0,0 @@ -package smoketests - -import "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - -func TestMyTest(_ *runner.SmokeTestRunner) { - // add your test here -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go deleted file mode 100644 index f3579990f2..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go +++ /dev/null @@ -1,185 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/vault" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - "github.com/zeta-chain/zetacore/testutil/sample" - "github.com/zeta-chain/zetacore/x/crosschain/types" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" -) - -func TestPauseZRC20(sm *runner.SmokeTestRunner) { - // Setup vault used to test zrc20 interactions - sm.Logger.Info("Deploying vault") - vaultAddr, _, vaultContract, err := vault.DeployVault(sm.ZevmAuth, sm.ZevmClient) - if err != nil { - panic(err) - } - // Approving vault to spend ZRC20 - tx, err := sm.ETHZRC20.Approve(sm.ZevmAuth, vaultAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("Vault approval should succeed") - } - tx, err = sm.USDTZRC20.Approve(sm.ZevmAuth, vaultAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("Vault approval should succeed") - } - - // Pause ETH ZRC20 - sm.Logger.Info("Pausing ETH") - msg := fungibletypes.NewMsgUpdateZRC20PausedStatus( - sm.ZetaTxServer.GetAccountAddress(0), - []string{sm.ETHZRC20Addr.Hex()}, - fungibletypes.UpdatePausedStatusAction_PAUSE, - ) - res, err := sm.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } - sm.Logger.Info("pause zrc20 tx hash: %s", res.TxHash) - - // Fetch and check pause status - fcRes, err := sm.FungibleClient.ForeignCoins(sm.Ctx, &fungibletypes.QueryGetForeignCoinsRequest{ - Index: sm.ETHZRC20Addr.Hex(), - }) - if err != nil { - panic(err) - } - if !fcRes.GetForeignCoins().Paused { - panic("ETH should be paused") - } - sm.Logger.Info("ETH is paused") - - // Try operations with ETH ZRC20 - sm.Logger.Info("Can no longer do operations on ETH ZRC20") - tx, err = sm.ETHZRC20.Transfer(sm.ZevmAuth, sample.EthAddress(), big.NewInt(1e5)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 1 { - panic("transfer should fail") - } - tx, err = sm.ETHZRC20.Burn(sm.ZevmAuth, big.NewInt(1e5)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 1 { - panic("burn should fail") - } - - // Operation on a contract that interact with ETH ZRC20 should fail - sm.Logger.Info("Vault contract can no longer interact with ETH ZRC20: %s", sm.ETHZRC20Addr.Hex()) - tx, err = vaultContract.Deposit(sm.ZevmAuth, sm.ETHZRC20Addr, big.NewInt(1e5)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 1 { - panic("deposit should fail") - } - sm.Logger.Info("Operations all failed") - - // Check we can still interact with USDT ZRC20 - sm.Logger.Info("Check other ZRC20 can still be operated") - tx, err = sm.USDTZRC20.Transfer(sm.ZevmAuth, sample.EthAddress(), big.NewInt(1e3)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("USDT transfer should succeed") - } - tx, err = vaultContract.Deposit(sm.ZevmAuth, sm.USDTZRC20Addr, big.NewInt(1e3)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("USDT vault deposit should succeed") - } - - // Check deposit revert when paused - signedTx, err := sm.SendEther(sm.TSSAddress, big.NewInt(1e17), nil) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.GoerliClient, signedTx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, signedTx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) - } - sm.Logger.Info("CCTX has been reverted") - - // Unpause ETH ZRC20 - sm.Logger.Info("Unpausing ETH") - msg = fungibletypes.NewMsgUpdateZRC20PausedStatus( - sm.ZetaTxServer.GetAccountAddress(0), - []string{sm.ETHZRC20Addr.Hex()}, - fungibletypes.UpdatePausedStatusAction_UNPAUSE, - ) - res, err = sm.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } - sm.Logger.Info("unpause zrc20 tx hash: %s", res.TxHash) - - // Fetch and check pause status - fcRes, err = sm.FungibleClient.ForeignCoins(sm.Ctx, &fungibletypes.QueryGetForeignCoinsRequest{ - Index: sm.ETHZRC20Addr.Hex(), - }) - if err != nil { - panic(err) - } - if fcRes.GetForeignCoins().Paused { - panic("ETH should be unpaused") - } - sm.Logger.Info("ETH is unpaused") - - // Try operations with ETH ZRC20 - sm.Logger.Info("Can do operations on ETH ZRC20 again") - tx, err = sm.ETHZRC20.Transfer(sm.ZevmAuth, sample.EthAddress(), big.NewInt(1e5)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("transfer should succeed") - } - tx, err = sm.ETHZRC20.Burn(sm.ZevmAuth, big.NewInt(1e5)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("burn should succeed") - } - - // Can deposit tokens into the vault again - tx, err = vaultContract.Deposit(sm.ZevmAuth, sm.ETHZRC20Addr, big.NewInt(1e5)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit should succeed") - } - - sm.Logger.Info("Operations all succeeded") -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_zeta_deposit.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_zeta_deposit.go deleted file mode 100644 index 886103b32f..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_zeta_deposit.go +++ /dev/null @@ -1,17 +0,0 @@ -package smoketests - -import ( - "math/big" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -func TestZetaDeposit(sm *runner.SmokeTestRunner) { - // Deposit 1 Zeta - hash := sm.DepositZetaWithAmount(big.NewInt(1e18)) - - // wait for the cctx to be mined - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, hash.Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "deposit") -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_zeta_withdraw.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_zeta_withdraw.go deleted file mode 100644 index 8f9fa959ec..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_zeta_withdraw.go +++ /dev/null @@ -1,138 +0,0 @@ -package smoketests - -import ( - "fmt" - "math/big" - - cctxtypes "github.com/zeta-chain/zetacore/x/crosschain/types" - - ethcommon "github.com/ethereum/go-ethereum/common" - connectorzevm "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/connectorzevm.sol" - "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -func TestZetaWithdraw(sm *runner.SmokeTestRunner) { - amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(10)) // 10 Zeta - - sm.ZevmAuth.Value = amount - tx, err := sm.WZeta.Deposit(sm.ZevmAuth) - if err != nil { - panic(err) - } - sm.ZevmAuth.Value = big.NewInt(0) - sm.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "wzeta deposit") - if receipt.Status == 0 { - panic("deposit failed") - } - - chainID, err := sm.GoerliClient.ChainID(sm.Ctx) - if err != nil { - panic(err) - } - - tx, err = sm.WZeta.Approve(sm.ZevmAuth, sm.ConnectorZEVMAddr, amount) - if err != nil { - panic(err) - } - sm.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "wzeta approve") - if receipt.Status == 0 { - panic(fmt.Sprintf("approve failed, logs: %+v", receipt.Logs)) - } - - tx, err = sm.ConnectorZEVM.Send(sm.ZevmAuth, connectorzevm.ZetaInterfacesSendInput{ - DestinationChainId: chainID, - DestinationAddress: sm.DeployerAddress.Bytes(), - DestinationGasLimit: big.NewInt(400_000), - Message: nil, - ZetaValueAndGas: amount, - ZetaParams: nil, - }) - if err != nil { - panic(err) - } - sm.Logger.Info("send tx hash: %s", tx.Hash().Hex()) - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "send") - if receipt.Status == 0 { - panic(fmt.Sprintf("send failed, logs: %+v", receipt.Logs)) - - } - - sm.Logger.Info(" Logs:") - for _, log := range receipt.Logs { - sentLog, err := sm.ConnectorZEVM.ParseZetaSent(*log) - if err == nil { - sm.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) - sm.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) - sm.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) - sm.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) - } - } - sm.Logger.Info("waiting for cctx status to change to final...") - - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, tx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.CctxTimeout) - sm.Logger.CCTX(*cctx, "zeta withdraw") - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { - panic(fmt.Errorf( - "expected cctx status to be %s; got %s, message %s", - cctxtypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } -} - -func TestZetaWithdrawBTCRevert(sm *runner.SmokeTestRunner) { - sm.ZevmAuth.Value = big.NewInt(1e18) // 1 Zeta - tx, err := sm.WZeta.Deposit(sm.ZevmAuth) - if err != nil { - panic(err) - } - sm.ZevmAuth.Value = big.NewInt(0) - sm.Logger.Info("Deposit tx hash: %s", tx.Hash().Hex()) - - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "Deposit") - if receipt.Status != 1 { - panic("Deposit failed") - } - - tx, err = sm.WZeta.Approve(sm.ZevmAuth, sm.ConnectorZEVMAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - sm.Logger.Info("wzeta.approve tx hash: %s", tx.Hash().Hex()) - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "Approve") - if receipt.Status != 1 { - panic("Approve failed") - } - - tx, err = sm.ConnectorZEVM.Send(sm.ZevmAuth, connectorzevm.ZetaInterfacesSendInput{ - DestinationChainId: big.NewInt(common.BtcRegtestChain().ChainId), - DestinationAddress: sm.DeployerAddress.Bytes(), - DestinationGasLimit: big.NewInt(400_000), - Message: nil, - ZetaValueAndGas: big.NewInt(1e17), - ZetaParams: nil, - }) - if err != nil { - panic(err) - } - sm.Logger.Info("send tx hash: %s", tx.Hash().Hex()) - - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.EVMReceipt(*receipt, "send") - if receipt.Status != 0 { - panic("Was able to send ZETA to BTC") - } -} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_zrc20_swap.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_zrc20_swap.go deleted file mode 100644 index 203fa1df0a..0000000000 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_zrc20_swap.go +++ /dev/null @@ -1,96 +0,0 @@ -package smoketests - -import ( - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" -) - -func TestZRC20Swap(sm *runner.SmokeTestRunner) { - // TODO: move into setup and skip it if already initialized - // https://github.com/zeta-chain/node-private/issues/88 - // it is kept as is for now to be consistent with the old implementation - // if the tx fails due to already initialized, it will be ignored - tx, err := sm.UniswapV2Factory.CreatePair(sm.ZevmAuth, sm.USDTZRC20Addr, sm.ETHZRC20Addr) - if err != nil { - sm.Logger.Print("ℹ️create pair error") - } else { - utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - } - - usdtEthPair, err := sm.UniswapV2Factory.GetPair(&bind.CallOpts{}, sm.USDTZRC20Addr, sm.ETHZRC20Addr) - if err != nil { - panic(err) - } - sm.Logger.Info("USDT-ETH pair receipt pair addr %s", usdtEthPair.Hex()) - - tx, err = sm.USDTZRC20.Approve(sm.ZevmAuth, sm.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("USDT ZRC20 approval receipt txhash %s status %d", receipt.TxHash, receipt.Status) - - tx, err = sm.ETHZRC20.Approve(sm.ZevmAuth, sm.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("ETH ZRC20 approval receipt txhash %s status %d", receipt.TxHash, receipt.Status) - - // temporarily increase gas limit to 400000 - previousGasLimit := sm.ZevmAuth.GasLimit - defer func() { - sm.ZevmAuth.GasLimit = previousGasLimit - }() - - sm.ZevmAuth.GasLimit = 400000 - tx, err = sm.UniswapV2Router.AddLiquidity( - sm.ZevmAuth, - sm.USDTZRC20Addr, - sm.ETHZRC20Addr, - big.NewInt(90000), - big.NewInt(1000), - big.NewInt(90000), - big.NewInt(1000), - sm.DeployerAddress, - big.NewInt(time.Now().Add(10*time.Minute).Unix()), - ) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("Add liquidity receipt txhash %s status %d", receipt.TxHash, receipt.Status) - - balETHBefore, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - ethOutAmout := big.NewInt(1) - tx, err = sm.UniswapV2Router.SwapExactTokensForTokens( - sm.ZevmAuth, - big.NewInt(1000), - ethOutAmout, - []ethcommon.Address{sm.USDTZRC20Addr, sm.ETHZRC20Addr}, - sm.DeployerAddress, - big.NewInt(time.Now().Add(10*time.Minute).Unix()), - ) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) - sm.Logger.Info("Swap USDT for ETH ZRC20 %s status %d", receipt.TxHash, receipt.Status) - - balETHAfter, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) - if err != nil { - panic(err) - } - ethDiff := big.NewInt(0).Sub(balETHAfter, balETHBefore) - if ethDiff.Cmp(ethOutAmout) < 0 { - panic("swap failed") - } -} diff --git a/contrib/localnet/orchestrator/start-upgrade.sh b/contrib/localnet/orchestrator/start-upgrade.sh deleted file mode 100644 index f13666aa57..0000000000 --- a/contrib/localnet/orchestrator/start-upgrade.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -ZETAE2E_CMD=$1 - -echo "waiting for geth RPC to start..." -sleep 2 - -# unlock the deployer account -echo "funding deployer address 0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", value: web3.toWei(100,"ether")})' attach http://eth:8545 - -# unlock erc20 tester accounts -echo "funding deployer address 0x6F57D5E7c6DBb75e59F1524a3dE38Fc389ec5Fd6 with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x6F57D5E7c6DBb75e59F1524a3dE38Fc389ec5Fd6", value: web3.toWei(100,"ether")})' attach http://eth:8545 - -# unlock zeta tester accounts -echo "funding deployer address 0x5cC2fBb200A929B372e3016F1925DcF988E081fd with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x5cC2fBb200A929B372e3016F1925DcF988E081fd", value: web3.toWei(100,"ether")})' attach http://eth:8545 - -# unlock bitcoin tester accounts -echo "funding deployer address 0x283d810090EdF4043E75247eAeBcE848806237fD with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x283d810090EdF4043E75247eAeBcE848806237fD", value: web3.toWei(100,"ether")})' attach http://eth:8545 - -# unlock ethers tester accounts -echo "funding deployer address 0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x8D47Db7390AC4D3D449Cc20D799ce4748F97619A", value: web3.toWei(100,"ether")})' attach http://eth:8545 - -# unlock miscellaneous tests accounts -echo "funding deployer address 0x90126d02E41c9eB2a10cfc43aAb3BD3460523Cdf with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0x90126d02E41c9eB2a10cfc43aAb3BD3460523Cdf", value: web3.toWei(100,"ether")})' attach http://eth:8545 - -# unlock advanced erc20 tests accounts -echo "funding deployer address 0xcC8487562AAc220ea4406196Ee902C7c076966af with 100 Ether" -geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xcC8487562AAc220ea4406196Ee902C7c076966af", value: web3.toWei(100,"ether")})' attach http://eth:8545 - - -echo "running E2E command to setup the networks and populate the state..." - -zetae2e "$ZETAE2E_CMD" --config-out deployed.yml - -ZETAE2E_EXIT_CODE=$? -if [ $ZETAE2E_EXIT_CODE -ne 0 ]; then - echo "E2E setup failed" - exit 1 -fi - -echo "E2E setup passed, waiting for upgrade height..." - -# Restart zetaclients at upgrade height -/work/restart-zetaclientd.sh -u 200 -n 2 - -echo "waiting 10 seconds for node to restart..." - -sleep 10 - -echo "running E2E command to test the network after upgrade..." - -zetae2e "$ZETAE2E_CMD" --skip-setup --config deployed.yml - -ZETAE2E_EXIT_CODE=$? -if [ $ZETAE2E_EXIT_CODE -eq 0 ]; then - echo "E2E passed after upgrade" - exit 0 -else - echo "E2E failed after upgrade" - exit 1 -fi \ No newline at end of file diff --git a/contrib/localnet/orchestrator/start.sh b/contrib/localnet/orchestrator/start.sh index 2c0901a2c2..69fc9056a5 100644 --- a/contrib/localnet/orchestrator/start.sh +++ b/contrib/localnet/orchestrator/start.sh @@ -1,10 +1,18 @@ #!/bin/bash +# The script run the zetae2e CLI to run local end-to-end tests +# First argument is the command to run the local e2e +# A second optional argument can be passed and can have the following value: +# upgrade: run the local e2e once, then restart zetaclientd at upgrade height and run the local e2e again + ZETAE2E_CMD=$1 +OPTION=$2 echo "waiting for geth RPC to start..." sleep 2 +### Create the accounts and fund them with Ether on local Ethereum network + # unlock the deployer account echo "funding deployer address 0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC with 100 Ether" geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", value: web3.toWei(100,"ether")})' attach http://eth:8545 @@ -37,17 +45,74 @@ geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xcC8487562AAc220ea44 echo "funding TSS address 0xF421292cb0d3c97b90EEEADfcD660B893592c6A2 with 100 Ether" geth --exec 'eth.sendTransaction({from: eth.coinbase, to: "0xF421292cb0d3c97b90EEEADfcD660B893592c6A2", value: web3.toWei(100,"ether")})' attach http://eth:8545 -# run e2e tests -echo "running e2e tests..." -zetae2e "$ZETAE2E_CMD" -ZETAE2E_EXIT_CODE=$? +### Run zetae2e command depending on the option passed + +if [ "$OPTION" == "upgrade" ]; then + + # Run the e2e tests, then restart zetaclientd at upgrade height and run the e2e tests again + + echo "running E2E command to setup the networks and populate the state..." + zetae2e "$ZETAE2E_CMD" --config-out deployed.yml + ZETAE2E_EXIT_CODE=$? + + if [ $ZETAE2E_EXIT_CODE -ne 0 ]; then + echo "E2E setup failed" + exit 1 + fi + + echo "E2E setup passed, waiting for upgrade height..." + + # Restart zetaclients at upgrade height + /work/restart-zetaclientd.sh -u 200 -n 2 + + echo "waiting 10 seconds for node to restart..." + + sleep 10 + + echo "running E2E command to test the network after upgrade..." + + zetae2e "$ZETAE2E_CMD" --skip-setup --config deployed.yml + + ZETAE2E_EXIT_CODE=$? + if [ $ZETAE2E_EXIT_CODE -eq 0 ]; then + echo "E2E passed after upgrade" + exit 0 + else + echo "E2E failed after upgrade" + exit 1 + fi + +elif [ "$OPTION" == "setup-only" ]; then + + # Setup localnet with the --setup-only flag + + zetae2e "$ZETAE2E_CMD" --setup-only + + ZETAE2E_EXIT_CODE=$? + if [ $ZETAE2E_EXIT_CODE -eq 0 ]; then + echo "Localnet setup" + exit 0 + else + echo "Localnet failed to start" + exit 1 + fi -# if e2e passed, exit with 0, otherwise exit with 1 -if [ $ZETAE2E_EXIT_CODE -eq 0 ]; then - cat /work/deployed.yml - echo "e2e passed" - exit 0 else - echo "e2e failed" - exit 1 + + # Run the e2e tests normally + + echo "running e2e tests..." + zetae2e "$ZETAE2E_CMD" + ZETAE2E_EXIT_CODE=$? + + # if e2e passed, exit with 0, otherwise exit with 1 + if [ $ZETAE2E_EXIT_CODE -eq 0 ]; then + cat /work/deployed.yml + echo "e2e passed" + exit 0 + else + echo "e2e failed" + exit 1 + fi + fi diff --git a/contrib/localnet/scripts/os-info.sh b/contrib/localnet/scripts/add-keys.sh similarity index 93% rename from contrib/localnet/scripts/os-info.sh rename to contrib/localnet/scripts/add-keys.sh index 734b1a2f82..60038a8ec3 100644 --- a/contrib/localnet/scripts/os-info.sh +++ b/contrib/localnet/scripts/add-keys.sh @@ -1,5 +1,7 @@ #!/bin/bash +# This script allows to add keys for operator and hotkey and create the required json structure for os_info + KEYRING_TEST="test" KEYRING_FILE="file" HOSTNAME=$(hostname) diff --git a/contrib/localnet/scripts/env.sh b/contrib/localnet/scripts/env.sh deleted file mode 100644 index dc24195315..0000000000 --- a/contrib/localnet/scripts/env.sh +++ /dev/null @@ -1,26 +0,0 @@ -# these are the connector (MPI) contract addresses -export GOERLI_MPI_ADDRESS=0x00007d0BA516a2bA02D77907d3a1348C1187Ae62 -export GOERLILOCALNET_MPI_ADDRESS=0x00007d0BA516a2bA02D77907d3a1348C1187Ae62 -export BSCTESTNET_MPI_ADDRESS=0x000054d3A0Bc83Ec7808F52fCdC28A96c89F6C5c -export MUMBAI_MPI_ADDRESS=0x000054d3A0Bc83Ec7808F52fCdC28A96c89F6C5c -export ROPSTEN_MPI_ADDRESS=0x000054d3A0Bc83Ec7808F52fCdC28A96c89F6C5c -export BAOBAB_MPI_ADDRESS=0x000054d3A0Bc83Ec7808F52fCdC28A96c89F6C5c - -# uncomment if you want to use pool price as oracle -#unset DUMMY_PRICE -#export GOERLI_POOL_ADDRESS=V2:0xb3a16c2b68bbb0111ebd27871a5934b949837d95:ETHZETA -#export BSCTESTNET_POOL_ADDRESS=V2:0x775fbbceffcfc5fccd999df2924039d086199222:ZETAETH -#export MUMBAI_POOL_ADDRESS=V3:0x0F65426268D78e563eaDEaa865e92C4B948dD8A1:ZETAETH -#export ROPSTEN_POOL_ADDRESS=V2:0x3b45806771fa4508f11ec1601240e81f577a9fd1:ZETAETH -export DUMMY_PRICE=yes - -# this disables keygen instruction from zetacore. -export DISABLE_TSS_KEYGEN=yes - -# use your own quicknode API links please; free plan is more than enough -export BSCTESTNET_ENDPOINT=https://data-seed-prebsc-1-s1.binance.org:8545 -export GOERLI_ENDPOINT=https://goerli.infura.io/v3/50b6673dc48443e59047246df462902c -export GOERLILOCALNET_ENDPOINT=https://goerli.infura.io/v3/50b6673dc48443e59047246df462902c -export ROPSTEN_ENDPOINT=https://ropsten.infura.io/v3/50b6673dc48443e59047246df462902c -export MUMBAI_ENDPOINT=https://polygon-mumbai.infura.io/v3/50b6673dc48443e59047246df462902c -export BAOBAB_ENDPOINT=https://klaytn-baobab-rpc.allthatnode.com:8551 diff --git a/contrib/localnet/scripts/genesis-stateful.sh b/contrib/localnet/scripts/genesis-stateful.sh deleted file mode 100755 index d9d377f42f..0000000000 --- a/contrib/localnet/scripts/genesis-stateful.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash - -/usr/sbin/sshd - -if [ $# -ne 1 ] -then - echo "Usage: genesis.sh " - exit 1 -fi -NUMOFNODES=$1 - -# create keys -CHAINID="athens_101-1" -KEYRING="test" -HOSTNAME=$(hostname) -INDEX=${HOSTNAME:0-1} - -export DAEMON_HOME=$HOME/.zetacored -export DAEMON_NAME=zetacored -export DAEMON_ALLOW_DOWNLOAD_BINARIES=true -export DAEMON_RESTART_AFTER_UPGRADE=true -export CLIENT_DAEMON_NAME=zetaclientd -export CLIENT_DAEMON_ARGS="-enable-chains,GOERLI,-val,operator" -export DAEMON_DATA_BACKUP_DIR=$DAEMON_HOME -export CLIENT_SKIP_UPGRADE=true -export CLIENT_START_PROCESS=false -export UNSAFE_SKIP_BACKUP=true -export UpgradeName=${NEW_VERSION} - -# generate node list -START=1 -# shellcheck disable=SC2100 -END=$((NUMOFNODES - 1)) -NODELIST=() -for i in $(eval echo "{$START..$END}") -do - NODELIST+=("zetacore$i") -done - -echo "HOSTNAME: $HOSTNAME" - -# Init a new node to generate genesis file . -# Copy config files from existing folders which get copied via Docker Copy when building images -mkdir -p ~/.backup/config -zetacored init Zetanode-Localnet --chain-id=$CHAINID -rm -rf ~/.zetacored/config/app.toml -rm -rf ~/.zetacored/config/client.toml -rm -rf ~/.zetacored/config/config.toml -cp -r ~/zetacored/common/app.toml ~/.zetacored/config/ -cp -r ~/zetacored/common/client.toml ~/.zetacored/config/ -cp -r ~/zetacored/common/config.toml ~/.zetacored/config/ -sed -i -e "/moniker =/s/=.*/= \"$HOSTNAME\"/" "$HOME"/.zetacored/config/config.toml - -# Add two new keys for operator and hotkey and create the required json structure for os_info -source ~/os-info.sh - -# Pause other nodes so that the primary can node can do the genesis creation -if [ $HOSTNAME != "zetacore0" ] -then - echo "Waiting for zetacore0 to create genesis.json" - sleep 10 - echo "genesis.json created" -fi - -# Genesis creation following steps -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json -# 2. Add the observers , authorizations and required params to the genesis.json -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json -# 5. Copy the final genesis.json to all the nodes and start the nodes -# 6. Update Config in zetacore0 so that it has the correct persistent peer list -# 7. Start the nodes - -# Start of genesis creation . This is done only on zetacore0 -if [ $HOSTNAME == "zetacore0" ] -then - # Misc : Copying the keyring to the client nodes so that they can sign the transactions - ssh zetaclient0 mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* zetaclient0:~/.zetacored/keyring-test/ - -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json - for NODE in "${NODELIST[@]}"; do - INDEX=${NODE:0-1} - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/ - scp "$NODE":~/.zetacored/os_info/os.json ~/.zetacored/os_info/os_z"$INDEX".json - scp ~/.zetacored/os_info/os_z"$INDEX".json zetaclient"$INDEX":~/.zetacored/os.json - done - - ssh zetaclient0 mkdir -p ~/.zetacored/ - scp ~/.zetacored/os_info/os.json zetaclient0:/root/.zetacored/os.json - -# 2. Add the observers , authorizations and required params to the genesis.json - zetacored collect-observer-info - zetacored add-observer-list --keygen-block 55 - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["evm"]["params"]["evm_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="500000000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["voting_params"]["voting_period"]="100s"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - -# set fungible admin account as admin for fungible token - zetacored add-genesis-account zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk 100000000000000000000000000azeta - zetacored add-genesis-account zeta1n0rn6sne54hv7w2uu93fl48ncyqz97d3kty6sh 100000000000000000000000000azeta # Funds the localnet_gov_admin account - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][0]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][1]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - -# give balance to deployer account to deploy contracts directly on zEVM - zetacored add-genesis-account zeta1uhznv7uzyjq84s3q056suc8pkme85lkvhrz3dd 100000000000000000000000000azeta -# erc20 tester - zetacored add-genesis-account zeta1datate7xmwm4uk032f9rmcu0cwy7ch7kg6y6zv 100000000000000000000000000azeta -# zeta tester - zetacored add-genesis-account zeta1tnp0hvsq4y5mxuhrq9h3jfwulxywpq0ads0rer 100000000000000000000000000azeta -# bitcoin tester - zetacored add-genesis-account zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80 100000000000000000000000000azeta -# ethers tester - zetacored add-genesis-account zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga 100000000000000000000000000azeta - -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node - zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING - # Copy host gentx to other nodes - for NODE in "${NODELIST[@]}"; do - ssh $NODE mkdir -p ~/.zetacored/config/gentx/peer/ - scp ~/.zetacored/config/gentx/* $NODE:~/.zetacored/config/gentx/peer/ - done - # Create gentx files on other nodes and copy them to host node - mkdir ~/.zetacored/config/gentx/z2gentx - for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - ssh $NODE zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/ - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/z2gentx/ - done - -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json - zetacored collect-gentxs - zetacored validate-genesis -# 5. Copy the final genesis.json to all the nodes - for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - done -# 6. Update Config in zetacore0 so that it has the correct persistent peer list - sleep 2 - pp=$(cat $HOME/.zetacored/config/gentx/z2gentx/*.json | jq '.body.memo' ) - pps=${pp:1:58} - sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -fi -# End of genesis creation steps . The steps below are common to all the nodes - -# Update persistent peers -if [ $HOSTNAME != "zetacore0" ] -then - # Misc : Copying the keyring to the client nodes so that they can sign the transactions - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* "zetaclient$INDEX":~/.zetacored/keyring-test/ - - pp=$(cat $HOME/.zetacored/config/gentx/peer/*.json | jq '.body.memo' ) - pps=${pp:1:58} - sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -fi - -mkdir -p $DAEMON_HOME/cosmovisor/genesis/bin -mkdir -p $DAEMON_HOME/cosmovisor/upgrades/"$UpgradeName"/bin - -# Setup cosmovisor -# Genesis -cp $GOPATH/bin/old/zetacored $DAEMON_HOME/cosmovisor/genesis/bin -cp $GOPATH/bin/zetaclientd $DAEMON_HOME/cosmovisor/genesis/bin - -#Upgrades -cp $GOPATH/bin/new/zetacored $DAEMON_HOME/cosmovisor/upgrades/$UpgradeName/bin/ - -#Permissions -chmod +x $DAEMON_HOME/cosmovisor/genesis/bin/zetacored -chmod +x $DAEMON_HOME/cosmovisor/genesis/bin/zetaclientd -chmod +x $DAEMON_HOME/cosmovisor/upgrades/$UpgradeName/bin/zetacored - - -# 7 Start the nodes -cosmovisor run start --pruning=nothing --minimum-gas-prices=0.0001azeta --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --home /root/.zetacored >> zetanode.log 2>&1 & -sleep 20 -echo - -if [ $HOSTNAME = "zetacore0" ] -then -/root/.zetacored/cosmovisor/genesis/bin/zetacored tx gov submit-legacy-proposal software-upgrade $UpgradeName --from hotkey --deposit 100000000azeta --upgrade-height 200 --title $UpgradeName --description $UpgradeName --keyring-backend test --chain-id $CHAINID --yes --no-validate --fees=200azeta --broadcast-mode block -fi - -sleep 8 -/root/.zetacored/cosmovisor/genesis/bin/zetacored tx gov vote 1 yes --from operator --keyring-backend test --chain-id $CHAINID --yes --fees=200azeta --broadcast-mode block -sleep 7 -/root/.zetacored/cosmovisor/genesis/bin/zetacored query gov proposal 1 - -tail -f zetanode.log \ No newline at end of file diff --git a/contrib/localnet/scripts/genesis-upgrade.sh b/contrib/localnet/scripts/genesis-upgrade.sh deleted file mode 100755 index 7e01983e66..0000000000 --- a/contrib/localnet/scripts/genesis-upgrade.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash - -/usr/sbin/sshd - -if [ $# -ne 1 ] -then - echo "Usage: genesis.sh " - exit 1 -fi -NUMOFNODES=$1 - -# create keys -CHAINID="athens_101-1" -KEYRING="test" -HOSTNAME=$(hostname) -INDEX=${HOSTNAME:0-1} - -# generate node list -START=1 -# shellcheck disable=SC2100 -END=$((NUMOFNODES - 1)) -NODELIST=() -for i in $(eval echo "{$START..$END}") -do - NODELIST+=("zetacore$i") -done - -echo "HOSTNAME: $HOSTNAME" - -# Init a new node to generate genesis file . -# Copy config files from existing folders which get copied via Docker Copy when building images -mkdir -p ~/.backup/config -zetacored init Zetanode-Localnet --chain-id=$CHAINID -rm -rf ~/.zetacored/config/app.toml -rm -rf ~/.zetacored/config/client.toml -rm -rf ~/.zetacored/config/config.toml -cp -r ~/zetacored/common/app.toml ~/.zetacored/config/ -cp -r ~/zetacored/common/client.toml ~/.zetacored/config/ -cp -r ~/zetacored/common/config.toml ~/.zetacored/config/ -sed -i -e "/moniker =/s/=.*/= \"$HOSTNAME\"/" "$HOME"/.zetacored/config/config.toml - -# Add two new keys for operator and hotkey and create the required json structure for os_info -source ~/os-info.sh - -# Pause other nodes so that the primary can node can do the genesis creation -if [ $HOSTNAME != "zetacore0" ] -then - echo "Waiting for zetacore0 to create genesis.json" - sleep $((7*NUMOFNODES)) - echo "genesis.json created" -fi - -# Genesis creation following steps -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json -# 2. Add the observers , authorizations and required params to the genesis.json -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json -# 5. Copy the final genesis.json to all the nodes and start the nodes -# 6. Update Config in zetacore0 so that it has the correct persistent peer list -# 7. Start the nodes - -# Start of genesis creation . This is done only on zetacore0 -if [ $HOSTNAME == "zetacore0" ] -then - # Misc : Copying the keyring to the client nodes so that they can sign the transactions - ssh zetaclient0 mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* zetaclient0:~/.zetacored/keyring-test/ - -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json - for NODE in "${NODELIST[@]}"; do - INDEX=${NODE:0-1} - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/ - scp "$NODE":~/.zetacored/os_info/os.json ~/.zetacored/os_info/os_z"$INDEX".json - scp ~/.zetacored/os_info/os_z"$INDEX".json zetaclient"$INDEX":~/.zetacored/os.json - done - - ssh zetaclient0 mkdir -p ~/.zetacored/ - scp ~/.zetacored/os_info/os.json zetaclient0:/root/.zetacored/os.json - -# 2. Add the observers , authorizations and required params to the genesis.json - zetacored collect-observer-info - zetacored add-observer-list - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["evm"]["params"]["evm_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="500000000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["voting_params"]["voting_period"]="100s"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - - # set admin account - zetacored add-genesis-account zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk 100000000000000000000000000azeta - zetacored add-genesis-account zeta1n0rn6sne54hv7w2uu93fl48ncyqz97d3kty6sh 100000000000000000000000000azeta # Funds the localnet_gov_admin account - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][0]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][1]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node - zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING - # Copy host gentx to other nodes - for NODE in "${NODELIST[@]}"; do - ssh $NODE mkdir -p ~/.zetacored/config/gentx/peer/ - scp ~/.zetacored/config/gentx/* $NODE:~/.zetacored/config/gentx/peer/ - done - # Create gentx files on other nodes and copy them to host node - mkdir ~/.zetacored/config/gentx/z2gentx - for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - ssh $NODE zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/ - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/z2gentx/ - done - -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json - zetacored collect-gentxs - zetacored validate-genesis -# 5. Copy the final genesis.json to all the nodes - for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - done -# 6. Update Config in zetacore0 so that it has the correct persistent peer list - sleep 2 - pp=$(cat $HOME/.zetacored/config/gentx/z2gentx/*.json | jq '.body.memo' ) - pps=${pp:1:58} - sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -fi -# End of genesis creation steps . The steps below are common to all the nodes - -# Update persistent peers -if [ $HOSTNAME != "zetacore0" ] -then - # Misc : Copying the keyring to the client nodes so that they can sign the transactions - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* "zetaclient$INDEX":~/.zetacored/keyring-test/ - - pp=$(cat $HOME/.zetacored/config/gentx/peer/*.json | jq '.body.memo' ) - pps=${pp:1:58} - sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -fi - -/root/zetacored-proposal.sh & - -# 7 Start the nodes -exec zetacored start --pruning=nothing --minimum-gas-prices=0.0001azeta --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --home /root/.zetacored \ No newline at end of file diff --git a/contrib/localnet/scripts/genesis.sh b/contrib/localnet/scripts/genesis.sh deleted file mode 100755 index 93c8833541..0000000000 --- a/contrib/localnet/scripts/genesis.sh +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/bash - -/usr/sbin/sshd - -if [ $# -ne 1 ] -then - echo "Usage: genesis.sh " - exit 1 -fi -NUMOFNODES=$1 - -# create keys -CHAINID="athens_101-1" -KEYRING="test" -HOSTNAME=$(hostname) -INDEX=${HOSTNAME:0-1} - -# generate node list -START=1 -# shellcheck disable=SC2100 -END=$((NUMOFNODES - 1)) -NODELIST=() -for i in $(eval echo "{$START..$END}") -do - NODELIST+=("zetacore$i") -done - -echo "HOSTNAME: $HOSTNAME" - -# Init a new node to generate genesis file . -# Copy config files from existing folders which get copied via Docker Copy when building images -mkdir -p ~/.backup/config -zetacored init Zetanode-Localnet --chain-id=$CHAINID -rm -rf ~/.zetacored/config/app.toml -rm -rf ~/.zetacored/config/client.toml -rm -rf ~/.zetacored/config/config.toml -cp -r ~/zetacored/common/app.toml ~/.zetacored/config/ -cp -r ~/zetacored/common/client.toml ~/.zetacored/config/ -cp -r ~/zetacored/common/config.toml ~/.zetacored/config/ -sed -i -e "/moniker =/s/=.*/= \"$HOSTNAME\"/" "$HOME"/.zetacored/config/config.toml - -# Add two new keys for operator and hotkey and create the required json structure for os_info -source ~/os-info.sh - -# Pause other nodes so that the primary can node can do the genesis creation -if [ $HOSTNAME != "zetacore0" ] -then - echo "Waiting for zetacore0 to create genesis.json" - sleep 10 - echo "genesis.json created" -fi - -# Genesis creation following steps -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json -# 2. Add the observers , authorizations and required params to the genesis.json -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json -# 5. Copy the final genesis.json to all the nodes and start the nodes -# 6. Update Config in zetacore0 so that it has the correct persistent peer list -# 7. Start the nodes - -# Start of genesis creation . This is done only on zetacore0 -if [ $HOSTNAME == "zetacore0" ] -then - # Misc : Copying the keyring to the client nodes so that they can sign the transactions - ssh zetaclient0 mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* zetaclient0:~/.zetacored/keyring-test/ - ssh zetaclient0 mkdir -p ~/.zetacored/keyring-file/ - scp ~/.zetacored/keyring-file/* zetaclient0:~/.zetacored/keyring-file/ - -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json - for NODE in "${NODELIST[@]}"; do - INDEX=${NODE:0-1} - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/ - scp "$NODE":~/.zetacored/os_info/os.json ~/.zetacored/os_info/os_z"$INDEX".json - scp ~/.zetacored/os_info/os_z"$INDEX".json zetaclient"$INDEX":~/.zetacored/os.json - done - - ssh zetaclient0 mkdir -p ~/.zetacored/ - scp ~/.zetacored/os_info/os.json zetaclient0:/root/.zetacored/os.json - -# 2. Add the observers, authorizations, required params and accounts to the genesis.json - zetacored collect-observer-info - zetacored add-observer-list --keygen-block 55 - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["evm"]["params"]["evm_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="500000000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["voting_params"]["voting_period"]="100s"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["feemarket"]["params"]["min_gas_price"]="10000000000.0000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - -# set admin account - zetacored add-genesis-account zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk 100000000000000000000000000azeta - zetacored add-genesis-account zeta1n0rn6sne54hv7w2uu93fl48ncyqz97d3kty6sh 100000000000000000000000000azeta # Funds the localnet_gov_admin account - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][0]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][1]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - -# give balance to runner accounts to deploy contracts directly on zEVM -# deployer - zetacored add-genesis-account zeta1uhznv7uzyjq84s3q056suc8pkme85lkvhrz3dd 100000000000000000000000000azeta -# erc20 tester - zetacored add-genesis-account zeta1datate7xmwm4uk032f9rmcu0cwy7ch7kg6y6zv 100000000000000000000000000azeta -# zeta tester - zetacored add-genesis-account zeta1tnp0hvsq4y5mxuhrq9h3jfwulxywpq0ads0rer 100000000000000000000000000azeta -# bitcoin tester - zetacored add-genesis-account zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80 100000000000000000000000000azeta -# ethers tester - zetacored add-genesis-account zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga 100000000000000000000000000azeta - -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node - zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING --gas-prices 20000000000azeta - # Copy host gentx to other nodes - for NODE in "${NODELIST[@]}"; do - ssh $NODE mkdir -p ~/.zetacored/config/gentx/peer/ - scp ~/.zetacored/config/gentx/* $NODE:~/.zetacored/config/gentx/peer/ - done - # Create gentx files on other nodes and copy them to host node - mkdir ~/.zetacored/config/gentx/z2gentx - for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - ssh $NODE zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/ - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/z2gentx/ - done - -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json - zetacored collect-gentxs - zetacored validate-genesis -# 5. Copy the final genesis.json to all the nodes - for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - done -# 6. Update Config in zetacore0 so that it has the correct persistent peer list - pp=$(cat $HOME/.zetacored/config/gentx/z2gentx/*.json | jq '.body.memo' ) - pps=${pp:1:58} - sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -fi -# End of genesis creation steps . The steps below are common to all the nodes - -# Update persistent peers -if [ $HOSTNAME != "zetacore0" ] -then - # Misc : Copying the keyring to the client nodes so that they can sign the transactions - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* "zetaclient$INDEX":~/.zetacored/keyring-test/ - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/keyring-file/ - scp ~/.zetacored/keyring-file/* "zetaclient$INDEX":~/.zetacored/keyring-file/ - - pp=$(cat $HOME/.zetacored/config/gentx/peer/*.json | jq '.body.memo' ) - pps=${pp:1:58} - sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -fi - -# 7 Start the nodes -exec zetacored start --pruning=nothing --minimum-gas-prices=0.0001azeta --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --home /root/.zetacored \ No newline at end of file diff --git a/contrib/localnet/scripts/keygen.sh b/contrib/localnet/scripts/keygen.sh deleted file mode 100644 index 7c8cc7faf3..0000000000 --- a/contrib/localnet/scripts/keygen.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -if [ $# -ne 1 ] -then - echo "Usage: keygen.sh " - exit 1 -fi -BLOCKNUM=$1 -HOSTNAME=$(hostname) - -cp /root/preparams/PreParams_$HOSTNAME.json /root/preParams.json -num=$(echo $HOSTNAME | tr -dc '0-9') -node="zetacore$num" -mv /root/zetacored/zetacored_$node /root/.zetacored - -mv /root/tss/$HOSTNAME /root/.tss - - -if [ $HOSTNAME == "zetaclient0" ] -then - rm ~/.tss/address_book.seed - export TSSPATH=~/.tss2 - zetaclientd init --val val --log-console --enable-chains "GOERLI,BSCTESTNET" \ - --pre-params ~/preParams.json --keygen-block $BLOCKNUM --zetacore-url zetacore0 \ - --chain-id athens_101-1 - zetaclientd start -else - num=$(echo $HOSTNAME | tr -dc '0-9') - node="zetacore$num" - SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) - - export TSSPATH=~/.tss2 - zetaclientd init --val val --log-console --enable-chains "GOERLI,BSCTESTNET" \ - --peer /dns/zetaclient0/tcp/6668/p2p/$SEED \ - --pre-params ~/preParams.json --keygen-block $BLOCKNUM --zetacore-url $node \ - --chain-id athens_101-1 - zetaclientd start -fi - - diff --git a/contrib/localnet/scripts/draft_proposal.json b/contrib/localnet/scripts/proposals/draft_proposal.json similarity index 100% rename from contrib/localnet/scripts/draft_proposal.json rename to contrib/localnet/scripts/proposals/draft_proposal.json diff --git a/contrib/localnet/scripts/reset-testnet.sh b/contrib/localnet/scripts/reset-testnet.sh deleted file mode 100644 index ca9d0369a4..0000000000 --- a/contrib/localnet/scripts/reset-testnet.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash -set -x - -CHAINID="athens_101-1" -KEYRING="test" -HOSTNAME=$(hostname) - -if [ $# -ne 1 ] -then - echo "Usage: reset-testnet.sh " - exit 1 -fi -NUMOFNODES=$1 - -# generate node list -START=1 -# shellcheck disable=SC2100 -END=$((NUMOFNODES - 1)) -NODELIST=() -for i in $(eval echo "{$START..$END}") -do - NODELIST+=("zetacore$i") -done - -HOSTNAME=$(hostname) -if [ $HOSTNAME != "zetacore0" ] -then - echo "You should run this only on zetacore0." - exit 1 -fi - - - -# Init a new node to generate genesis file. -# Copy config files from existing folders which get copied via Docker Copy when building images -mkdir -p ~/.backup/config -zetacored init Zetanode-Localnet --chain-id="$CHAINID" -for NODE in "${NODELIST[@]}" -do - ssh "$NODE" mkdir -p ~/.backup/config - ssh "$NODE" zetacored init Zetanode-Localnet --chain-id="$CHAINID" -done - -# Add two new keys for operator and hotkey and create the required json structure for os_info -source /root/os-info.sh -for NODE in "${NODELIST[@]}"; do - ssh $NODE source /root/os-info.sh -done - - -# Start of genesis creation. - -# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json -ssh zetaclient0 mkdir -p ~/.zetacored/ -scp ~/.zetacored/os_info/os.json zetaclient0:~/.zetacored/os.json -for NODE in "${NODELIST[@]}"; do - INDEX=${NODE:0-1} - ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/ - scp "$NODE":~/.zetacored/os_info/os.json ~/.zetacored/os_info/os_z"$INDEX".json - scp ~/.zetacored/os_info/os_z"$INDEX".json zetaclient"$INDEX":~/.zetacored/os.json -done - -# 2. Add the observers , authorizations and required params to the genesis.json -zetacored collect-observer-info -zetacored add-observer-list -cat $HOME/.zetacored/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json -cat $HOME/.zetacored/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json -cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json -cat $HOME/.zetacored/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json -cat $HOME/.zetacored/config/genesis.json | jq '.app_state["evm"]["params"]["evm_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json -cat $HOME/.zetacored/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="10000000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json - -# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node -zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING -mkdir ~/.zetacored/config/gentx/z2gentx -for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json - ssh $NODE zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/ - scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/z2gentx/ -done - -# 4. Collect all the gentx files in zetacore0 and create the final genesis.json -zetacored collect-gentxs -zetacored validate-genesis - -# 5. Copy the final genesis.json to all the nodes -for NODE in "${NODELIST[@]}"; do - ssh $NODE rm -rf ~/.zetacored/genesis.json - scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json -done - -# 6. Update Config in zetacore0 so that it has the correct persistent peer list -sleep 2 -pp=$(cat $HOME/.zetacored/config/gentx/z2gentx/*.json | jq '.body.memo' ) -pps=${pp:1:58} -sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml -# End of genesis creation steps . The steps below are common to all the nodes - -# Misc : Copying the keyring to the client nodes so that they can sign the transactions -# We do not need to use keyring/* , as the client only needs the hotkey to sign the transactions but differentiating between the two keys would add additional logic to the script -scp ~/.zetacored/keyring-test/* "zetaclient0":~/.zetacored/keyring-test/ -for NODE in "${NODELIST[@]}"; do - INDEX=${NODE:0-1} - ssh "zetaclient$INDEX" mkdir -p ~/.zetacored/keyring-test/ - scp ~/.zetacored/keyring-test/* "zetaclient$INDEX":~/.zetacored/keyring-test/ -done \ No newline at end of file diff --git a/contrib/localnet/scripts/seed.sh b/contrib/localnet/scripts/seed.sh deleted file mode 100644 index 9d6557e5f3..0000000000 --- a/contrib/localnet/scripts/seed.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -HOSTNAME=$(hostname) - -if [ $HOSTNAME == "node0" ] -then - export TSSPATH=~/.tss2 - zetaclientd init --val val --log-console --enable-chains "GOERLI,BSCTESTNET" --pre-params ~/preParams.json - zetaclientd start -else - SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s node0:8123/p2p) - echo "SEED:" $SEED - echo $SEED > ~/.seed -fi diff --git a/contrib/localnet/scripts/setup-testnet.sh b/contrib/localnet/scripts/setup-testnet.sh deleted file mode 100644 index a110bfc7fd..0000000000 --- a/contrib/localnet/scripts/setup-testnet.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -set -x -ZETACORED=/usr/local/bin/zetacored -NODES="zetacore1" -HOSTNAME=$(hostname) -if [ $HOSTNAME != "zetacore0" ] -then - echo "You should run this only on zetacore0." - exit 1 -fi - -if $ZETACORED validate-genesis; then - echo "Genesis file is valid" -else - echo "Genesis file is invalid" - exit 1 -fi - -NODES="zetacore0 zetacore1" -for NODE in $NODES; do - ssh $NODE $ZETACORED validate-genesis - scp -done - diff --git a/contrib/localnet/scripts/start-zetaclientd-background.sh b/contrib/localnet/scripts/start-zetaclientd-background.sh deleted file mode 100644 index c41d13ff58..0000000000 --- a/contrib/localnet/scripts/start-zetaclientd-background.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -/usr/sbin/sshd - -HOSTNAME=$(hostname) - -# read HOTKEY_BACKEND env var for hotkey keyring backend and set default to test -BACKEND="test" -if [ "$HOTKEY_BACKEND" == "file" ]; then - BACKEND="file" -fi - - -cp /root/preparams/PreParams_$HOSTNAME.json /root/preParams.json -num=$(echo $HOSTNAME | tr -dc '0-9') -node="zetacore$num" - -echo "Wait for zetacore to exchange genesis file" -sleep 40 -operator=$(cat $HOME/.zetacored/os.json | jq '.ObserverAddress' ) -operatorAddress=$(echo "$operator" | tr -d '"') -echo "operatorAddress: $operatorAddress" -echo "Start zetaclientd" -if [ $HOSTNAME == "zetaclient0" ] -then - rm ~/.tss/* - MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) - zetaclientd init --zetacore-url zetacore0 --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --keyring-backend "$BACKEND" - zetaclientd start < /root/password.file > $HOME/zetaclient.log 2>&1 & -else - num=$(echo $HOSTNAME | tr -dc '0-9') - node="zetacore$num" - MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) - SEED="" - while [ -z "$SEED" ] - do - SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) - done - rm ~/.tss/* - zetaclientd init --peer /ip4/172.20.0.21/tcp/6668/p2p/"$SEED" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 1 --keyring-backend "$BACKEND" - zetaclientd start < /root/password.file > $HOME/zetaclient.log 2>&1 & -fi - -sleep 3 -tail -f $HOME/zetaclient.log \ No newline at end of file diff --git a/contrib/localnet/scripts/start-zetaclientd-genesis.sh b/contrib/localnet/scripts/start-zetaclientd-genesis.sh deleted file mode 100755 index 4716973fc8..0000000000 --- a/contrib/localnet/scripts/start-zetaclientd-genesis.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -/usr/sbin/sshd - -HOSTNAME=$(hostname) - -# read HOTKEY_BACKEND env var for hotkey keyring backend and set default to test -BACKEND="test" -if [ "$HOTKEY_BACKEND" == "file" ]; then - BACKEND="file" -fi - -cp /root/preparams/PreParams_$HOSTNAME.json /root/preParams.json -num=$(echo $HOSTNAME | tr -dc '0-9') -node="zetacore$num" - -echo "Wait for zetacore to exchange genesis file" -sleep 40 -operator=$(cat $HOME/.zetacored/os.json | jq '.ObserverAddress' ) -operatorAddress=$(echo "$operator" | tr -d '"') -echo "operatorAddress: $operatorAddress" -echo "Start zetaclientd" -if [ $HOSTNAME == "zetaclient0" ] -then - rm ~/.tss/* - MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) - zetaclientd init --zetacore-url zetacore0 --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --keyring-backend "$BACKEND" - zetaclientd start < /root/password.file -else - num=$(echo $HOSTNAME | tr -dc '0-9') - node="zetacore$num" - MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) - SEED="" - while [ -z "$SEED" ] - do - SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) - done - rm ~/.tss/* - zetaclientd init --peer /ip4/172.20.0.21/tcp/6668/p2p/"$SEED" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 1 --keyring-backend "$BACKEND" - zetaclientd start < /root/password.file -fi diff --git a/contrib/localnet/scripts/start-zetaclientd-p2p-diag.sh b/contrib/localnet/scripts/start-zetaclientd-p2p-diag.sh deleted file mode 100644 index 310e245878..0000000000 --- a/contrib/localnet/scripts/start-zetaclientd-p2p-diag.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -HOSTNAME=$(hostname) - -cp /root/preparams/PreParams_$HOSTNAME.json /root/preParams.json -num=$(echo $HOSTNAME | tr -dc '0-9') -node="zetacore$num" -mv /root/zetacored/zetacored_$node /root/.zetacored - -mv /root/tss/$HOSTNAME /root/.tss - - -if [ $HOSTNAME == "zetaclient0" ] -then - rm ~/.tss/address_book.seed - export TSSPATH=~/.tss - zetaclientd init --enable-chains "goerli_localnet,btc_regtest" \ - --pre-params ~/preParams.json --zetacore-url zetacore0 \ - --chain-id athens_101-1 --dev --operator zeta1z46tdw75jvh4h39y3vu758ctv34rw5z9kmyhgz --log-level 0 --hotkey=val_grantee_observer \ - --p2p-diagnostic - zetaclientd start < /root/password.file -else - num=$(echo $HOSTNAME | tr -dc '0-9') - node="zetacore$num" - SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) - - export TSSPATH=~/.tss - zetaclientd init --enable-chains "goerli_localnet,btc_regtest" \ - --peer /ip4/172.20.0.21/tcp/6668/p2p/$SEED \ - --pre-params ~/preParams.json --zetacore-url $node \ - --chain-id athens_101-1 --dev --operator zeta1lz2fqwzjnk6qy48fgj753h48444fxtt7hekp52 --log-level 0 --hotkey=val_grantee_observer \ - --p2p-diagnostic - zetaclientd start < /root/password.file -fi diff --git a/contrib/localnet/scripts/start-zetaclientd.sh b/contrib/localnet/scripts/start-zetaclientd.sh old mode 100644 new mode 100755 index eecb8b8e5d..d519a1fbc9 --- a/contrib/localnet/scripts/start-zetaclientd.sh +++ b/contrib/localnet/scripts/start-zetaclientd.sh @@ -1,28 +1,52 @@ #!/bin/bash + +# This script is used to start ZetaClient for the localnet +# An optional argument can be passed and can have the following value: +# background: start the ZetaClient in the background + +/usr/sbin/sshd + HOSTNAME=$(hostname) +OPTION=$1 + +# read HOTKEY_BACKEND env var for hotkey keyring backend and set default to test +BACKEND="test" +if [ "$HOTKEY_BACKEND" == "file" ]; then + BACKEND="file" +fi cp /root/preparams/PreParams_$HOSTNAME.json /root/preParams.json num=$(echo $HOSTNAME | tr -dc '0-9') node="zetacore$num" -mv /root/zetacored/zetacored_$node /root/.zetacored - -mv /root/tss/$HOSTNAME /root/.tss - +echo "Wait for zetacore to exchange genesis file" +sleep 40 +operator=$(cat $HOME/.zetacored/os.json | jq '.ObserverAddress' ) +operatorAddress=$(echo "$operator" | tr -d '"') +echo "operatorAddress: $operatorAddress" +echo "Start zetaclientd" if [ $HOSTNAME == "zetaclient0" ] then - rm ~/.tss/address_book.seed - zetaclientd init \ - --pre-params ~/preParams.json --zetacore-url zetacore0 \ - --chain-id athens_101-1 --operator zeta1z46tdw75jvh4h39y3vu758ctv34rw5z9kmyhgz --log-level 1 --hotkey=val_grantee_observer - zetaclientd start + rm ~/.tss/* + MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) + zetaclientd init --zetacore-url zetacore0 --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --keyring-backend "$BACKEND" + zetaclientd start < /root/password.file else num=$(echo $HOSTNAME | tr -dc '0-9') node="zetacore$num" - SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) - zetaclientd init \ - --peer /ip4/172.20.0.21/tcp/6668/p2p/$SEED \ - --pre-params ~/preParams.json --zetacore-url $node \ - --chain-id athens_101-1 --operator zeta1lz2fqwzjnk6qy48fgj753h48444fxtt7hekp52 --log-level 1 --hotkey=val_grantee_observer - zetaclientd start + MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1) + SEED="" + while [ -z "$SEED" ] + do + SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) + done + rm ~/.tss/* + zetaclientd init --peer /ip4/172.20.0.21/tcp/6668/p2p/"$SEED" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 1 --keyring-backend "$BACKEND" + zetaclientd start < /root/password.file fi + +if [ "$OPTION" == "background" ]; then + sleep 3 + tail -f $HOME/zetaclient.log +fi + diff --git a/contrib/localnet/scripts/start-zetacored.sh b/contrib/localnet/scripts/start-zetacored.sh old mode 100644 new mode 100755 index 04dfa5733c..559f07c862 --- a/contrib/localnet/scripts/start-zetacored.sh +++ b/contrib/localnet/scripts/start-zetacored.sh @@ -1,16 +1,227 @@ #!/bin/bash +# This script is used to start the zetacored nodes +# It initializes the nodes and creates the genesis.json file +# It also starts the nodes +# The number of nodes is passed as an first argument to the script +# The second argument is optional and can have the following value: +# 1. upgrade : This is used to test the upgrade process, a proposal is created for the upgrade and the nodes are started using cosmovisor + +/usr/sbin/sshd + +if [ $# -lt 1 ] +then + echo "Usage: genesis.sh [option]" + exit 1 +fi +NUMOFNODES=$1 +OPTION=$2 + +# create keys +CHAINID="athens_101-1" +KEYRING="test" HOSTNAME=$(hostname) -cp -r "/root/zetacored/zetacored_$HOSTNAME" /root/.zetacored +INDEX=${HOSTNAME:0-1} -if [ -f "/root/.zetacored/data/priv_validator_state.json" ]; then - echo "priv_validator_state.json already exists" -else - echo "priv_validator_state.json does not exist; creating an empty one" - mkdir -p /root/.zetacored/data - cp -r "/root/zetacored/zetacored_$HOSTNAME/priv_validator_state.json" /root/.zetacored/data +# Environment variables used for upgrade testing +export DAEMON_HOME=$HOME/.zetacored +export DAEMON_NAME=zetacored +export DAEMON_ALLOW_DOWNLOAD_BINARIES=true +export DAEMON_RESTART_AFTER_UPGRADE=true +export CLIENT_DAEMON_NAME=zetaclientd +export CLIENT_DAEMON_ARGS="-enable-chains,GOERLI,-val,operator" +export DAEMON_DATA_BACKUP_DIR=$DAEMON_HOME +export CLIENT_SKIP_UPGRADE=true +export CLIENT_START_PROCESS=false +export UNSAFE_SKIP_BACKUP=true +export UpgradeName=${NEW_VERSION} + +# upgrade name used for upgrade testing +export UpgradeName=${NEW_VERSION} + +# generate node list +START=1 +# shellcheck disable=SC2100 +END=$((NUMOFNODES - 1)) +NODELIST=() +for i in $(eval echo "{$START..$END}") +do + NODELIST+=("zetacore$i") +done + +echo "HOSTNAME: $HOSTNAME" + +# Init a new node to generate genesis file . +# Copy config files from existing folders which get copied via Docker Copy when building images +mkdir -p ~/.backup/config +zetacored init Zetanode-Localnet --chain-id=$CHAINID +rm -rf ~/.zetacored/config/app.toml +rm -rf ~/.zetacored/config/client.toml +rm -rf ~/.zetacored/config/config.toml +cp -r ~/zetacored/common/app.toml ~/.zetacored/config/ +cp -r ~/zetacored/common/client.toml ~/.zetacored/config/ +cp -r ~/zetacored/common/config.toml ~/.zetacored/config/ +sed -i -e "/moniker =/s/=.*/= \"$HOSTNAME\"/" "$HOME"/.zetacored/config/config.toml + +# Add two new keys for operator and hotkey and create the required json structure for os_info +source ~/add-keys.sh + +# Pause other nodes so that the primary can node can do the genesis creation +if [ $HOSTNAME != "zetacore0" ] +then + echo "Waiting for zetacore0 to create genesis.json" + sleep 10 + echo "genesis.json created" fi -/root/zetacored-proposal.sh & +# Genesis creation following steps +# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json +# 2. Add the observers , authorizations and required params to the genesis.json +# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node +# 4. Collect all the gentx files in zetacore0 and create the final genesis.json +# 5. Copy the final genesis.json to all the nodes and start the nodes +# 6. Update Config in zetacore0 so that it has the correct persistent peer list +# 7. Start the nodes + +# Start of genesis creation . This is done only on zetacore0 +if [ $HOSTNAME == "zetacore0" ] +then + # Misc : Copying the keyring to the client nodes so that they can sign the transactions + ssh zetaclient0 mkdir -p ~/.zetacored/keyring-test/ + scp ~/.zetacored/keyring-test/* zetaclient0:~/.zetacored/keyring-test/ + ssh zetaclient0 mkdir -p ~/.zetacored/keyring-file/ + scp ~/.zetacored/keyring-file/* zetaclient0:~/.zetacored/keyring-file/ + +# 1. Accumulate all the os_info files from other nodes on zetcacore0 and create a genesis.json + for NODE in "${NODELIST[@]}"; do + INDEX=${NODE:0-1} + ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/ + scp "$NODE":~/.zetacored/os_info/os.json ~/.zetacored/os_info/os_z"$INDEX".json + scp ~/.zetacored/os_info/os_z"$INDEX".json zetaclient"$INDEX":~/.zetacored/os.json + done + + ssh zetaclient0 mkdir -p ~/.zetacored/ + scp ~/.zetacored/os_info/os.json zetaclient0:/root/.zetacored/os.json + +# 2. Add the observers, authorizations, required params and accounts to the genesis.json + zetacored collect-observer-info + zetacored add-observer-list --keygen-block 55 + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["evm"]["params"]["evm_denom"]="azeta"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="500000000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["gov"]["voting_params"]["voting_period"]="100s"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["feemarket"]["params"]["min_gas_price"]="10000000000.0000"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + +# set admin account + zetacored add-genesis-account zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk 100000000000000000000000000azeta + zetacored add-genesis-account zeta1n0rn6sne54hv7w2uu93fl48ncyqz97d3kty6sh 100000000000000000000000000azeta # Funds the localnet_gov_admin account + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][0]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + cat $HOME/.zetacored/config/genesis.json | jq '.app_state["observer"]["params"]["admin_policy"][1]["address"]="zeta1srsq755t654agc0grpxj4y3w0znktrpr9tcdgk"' > $HOME/.zetacored/config/tmp_genesis.json && mv $HOME/.zetacored/config/tmp_genesis.json $HOME/.zetacored/config/genesis.json + +# give balance to runner accounts to deploy contracts directly on zEVM +# deployer + zetacored add-genesis-account zeta1uhznv7uzyjq84s3q056suc8pkme85lkvhrz3dd 100000000000000000000000000azeta +# erc20 tester + zetacored add-genesis-account zeta1datate7xmwm4uk032f9rmcu0cwy7ch7kg6y6zv 100000000000000000000000000azeta +# zeta tester + zetacored add-genesis-account zeta1tnp0hvsq4y5mxuhrq9h3jfwulxywpq0ads0rer 100000000000000000000000000azeta +# bitcoin tester + zetacored add-genesis-account zeta19q7czqysah6qg0n4y3l2a08gfzqxydla492v80 100000000000000000000000000azeta +# ethers tester + zetacored add-genesis-account zeta134rakuus43xn63yucgxhn88ywj8ewcv6ezn2ga 100000000000000000000000000azeta + +# 3. Copy the genesis.json to all the nodes .And use it to create a gentx for every node + zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING --gas-prices 20000000000azeta + # Copy host gentx to other nodes + for NODE in "${NODELIST[@]}"; do + ssh $NODE mkdir -p ~/.zetacored/config/gentx/peer/ + scp ~/.zetacored/config/gentx/* $NODE:~/.zetacored/config/gentx/peer/ + done + # Create gentx files on other nodes and copy them to host node + mkdir ~/.zetacored/config/gentx/z2gentx + for NODE in "${NODELIST[@]}"; do + ssh $NODE rm -rf ~/.zetacored/genesis.json + scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json + ssh $NODE zetacored gentx operator 1000000000000000000000azeta --chain-id=$CHAINID --keyring-backend=$KEYRING + scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/ + scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/z2gentx/ + done + +# 4. Collect all the gentx files in zetacore0 and create the final genesis.json + zetacored collect-gentxs + zetacored validate-genesis +# 5. Copy the final genesis.json to all the nodes + for NODE in "${NODELIST[@]}"; do + ssh $NODE rm -rf ~/.zetacored/genesis.json + scp ~/.zetacored/config/genesis.json $NODE:~/.zetacored/config/genesis.json + done +# 6. Update Config in zetacore0 so that it has the correct persistent peer list + pp=$(cat $HOME/.zetacored/config/gentx/z2gentx/*.json | jq '.body.memo' ) + pps=${pp:1:58} + sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml +fi +# End of genesis creation steps . The steps below are common to all the nodes + +# Update persistent peers +if [ $HOSTNAME != "zetacore0" ] +then + # Misc : Copying the keyring to the client nodes so that they can sign the transactions + ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/keyring-test/ + scp ~/.zetacored/keyring-test/* "zetaclient$INDEX":~/.zetacored/keyring-test/ + ssh zetaclient"$INDEX" mkdir -p ~/.zetacored/keyring-file/ + scp ~/.zetacored/keyring-file/* "zetaclient$INDEX":~/.zetacored/keyring-file/ + + pp=$(cat $HOME/.zetacored/config/gentx/peer/*.json | jq '.body.memo' ) + pps=${pp:1:58} + sed -i -e "/persistent_peers =/s/=.*/= \"$pps\"/" "$HOME"/.zetacored/config/config.toml +fi + +# 7 Start the nodes +# If upgrade option is passed, use cosmovisor to start the nodes and create a governance proposal for upgrade +if [ "$OPTION" != "upgrade" ]; then + + exec zetacored start --pruning=nothing --minimum-gas-prices=0.0001azeta --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --home /root/.zetacored + +else + + # Setup cosmovisor + mkdir -p $DAEMON_HOME/cosmovisor/genesis/bin + mkdir -p $DAEMON_HOME/cosmovisor/upgrades/"$UpgradeName"/bin + + # Genesis + cp $GOPATH/bin/old/zetacored $DAEMON_HOME/cosmovisor/genesis/bin + cp $GOPATH/bin/zetaclientd $DAEMON_HOME/cosmovisor/genesis/bin + + #Upgrades + cp $GOPATH/bin/new/zetacored $DAEMON_HOME/cosmovisor/upgrades/$UpgradeName/bin/ + + #Permissions + chmod +x $DAEMON_HOME/cosmovisor/genesis/bin/zetacored + chmod +x $DAEMON_HOME/cosmovisor/genesis/bin/zetaclientd + chmod +x $DAEMON_HOME/cosmovisor/upgrades/$UpgradeName/bin/zetacored + + # Start the node using cosmovisor + cosmovisor run start --pruning=nothing --minimum-gas-prices=0.0001azeta --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --home /root/.zetacored >> zetanode.log 2>&1 & + sleep 20 + echo + + # If this is the first node, create a governance proposal for upgrade + if [ $HOSTNAME = "zetacore0" ] + then + /root/.zetacored/cosmovisor/genesis/bin/zetacored tx gov submit-legacy-proposal software-upgrade $UpgradeName --from hotkey --deposit 100000000azeta --upgrade-height 200 --title $UpgradeName --description $UpgradeName --keyring-backend test --chain-id $CHAINID --yes --no-validate --fees=2000000000000000azeta --broadcast-mode block + fi + + # Wait for the proposal to be voted on + sleep 8 + /root/.zetacored/cosmovisor/genesis/bin/zetacored tx gov vote 1 yes --from operator --keyring-backend test --chain-id $CHAINID --yes --fees=2000000000000000azeta --broadcast-mode block + sleep 7 + /root/.zetacored/cosmovisor/genesis/bin/zetacored query gov proposal 1 + + # We use tail -f to keep the container running + tail -f zetanode.log + +fi -zetacored start --pruning=nothing --minimum-gas-prices=0.0001azeta --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --home /root/.zetacored \ No newline at end of file diff --git a/contrib/localnet/scripts/gov-proposals-testing.sh b/contrib/localnet/scripts/test-gov-proposals.sh similarity index 79% rename from contrib/localnet/scripts/gov-proposals-testing.sh rename to contrib/localnet/scripts/test-gov-proposals.sh index a984fa9250..7cd479ef74 100755 --- a/contrib/localnet/scripts/gov-proposals-testing.sh +++ b/contrib/localnet/scripts/test-gov-proposals.sh @@ -1,5 +1,14 @@ #!/bin/bash +# This script is used to create a variety of proposals for testing purposes +# It creates proposals with different deposit amounts, voting periods, and content +# It also creates proposals with different voting options and votes on them +# It is intended to be run after the network has been started and the zetacored client is running +# It is intended to be run from the root of the zetacored repository +# It is intended to be run with the following command +# docker exec -it zetacore0 bash +# #/root/test-gov-proposals.sh + SCRIPT_DIR=$(dirname "$0") cd "$SCRIPT_DIR" || exit @@ -32,10 +41,3 @@ zetacored tx gov vote 6 VOTE_OPTION_YES --from $WALLET_NAME --keyring-backend te zetacored tx gov submit-proposal proposals/proposal_for_deposit.json --from $WALLET_NAME --keyring-backend test --chain-id athens_101-1 --fees 2000000000000000azeta --yes && sleep 12 zetacored tx gov vote 7 VOTE_OPTION_YES --from $WALLET_NAME --keyring-backend test --chain-id athens_101-1 --fees 2000000000000000azeta --yes && sleep 12 - -# Consensus param test -#zetacored tx gov submit-legacy-proposal param-change proposals/proposal_for_consensus_params.json --from $WALLET_NAME --keyring-backend test --chain-id athens_101-1 --fees 2000000000000000azeta --yes && sleep 12 -#zetacored tx gov vote 1 VOTE_OPTION_YES --from $WALLET_NAME --keyring-backend test --chain-id athens_101-1 --fees 2000000000000000azeta --yes && sleep 12 - -#zetacored tx gov submit-legacy-proposal param-change proposals/emissions_change.json --from $WALLET_NAME --keyring-backend test --chain-id athens_101-1 --gas 1000000 --yes && sleep 12 -#zetacored tx gov vote 1 VOTE_OPTION_YES --from $WALLET_NAME --keyring-backend test --chain-id athens_101-1 --fees 2000000000000000azeta --yes && sleep 12 diff --git a/contrib/localnet/scripts/zetacored-proposal.sh b/contrib/localnet/scripts/zetacored-proposal.sh deleted file mode 100644 index 722d4474ff..0000000000 --- a/contrib/localnet/scripts/zetacored-proposal.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -echo "proposal script running..." -sleep 100 - -HOSTNAME=$(hostname) -num=$(echo $HOSTNAME | tr -dc '0-9') - -cd /root - -if [ "$num" == "0" ] -then - zetacored tx gov submit-proposal draft_proposal.json --from operator --chain-id athens_101-1 --fees 20azeta --yes -fi - -sleep 10 -zetacored tx gov vote 1 yes --from operator --keyring-backend test --chain-id athens_101-1 --yes --fees 20azeta --yes - - diff --git a/contrib/localnet/orchestrator/smoketest/README.md b/e2e/README.md similarity index 52% rename from contrib/localnet/orchestrator/smoketest/README.md rename to e2e/README.md index 0ac8e82e75..882f73c100 100644 --- a/contrib/localnet/orchestrator/smoketest/README.md +++ b/e2e/README.md @@ -1,23 +1,22 @@ -# `smoketest` +# `e2e` -`smoketest` is a comprehensive suite of smoke tests designed to validate the integration and functionality of the ZetaChain network, particularly its interactions with Bitcoin and EVM (Ethereum Virtual Machine) networks. This tool is essential for ensuring the robustness and reliability of ZetaChain's cross-chain functionalities. +`e2e` is a comprehensive suite of E2E tests designed to validate the integration and functionality of the ZetaChain network, particularly its interactions with Bitcoin and EVM (Ethereum Virtual Machine) networks. This tool is essential for ensuring the robustness and reliability of ZetaChain's cross-chain functionalities. ## Packages -The smoketest project is organized into several packages, each with a specific role: +The E2E testing project is organized into several packages, each with a specific role: -- `cmd`: Contains the main commands to execute the smoke tests. -- `config`: Provides general configuration for smoke tests, including RPC addresses for connected networks, addresses of deployed smart contracts, and account details for test transactions. +- `config`: Provides general configuration for E2E tests, including RPC addresses for connected networks, addresses of deployed smart contracts, and account details for test transactions. - `contracts`: Includes sample Solidity smart contracts used in testing scenarios. -- `runner`: Responsible for executing smoke tests, handling interactions with various network clients. -- `smoketests`: Houses a collection of smoke tests that can be run against the ZetaChain network. +- `runner`: Responsible for executing E2E tests, handling interactions with various network clients. +- `e2etests`: Houses a collection of E2E tests that can be run against the ZetaChain network. - `txserver`: A minimalistic client for interacting with the ZetaChain RPC interface. - `utils`: Offers utility functions to facilitate interactions with the different blockchain networks involved in testing. ## Config -The smoketest suite utilizes a flexible and comprehensive configuration system defined in the config package, which is central to setting up and customizing your test environments. The configuration is structured as follows: +The E2E testing suite utilizes a flexible and comprehensive configuration system defined in the config package, which is central to setting up and customizing your test environments. The configuration is structured as follows: -A config YAML file can be provided to the smoke test tool via the `--config` flag. If no config file is provided, the tool will use default values for all configuration parameters. +A config YAML file can be provided to the E2E test tool via the `--config` flag. If no config file is provided, the tool will use default values for all configuration parameters. ### Config Structure - `RPCs`: Defines the RPC endpoints for various networks involved in the testing. @@ -57,7 +56,3 @@ zeta_chain_id: "zetachain-1" ``` NOTE: config is in progress, contracts on the zEVM must be added - -## Getting Started - -TODO: Add instructions for running the smoketest tool directly from the command line. \ No newline at end of file diff --git a/contrib/localnet/orchestrator/smoketest/config/config.go b/e2e/config/config.go similarity index 98% rename from contrib/localnet/orchestrator/smoketest/config/config.go rename to e2e/config/config.go index 442ab6df63..46281b5558 100644 --- a/contrib/localnet/orchestrator/smoketest/config/config.go +++ b/e2e/config/config.go @@ -10,7 +10,7 @@ import ( "gopkg.in/yaml.v2" ) -// Config contains the configuration for the smoke test +// Config contains the configuration for the e2e test type Config struct { Accounts Accounts `yaml:"accounts"` RPCs RPCs `yaml:"rpcs"` @@ -81,7 +81,7 @@ func DefaultConfig() Config { EVM: "http://eth:8545", Bitcoin: BitcoinRPC{ Host: "bitcoin:18443", - User: "smoketest", + User: "e2e", Pass: "123", HTTPPostMode: true, DisableTLS: true, diff --git a/contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.abi b/e2e/contracts/contextapp/ContextApp.abi similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.abi rename to e2e/contracts/contextapp/ContextApp.abi diff --git a/contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.bin b/e2e/contracts/contextapp/ContextApp.bin similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.bin rename to e2e/contracts/contextapp/ContextApp.bin diff --git a/contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.go b/e2e/contracts/contextapp/ContextApp.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.go rename to e2e/contracts/contextapp/ContextApp.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.json b/e2e/contracts/contextapp/ContextApp.json similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.json rename to e2e/contracts/contextapp/ContextApp.json diff --git a/contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.sol b/e2e/contracts/contextapp/ContextApp.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/contextapp/ContextApp.sol rename to e2e/contracts/contextapp/ContextApp.sol diff --git a/contrib/localnet/orchestrator/smoketest/contracts/contextapp/bindings.go b/e2e/contracts/contextapp/bindings.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/contextapp/bindings.go rename to e2e/contracts/contextapp/bindings.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.abi b/e2e/contracts/erc20/USDT.abi similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.abi rename to e2e/contracts/erc20/USDT.abi diff --git a/contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.bin b/e2e/contracts/erc20/USDT.bin similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.bin rename to e2e/contracts/erc20/USDT.bin diff --git a/contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.go b/e2e/contracts/erc20/USDT.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.go rename to e2e/contracts/erc20/USDT.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.json b/e2e/contracts/erc20/USDT.json similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/erc20/USDT.json rename to e2e/contracts/erc20/USDT.json diff --git a/contrib/localnet/orchestrator/smoketest/contracts/erc20/bindings.go b/e2e/contracts/erc20/bindings.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/erc20/bindings.go rename to e2e/contracts/erc20/bindings.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.abi b/e2e/contracts/testdapp/TestDApp.abi similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.abi rename to e2e/contracts/testdapp/TestDApp.abi diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.bin b/e2e/contracts/testdapp/TestDApp.bin similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.bin rename to e2e/contracts/testdapp/TestDApp.bin diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.go b/e2e/contracts/testdapp/TestDApp.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.go rename to e2e/contracts/testdapp/TestDApp.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.json b/e2e/contracts/testdapp/TestDApp.json similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.json rename to e2e/contracts/testdapp/TestDApp.json diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.sol b/e2e/contracts/testdapp/TestDApp.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testdapp/TestDApp.sol rename to e2e/contracts/testdapp/TestDApp.sol diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testdapp/bindings.go b/e2e/contracts/testdapp/bindings.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testdapp/bindings.go rename to e2e/contracts/testdapp/bindings.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.abi b/e2e/contracts/testzrc20/TestZRC20.abi similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.abi rename to e2e/contracts/testzrc20/TestZRC20.abi diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.bin b/e2e/contracts/testzrc20/TestZRC20.bin similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.bin rename to e2e/contracts/testzrc20/TestZRC20.bin diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.go b/e2e/contracts/testzrc20/TestZRC20.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.go rename to e2e/contracts/testzrc20/TestZRC20.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.json b/e2e/contracts/testzrc20/TestZRC20.json similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.json rename to e2e/contracts/testzrc20/TestZRC20.json diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.sol b/e2e/contracts/testzrc20/TestZRC20.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testzrc20/TestZRC20.sol rename to e2e/contracts/testzrc20/TestZRC20.sol diff --git a/contrib/localnet/orchestrator/smoketest/contracts/testzrc20/bindings.go b/e2e/contracts/testzrc20/bindings.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/testzrc20/bindings.go rename to e2e/contracts/testzrc20/bindings.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.abi b/e2e/contracts/vault/Vault.abi similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.abi rename to e2e/contracts/vault/Vault.abi diff --git a/contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.bin b/e2e/contracts/vault/Vault.bin similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.bin rename to e2e/contracts/vault/Vault.bin diff --git a/contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.go b/e2e/contracts/vault/Vault.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.go rename to e2e/contracts/vault/Vault.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.json b/e2e/contracts/vault/Vault.json similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.json rename to e2e/contracts/vault/Vault.json diff --git a/contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.sol b/e2e/contracts/vault/Vault.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/vault/Vault.sol rename to e2e/contracts/vault/Vault.sol diff --git a/contrib/localnet/orchestrator/smoketest/contracts/vault/bindings.go b/e2e/contracts/vault/bindings.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/vault/bindings.go rename to e2e/contracts/vault/bindings.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.abi b/e2e/contracts/zevmswap/ZEVMSwapApp.abi similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.abi rename to e2e/contracts/zevmswap/ZEVMSwapApp.abi diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.bin b/e2e/contracts/zevmswap/ZEVMSwapApp.bin similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.bin rename to e2e/contracts/zevmswap/ZEVMSwapApp.bin diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.go b/e2e/contracts/zevmswap/ZEVMSwapApp.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.go rename to e2e/contracts/zevmswap/ZEVMSwapApp.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.json b/e2e/contracts/zevmswap/ZEVMSwapApp.json similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.json rename to e2e/contracts/zevmswap/ZEVMSwapApp.json diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.sol b/e2e/contracts/zevmswap/ZEVMSwapApp.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/ZEVMSwapApp.sol rename to e2e/contracts/zevmswap/ZEVMSwapApp.sol diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/bindings.go b/e2e/contracts/zevmswap/bindings.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/bindings.go rename to e2e/contracts/zevmswap/bindings.go diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/interfaces/IUniswapV2Router01.sol b/e2e/contracts/zevmswap/interfaces/IUniswapV2Router01.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/interfaces/IUniswapV2Router01.sol rename to e2e/contracts/zevmswap/interfaces/IUniswapV2Router01.sol diff --git a/contrib/localnet/orchestrator/smoketest/contracts/zevmswap/interfaces/IUniswapV2Router02.sol b/e2e/contracts/zevmswap/interfaces/IUniswapV2Router02.sol similarity index 100% rename from contrib/localnet/orchestrator/smoketest/contracts/zevmswap/interfaces/IUniswapV2Router02.sol rename to e2e/contracts/zevmswap/interfaces/IUniswapV2Router02.sol diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/smoketests.go b/e2e/e2etests/e2etests.go similarity index 95% rename from contrib/localnet/orchestrator/smoketest/smoketests/smoketests.go rename to e2e/e2etests/e2etests.go index 300ec2e866..ef6e1cbb74 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/smoketests.go +++ b/e2e/e2etests/e2etests.go @@ -1,6 +1,8 @@ -package smoketests +package e2etests -import "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" +import ( + "github.com/zeta-chain/zetacore/e2e/runner" +) // TODO : Add smoke test for abort refund // https://github.com/zeta-chain/node/issues/1745 @@ -39,8 +41,8 @@ const ( TestStressBTCDepositName = "stress_btc_deposit" ) -// AllSmokeTests is an ordered list of all smoke tests -var AllSmokeTests = []runner.SmokeTest{ +// AllE2ETests is an ordered list of all e2e tests +var AllE2ETests = []runner.E2ETest{ { TestContextUpgradeName, "tests sending ETH on ZEVM and check context data using ContextApp", diff --git a/e2e/e2etests/test_bitcoin_deposit.go b/e2e/e2etests/test_bitcoin_deposit.go new file mode 100644 index 0000000000..71e3e87ff9 --- /dev/null +++ b/e2e/e2etests/test_bitcoin_deposit.go @@ -0,0 +1,27 @@ +package e2etests + +import ( + "fmt" + + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestBitcoinDeposit(r *runner.E2ERunner) { + + r.SetBtcAddress(r.Name, false) + + txHash := r.DepositBTCWithAmount(0.001) + + // wait for the cctx to be mined + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "deposit") + if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { + panic(fmt.Sprintf( + "expected mined status; got %s, message: %s", + cctx.CctxStatus.Status.String(), + cctx.CctxStatus.StatusMessage), + ) + } +} diff --git a/e2e/e2etests/test_bitcoin_withdraw.go b/e2e/e2etests/test_bitcoin_withdraw.go new file mode 100644 index 0000000000..f70a4653d2 --- /dev/null +++ b/e2e/e2etests/test_bitcoin_withdraw.go @@ -0,0 +1,228 @@ +package e2etests + +import ( + "fmt" + "math/big" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcutil" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" +) + +func TestBitcoinWithdraw(r *runner.E2ERunner) { + // withdraw 0.1 BTC from ZRC20 to BTC address + // first, approve the ZRC20 contract to spend 1 BTC from the deployer address + WithdrawBitcoin(r) +} + +func WithdrawBitcoin(r *runner.E2ERunner) { + amount := big.NewInt(0.1 * btcutil.SatoshiPerBitcoin) + + // approve the ZRC20 contract to spend 1 BTC from the deployer address + tx, err := r.BTCZRC20.Approve(r.ZevmAuth, r.BTCZRC20Addr, big.NewInt(amount.Int64()*2)) // approve more to cover withdraw fee + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic(fmt.Errorf("approve receipt status is not 1")) + } + + // mine blocks + stop := r.MineBlocks() + + // withdraw 0.1 BTC from ZRC20 to BTC address + tx, err = r.BTCZRC20.Withdraw(r.ZevmAuth, []byte(r.BTCDeployerAddress.EncodeAddress()), amount) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic(fmt.Errorf("withdraw receipt status is not 1")) + } + + // mine 10 blocks to confirm the withdraw tx + _, err = r.BtcRPCClient.GenerateToAddress(10, r.BTCDeployerAddress, nil) + if err != nil { + panic(err) + } + + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + outTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash + hash, err := chainhash.NewHashFromStr(outTxHash) + if err != nil { + panic(err) + } + + rawTx, err := r.BtcRPCClient.GetRawTransactionVerbose(hash) + if err != nil { + panic(err) + } + r.Logger.Info("raw tx:") + r.Logger.Info(" TxIn: %d", len(rawTx.Vin)) + for idx, txIn := range rawTx.Vin { + r.Logger.Info(" TxIn %d:", idx) + r.Logger.Info(" TxID:Vout: %s:%d", txIn.Txid, txIn.Vout) + r.Logger.Info(" ScriptSig: %s", txIn.ScriptSig.Hex) + } + r.Logger.Info(" TxOut: %d", len(rawTx.Vout)) + for _, txOut := range rawTx.Vout { + r.Logger.Info(" TxOut %d:", txOut.N) + r.Logger.Info(" Value: %.8f", txOut.Value) + r.Logger.Info(" ScriptPubKey: %s", txOut.ScriptPubKey.Hex) + } + + // stop mining + stop <- struct{}{} +} + +// WithdrawBitcoinMultipleTimes ... +// TODO: complete and uncomment E2E test +// https://github.com/zeta-chain/node-private/issues/79 +//func WithdrawBitcoinMultipleTimes(r *runner.E2ERunner, repeat int64) { +// totalAmount := big.NewInt(int64(0.1 * 1e8)) +// +// // #nosec G701 test - always in range +// amount := big.NewInt(int64(0.1 * 1e8 / float64(repeat))) +// +// // check if the deposit is successful +// BTCZRC20Addr, err := r.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(common.BtcRegtestChain().ChainId)) +// if err != nil { +// panic(err) +// } +// r.Logger.Info("BTCZRC20Addr: %s", BTCZRC20Addr.Hex()) +// BTCZRC20, err := zrc20.NewZRC20(BTCZRC20Addr, r.ZevmClient) +// if err != nil { +// panic(err) +// } +// balance, err := BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) +// if err != nil { +// panic(err) +// } +// if balance.Cmp(totalAmount) < 0 { +// panic(fmt.Errorf("not enough balance in ZRC20 contract")) +// } +// // approve the ZRC20 contract to spend 1 BTC from the deployer address +// { +// // approve more to cover withdraw fee +// tx, err := BTCZRC20.Approve(r.ZevmAuth, BTCZRC20Addr, totalAmount.Mul(totalAmount, big.NewInt(100))) +// if err != nil { +// panic(err) +// } +// receipt := config.MustWaitForTxReceipt(r.ZevmClient, tx, r.Logger) +// r.Logger.Info("approve receipt: status %d", receipt.Status) +// if receipt.Status != 1 { +// panic(fmt.Errorf("approve receipt status is not 1")) +// } +// } +// go func() { +// for { +// time.Sleep(3 * time.Second) +// _, err = r.BtcRPCClient.GenerateToAddress(1, r.BTCDeployerAddress, nil) +// if err != nil { +// panic(err) +// } +// } +// }() +// // withdraw 0.1 BTC from ZRC20 to BTC address +// for i := int64(0); i < repeat; i++ { +// _, gasFee, err := BTCZRC20.WithdrawGasFee(&bind.CallOpts{}) +// if err != nil { +// panic(err) +// } +// r.Logger.Info("withdraw gas fee: %d", gasFee) +// tx, err := BTCZRC20.Withdraw(r.ZevmAuth, []byte(r.BTCDeployerAddress.EncodeAddress()), amount) +// if err != nil { +// panic(err) +// } +// receipt := config.MustWaitForTxReceipt(r.ZevmClient, tx, r.Logger) +// r.Logger.Info("withdraw receipt: status %d", receipt.Status) +// if receipt.Status != 1 { +// panic(fmt.Errorf("withdraw receipt status is not 1")) +// } +// _, err = r.BtcRPCClient.GenerateToAddress(10, r.BTCDeployerAddress, nil) +// if err != nil { +// panic(err) +// } +// cctx := config.WaitCctxMinedByInTxHash(receipt.TxHash.Hex(), r.CctxClient, r.Logger) +// outTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash +// hash, err := chainhash.NewHashFromStr(outTxHash) +// if err != nil { +// panic(err) +// } +// +// rawTx, err := r.BtcRPCClient.GetRawTransactionVerbose(hash) +// if err != nil { +// panic(err) +// } +// r.Logger.Info("raw tx:") +// r.Logger.Info(" TxIn: %d", len(rawTx.Vin)) +// for idx, txIn := range rawTx.Vin { +// r.Logger.Info(" TxIn %d:", idx) +// r.Logger.Info(" TxID:Vout: %s:%d", txIn.Txid, txIn.Vout) +// r.Logger.Info(" ScriptSig: %s", txIn.ScriptSig.Hex) +// } +// r.Logger.Info(" TxOut: %d", len(rawTx.Vout)) +// for _, txOut := range rawTx.Vout { +// r.Logger.Info(" TxOut %d:", txOut.N) +// r.Logger.Info(" Value: %.8f", txOut.Value) +// r.Logger.Info(" ScriptPubKey: %s", txOut.ScriptPubKey.Hex) +// } +// } +//} + +// DepositBTCRefund ... +// TODO: define e2e test +// https://github.com/zeta-chain/node-private/issues/79 +//func DepositBTCRefund(r *runner.E2ERunner) { +// r.Logger.InfoLoud("Deposit BTC with invalid memo; should be refunded") +// btc := r.BtcRPCClient +// utxos, err := r.BtcRPCClient.ListUnspent() +// if err != nil { +// panic(err) +// } +// spendableAmount := 0.0 +// spendableUTXOs := 0 +// for _, utxo := range utxos { +// if utxo.Spendable { +// spendableAmount += utxo.Amount +// spendableUTXOs++ +// } +// } +// r.Logger.Info("ListUnspent:") +// r.Logger.Info(" spendableAmount: %f", spendableAmount) +// r.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) +// r.Logger.Info("Now sending two txs to TSS address...") +// _, err = r.SendToTSSFromDeployerToDeposit(r.BTCTSSAddress, 1.1, utxos[:2], btc, r.BTCDeployerAddress) +// if err != nil { +// panic(err) +// } +// _, err = r.SendToTSSFromDeployerToDeposit(r.BTCTSSAddress, 0.05, utxos[2:4], btc, r.BTCDeployerAddress) +// if err != nil { +// panic(err) +// } +// +// r.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") +// +// // check if the deposit is successful +// initialBalance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) +// if err != nil { +// panic(err) +// } +// for { +// time.Sleep(3 * time.Second) +// balance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) +// if err != nil { +// panic(err) +// } +// diff := big.NewInt(0) +// diff.Sub(balance, initialBalance) +// if diff.Cmp(big.NewInt(1.15*btcutil.SatoshiPerBitcoin)) != 0 { +// r.Logger.Info("waiting for BTC balance to show up in ZRC contract... current bal %d", balance) +// } else { +// r.Logger.Info("BTC balance is in ZRC contract! Success") +// break +// } +// } +//} diff --git a/e2e/e2etests/test_context.go b/e2e/e2etests/test_context.go new file mode 100644 index 0000000000..aaf7187608 --- /dev/null +++ b/e2e/e2etests/test_context.go @@ -0,0 +1,76 @@ +package e2etests + +import ( + "bytes" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" +) + +// TestContextUpgrade tests sending ETH on ZetaChain and check context data +func TestContextUpgrade(r *runner.E2ERunner) { + value := big.NewInt(1000000000000000) // in wei (1 eth) + data := make([]byte, 0, 32) + data = append(data, r.ContextAppAddr.Bytes()...) + data = append(data, []byte("filler")...) // just to make sure that this is a contract call; + + signedTx, err := r.SendEther(r.TSSAddress, value, data) + if err != nil { + panic(err) + } + + r.Logger.Info("GOERLI tx sent: %s; to %s, nonce %d", signedTx.Hash().String(), signedTx.To().Hex(), signedTx.Nonce()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } + r.Logger.Info("GOERLI tx receipt: %d", receipt.Status) + r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) + r.Logger.Info(" to: %s", signedTx.To().String()) + r.Logger.Info(" value: %d", signedTx.Value()) + r.Logger.Info(" block num: %d", receipt.BlockNumber) + r.Logger.Info(" data: %x", signedTx.Data()) + + found := false + for i := 0; i < 10; i++ { + eventIter, err := r.ContextApp.FilterContextData(&bind.FilterOpts{ + Start: 0, + End: nil, + }) + if err != nil { + r.Logger.Info("filter error: %s", err.Error()) + continue + } + for eventIter.Next() { + r.Logger.Info("event: ContextData") + r.Logger.Info(" origin: %x", eventIter.Event.Origin) + r.Logger.Info(" sender: %s", eventIter.Event.Sender.Hex()) + r.Logger.Info(" chainid: %d", eventIter.Event.ChainID) + r.Logger.Info(" msgsender: %s", eventIter.Event.MsgSender.Hex()) + found = true + if bytes.Compare(eventIter.Event.Origin, r.DeployerAddress.Bytes()) != 0 { + panic("origin mismatch") + } + chainID, err := r.GoerliClient.ChainID(r.Ctx) + if err != nil { + panic(err) + } + if eventIter.Event.ChainID.Cmp(chainID) != 0 { + panic("chainID mismatch") + } + + } + if found { + break + } + time.Sleep(2 * time.Second) + } + + if !found { + panic("event not found") + } + +} diff --git a/e2e/e2etests/test_crosschain_swap.go b/e2e/e2etests/test_crosschain_swap.go new file mode 100644 index 0000000000..5772d185b9 --- /dev/null +++ b/e2e/e2etests/test_crosschain_swap.go @@ -0,0 +1,239 @@ +package e2etests + +import ( + "fmt" + "math/big" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestCrosschainSwap(r *runner.E2ERunner) { + r.ZevmAuth.GasLimit = 10000000 + + // TODO: move into setup and skip it if already initialized + // https://github.com/zeta-chain/node-private/issues/88 + // it is kept as is for now to be consistent with the old implementation + // if the tx fails due to already initialized, it will be ignored + _, err := r.UniswapV2Factory.CreatePair(r.ZevmAuth, r.USDTZRC20Addr, r.BTCZRC20Addr) + if err != nil { + r.Logger.Print("ℹ️create pair error") + } + txUSDTApprove, err := r.USDTZRC20.Approve(r.ZevmAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + txBTCApprove, err := r.BTCZRC20.Approve(r.ZevmAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + + // Fund ZEVMSwapApp with gas ZRC20s + txTransferETH, err := r.ETHZRC20.Transfer(r.ZevmAuth, r.ZEVMSwapAppAddr, big.NewInt(1e7)) + if err != nil { + panic(err) + } + txTransferBTC, err := r.BTCZRC20.Transfer(r.ZevmAuth, r.ZEVMSwapAppAddr, big.NewInt(1e6)) + if err != nil { + panic(err) + } + + if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, txUSDTApprove, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { + panic("usdt approve failed") + } + if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, txBTCApprove, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { + panic("btc approve failed") + } + if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, txTransferETH, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { + panic("ETH ZRC20 transfer failed") + } + if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, txTransferBTC, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { + panic("BTC ZRC20 transfer failed") + } + + // Add 100 USDT liq and 0.001 BTC + txAddLiquidity, err := r.UniswapV2Router.AddLiquidity( + r.ZevmAuth, + r.USDTZRC20Addr, + r.BTCZRC20Addr, + big.NewInt(1e8), + big.NewInt(1e8), + big.NewInt(1e8), + big.NewInt(1e5), + r.DeployerAddress, + big.NewInt(time.Now().Add(10*time.Minute).Unix()), + ) + if err != nil { + panic(fmt.Sprintf("Error liq %s", err.Error())) + } + + if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, txAddLiquidity, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { + panic("add liq receipt status is not 1") + } + + // msg would be [ZEVMSwapAppAddr, memobytes] + // memobytes is dApp specific; see the contracts/ZEVMSwapApp.sol for details + msg := []byte{} + msg = append(msg, r.ZEVMSwapAppAddr.Bytes()...) + memobytes, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.BTCZRC20Addr, []byte(r.BTCDeployerAddress.EncodeAddress())) + + if err != nil { + panic(err) + } + r.Logger.Info("memobytes(%d) %x", len(memobytes), memobytes) + msg = append(msg, memobytes...) + + r.Logger.Info("***** First test: USDT -> BTC") + // Should deposit USDT for swap, swap for BTC and withdraw BTC + txHash := r.DepositERC20WithAmountAndMessage(big.NewInt(8e7), msg) + cctx1 := utils.WaitCctxMinedByInTxHash(r.Ctx, txHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + + // check the cctx status + if cctx1.CctxStatus.Status != types.CctxStatus_OutboundMined { + panic(fmt.Sprintf("expected outbound mined status; got %s, message: %s", cctx1.CctxStatus.Status.String(), cctx1.CctxStatus.StatusMessage)) + } + + // mine 10 blocks to confirm the outbound tx + _, err = r.BtcRPCClient.GenerateToAddress(10, r.BTCDeployerAddress, nil) + if err != nil { + panic(err) + } + stop := r.MineBlocks() + + // cctx1 index acts like the inTxHash for the second cctx (the one that withdraws BTC) + cctx2 := utils.WaitCctxMinedByInTxHash(r.Ctx, cctx1.Index, r.CctxClient, r.Logger, r.CctxTimeout) + + // check the cctx status + if cctx2.CctxStatus.Status != types.CctxStatus_OutboundMined { + panic(fmt.Sprintf( + "expected outbound mined status; got %s, message: %s", + cctx2.CctxStatus.Status.String(), + cctx2.CctxStatus.StatusMessage), + ) + } + + r.Logger.Info("cctx2 outbound tx hash %s", cctx2.GetCurrentOutTxParam().OutboundTxHash) + + r.Logger.Info("******* Second test: BTC -> USDT") + utxos, err := r.BtcRPCClient.ListUnspent() + if err != nil { + panic(err) + } + r.Logger.Info("#utxos %d", len(utxos)) + r.Logger.Info("memo address %s", r.USDTZRC20Addr) + memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.USDTZRC20Addr, r.DeployerAddress.Bytes()) + if err != nil { + panic(err) + } + memo = append(r.ZEVMSwapAppAddr.Bytes(), memo...) + r.Logger.Info("memo length %d", len(memo)) + + txID, err := r.SendToTSSFromDeployerWithMemo( + r.BTCTSSAddress, + 0.01, + utxos[0:2], + r.BtcRPCClient, + memo, + r.BTCDeployerAddress, + ) + if err != nil { + panic(err) + } + r.Logger.Info("Sent BTC to TSS txid %s; now mining 10 blocks for confirmation", txID) + _, err = r.BtcRPCClient.GenerateToAddress(10, r.BTCDeployerAddress, nil) + if err != nil { + panic(err) + } + + cctx3 := utils.WaitCctxMinedByInTxHash(r.Ctx, txID.String(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx3.CctxStatus.Status != types.CctxStatus_OutboundMined { + panic(fmt.Sprintf( + "expected outbound mined status; got %s, message: %s", + cctx3.CctxStatus.Status.String(), + cctx3.CctxStatus.StatusMessage), + ) + } + r.Logger.Info("cctx3 index %s", cctx3.Index) + r.Logger.Info(" inbound tx hash %s", cctx3.InboundTxParams.InboundTxObservedHash) + r.Logger.Info(" status %s", cctx3.CctxStatus.Status.String()) + r.Logger.Info(" status msg: %s", cctx3.CctxStatus.StatusMessage) + + cctx4 := utils.WaitCctxMinedByInTxHash(r.Ctx, cctx3.Index, r.CctxClient, r.Logger, r.CctxTimeout) + if cctx4.CctxStatus.Status != types.CctxStatus_OutboundMined { + panic(fmt.Sprintf( + "expected outbound mined status; got %s, message: %s", + cctx3.CctxStatus.Status.String(), + cctx3.CctxStatus.StatusMessage), + ) + } + r.Logger.Info("cctx4 index %s", cctx4.Index) + r.Logger.Info(" outbound tx hash %s", cctx4.GetCurrentOutTxParam().OutboundTxHash) + r.Logger.Info(" status %s", cctx4.CctxStatus.Status.String()) + + { + r.Logger.Info("******* Third test: BTC -> ETH with contract call reverted; should refund BTC") + utxos, err := r.BtcRPCClient.ListUnspent() + if err != nil { + panic(err) + } + r.Logger.Info("#utxos %d", len(utxos)) + // the following memo will result in a revert in the contract call as targetZRC20 is set to DeployerAddress + // which is apparently not a ZRC20 contract; the UNISWAP call will revert + memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.DeployerAddress, r.DeployerAddress.Bytes()) + if err != nil { + panic(err) + } + memo = append(r.ZEVMSwapAppAddr.Bytes(), memo...) + r.Logger.Info("memo length %d", len(memo)) + + amount := 0.1 + txid, err := r.SendToTSSFromDeployerWithMemo( + r.BTCTSSAddress, + amount, + utxos[0:2], + r.BtcRPCClient, + memo, + r.BTCDeployerAddress, + ) + if err != nil { + panic(err) + } + r.Logger.Info("Sent BTC to TSS txid %s; now mining 10 blocks for confirmation", txid) + _, err = r.BtcRPCClient.GenerateToAddress(10, r.BTCDeployerAddress, nil) + if err != nil { + panic(err) + } + + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, txid.String(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.Info("cctx3 index %s", cctx.Index) + r.Logger.Info(" inbound tx hash %s", cctx.InboundTxParams.InboundTxObservedHash) + r.Logger.Info(" status %s", cctx.CctxStatus.Status.String()) + r.Logger.Info(" status msg: %s", cctx.CctxStatus.StatusMessage) + + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + panic(fmt.Sprintf("expected reverted status; got %s", cctx.CctxStatus.Status.String())) + } + outTxHash, err := chainhash.NewHashFromStr(cctx.GetCurrentOutTxParam().OutboundTxHash) + if err != nil { + panic(err) + } + txraw, err := r.BtcRPCClient.GetRawTransactionVerbose(outTxHash) + if err != nil { + panic(err) + } + r.Logger.Info("out txid %s", txraw.Txid) + for _, vout := range txraw.Vout { + r.Logger.Info(" vout %d", vout.N) + r.Logger.Info(" value %f", vout.Value) + r.Logger.Info(" scriptPubKey %s", vout.ScriptPubKey.Hex) + r.Logger.Info(" p2wpkh address: %s", utils.ScriptPKToAddress(vout.ScriptPubKey.Hex, r.BitcoinParams)) + } + } + + // stop mining + stop <- struct{}{} +} diff --git a/e2e/e2etests/test_donation.go b/e2e/e2etests/test_donation.go new file mode 100644 index 0000000000..730762f760 --- /dev/null +++ b/e2e/e2etests/test_donation.go @@ -0,0 +1,25 @@ +package e2etests + +import ( + "math/big" + + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/zetaclient/evm" +) + +// TestDonationEther tests donation of ether to the tss address +func TestDonationEther(r *runner.E2ERunner) { + txDonation, err := r.SendEther(r.TSSAddress, big.NewInt(100000000000000000), []byte(evm.DonationMessage)) + if err != nil { + panic(err) + } + r.Logger.EVMTransaction(*txDonation, "donation") + + // check contract deployment receipt + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, txDonation, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "donation") + if receipt.Status != 1 { + panic("donation tx failed") + } +} diff --git a/e2e/e2etests/test_erc20_deposit.go b/e2e/e2etests/test_erc20_deposit.go new file mode 100644 index 0000000000..bd91ac72d6 --- /dev/null +++ b/e2e/e2etests/test_erc20_deposit.go @@ -0,0 +1,16 @@ +package e2etests + +import ( + "math/big" + + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" +) + +func TestERC20Deposit(r *runner.E2ERunner) { + hash := r.DepositERC20WithAmountAndMessage(big.NewInt(100000), []byte{}) + + // wait for the cctx to be mined + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, hash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "deposit") +} diff --git a/e2e/e2etests/test_erc20_multiple_deposits.go b/e2e/e2etests/test_erc20_multiple_deposits.go new file mode 100644 index 0000000000..d76481826e --- /dev/null +++ b/e2e/e2etests/test_erc20_multiple_deposits.go @@ -0,0 +1,77 @@ +package e2etests + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + testcontract "github.com/zeta-chain/zetacore/testutil/contracts" +) + +func TestMultipleERC20Deposit(r *runner.E2ERunner) { + initialBal, err := r.USDTZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + txhash := MultipleDeposits(r, big.NewInt(1e9), big.NewInt(3)) + cctxs := utils.WaitCctxsMinedByInTxHash(r.Ctx, txhash.Hex(), r.CctxClient, 3, r.Logger, r.CctxTimeout) + if len(cctxs) != 3 { + panic(fmt.Sprintf("cctxs length is not correct: %d", len(cctxs))) + } + + // check new balance is increased by 1e9 * 3 + bal, err := r.USDTZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + diff := big.NewInt(0).Sub(bal, initialBal) + if diff.Int64() != 3e9 { + panic(fmt.Sprintf("balance difference is not correct: %d", diff.Int64())) + } +} + +func MultipleDeposits(r *runner.E2ERunner, amount, count *big.Int) ethcommon.Hash { + // deploy depositor + depositorAddr, _, depositor, err := testcontract.DeployDepositor(r.GoerliAuth, r.GoerliClient, r.ERC20CustodyAddr) + if err != nil { + panic(err) + } + + fullAmount := big.NewInt(0).Mul(amount, count) + + // approve + tx, err := r.USDTERC20.Approve(r.GoerliAuth, depositorAddr, fullAmount) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve failed") + } + r.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) + + // deposit + tx, err = depositor.RunDeposits(r.GoerliAuth, r.DeployerAddress.Bytes(), r.USDTERC20Addr, amount, []byte{}, count) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposits failed") + } + r.Logger.Info("Deposits receipt tx hash: %s", tx.Hash().Hex()) + + for _, log := range receipt.Logs { + event, err := r.ERC20Custody.ParseDeposited(*log) + if err != nil { + continue + } + r.Logger.Info("Multiple deposit event: ") + r.Logger.Info(" Amount: %d, ", event.Amount) + } + r.Logger.Info("gas limit %d", r.ZevmAuth.GasLimit) + return tx.Hash() +} diff --git a/e2e/e2etests/test_erc20_multiple_withdraws.go b/e2e/e2etests/test_erc20_multiple_withdraws.go new file mode 100644 index 0000000000..37eb5b557f --- /dev/null +++ b/e2e/e2etests/test_erc20_multiple_withdraws.go @@ -0,0 +1,78 @@ +package e2etests + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + testcontract "github.com/zeta-chain/zetacore/testutil/contracts" +) + +func TestMultipleWithdraws(r *runner.E2ERunner) { + // deploy withdrawer + withdrawerAddr, _, withdrawer, err := testcontract.DeployWithdrawer(r.ZevmAuth, r.ZevmClient) + if err != nil { + panic(err) + } + + // approve + tx, err := r.USDTZRC20.Approve(r.ZevmAuth, withdrawerAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve failed") + } + r.Logger.Info("USDT ZRC20 approve receipt: status %d", receipt.Status) + + // approve gas token + tx, err = r.ETHZRC20.Approve(r.ZevmAuth, withdrawerAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve gas token failed") + } + r.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) + + // check the balance + bal, err := r.USDTZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + r.Logger.Info("balance of deployer on USDT ZRC20: %d", bal) + + if bal.Int64() < 1000 { + panic("not enough USDT ZRC20 balance!") + } + + // withdraw + tx, err = withdrawer.RunWithdraws( + r.ZevmAuth, + r.DeployerAddress.Bytes(), + r.USDTZRC20Addr, + big.NewInt(100), + big.NewInt(3), + ) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("withdraw failed") + } + + cctxs := utils.WaitCctxsMinedByInTxHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, 3, r.Logger, r.CctxTimeout) + if len(cctxs) != 3 { + panic(fmt.Sprintf("cctxs length is not correct: %d", len(cctxs))) + } + + // verify the withdraw value + for _, cctx := range cctxs { + verifyTransferAmountFromCCTX(r, cctx, 100) + } +} diff --git a/e2e/e2etests/test_erc20_refund.go b/e2e/e2etests/test_erc20_refund.go new file mode 100644 index 0000000000..252c76162d --- /dev/null +++ b/e2e/e2etests/test_erc20_refund.go @@ -0,0 +1,207 @@ +package e2etests + +import ( + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestERC20DepositAndCallRefund(r *runner.E2ERunner) { + // Get the initial balance of the deployer + initialBal, err := r.USDTZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + + r.Logger.Info("Sending a deposit that should revert without a liquidity pool makes the cctx aborted") + + amount := big.NewInt(1e4) + + // send the deposit + inTxHash, err := sendInvalidUSDTDeposit(r, amount) + if err != nil { + panic(err) + } + + // There is no liquidity pool, therefore the cctx should abort + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, inTxHash, r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "deposit") + if cctx.CctxStatus.Status != types.CctxStatus_Aborted { + panic(fmt.Sprintf("expected cctx status to be Aborted; got %s", cctx.CctxStatus.Status)) + } + + if cctx.CctxStatus.IsAbortRefunded != false { + panic(fmt.Sprintf("expected cctx status to be not refunded; got %t", cctx.CctxStatus.IsAbortRefunded)) + } + + r.Logger.Info("Refunding the cctx via admin") + msg := types.NewMsgRefundAbortedCCTX( + r.ZetaTxServer.GetAccountAddress(0), + cctx.Index, + r.DeployerAddress.String()) + _, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) + if err != nil { + panic(err) + } + + // Check that the erc20 in the aborted cctx was refunded on ZetaChain + newBalance, err := r.USDTZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + expectedBalance := initialBal.Add(initialBal, amount) + if newBalance.Cmp(expectedBalance) != 0 { + panic(fmt.Sprintf("expected balance to be %s after refund; got %s", expectedBalance.String(), newBalance.String())) + } + r.Logger.Info("CCTX has been aborted on ZetaChain") + + // test refund when there is a liquidity pool + r.Logger.Info("Sending a deposit that should revert with a liquidity pool") + + r.Logger.Info("Creating the liquidity pool USTD/ZETA") + err = createZetaERC20LiquidityPool(r) + if err != nil { + panic(err) + } + r.Logger.Info("Liquidity pool created") + + goerliBalance, err := r.USDTERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + + // send the deposit + amount = big.NewInt(1e7) + inTxHash, err = sendInvalidUSDTDeposit(r, amount) + if err != nil { + panic(err) + } + goerliBalanceAfterSend := big.NewInt(0).Sub(goerliBalance, amount) + + // there is a liquidity pool, therefore the cctx should revert + cctx = utils.WaitCctxMinedByInTxHash(r.Ctx, inTxHash, r.CctxClient, r.Logger, r.CctxTimeout) + + // the revert tx creation will fail because the sender, used as the recipient, is not defined in the cctx + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + panic(fmt.Sprintf( + "expected cctx status to be PendingRevert; got %s, aborted message: %s", + cctx.CctxStatus.Status, + cctx.CctxStatus.StatusMessage, + )) + } + + // get revert tx + revertTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash + receipt, err := r.GoerliClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(revertTxHash)) + if err != nil { + panic(err) + } + if receipt.Status == 0 { + panic("expected the revert tx receipt to have status 1; got 0") + } + + // check that the erc20 in the reverted cctx was refunded on Goerli + goerliBalanceAfterRefund, err := r.USDTERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + // the new balance must be higher than the previous one because of the revert refund + if goerliBalanceAfterSend.Cmp(goerliBalanceAfterRefund) != -1 { + panic(fmt.Sprintf( + "expected balance to be higher after refund than after send %s < %s", + goerliBalanceAfterSend.String(), + goerliBalanceAfterRefund.String(), + )) + } + // it must also be lower than the previous balance + the amount because of the gas fee for the revert tx + if goerliBalanceAfterRefund.Cmp(goerliBalance) != -1 { + panic(fmt.Sprintf( + "expected balance to be lower after refund than before send %s < %s", + goerliBalanceAfterRefund.String(), + goerliBalance.String()), + ) + } + + r.Logger.Info("ERC20 CCTX successfully reverted") + r.Logger.Info("\tbalance before refund: %s", goerliBalance.String()) + r.Logger.Info("\tamount: %s", amount.String()) + r.Logger.Info("\tbalance after refund: %s", goerliBalanceAfterRefund.String()) +} + +func createZetaERC20LiquidityPool(r *runner.E2ERunner) error { + amount := big.NewInt(1e10) + txHash := r.DepositERC20WithAmountAndMessage(amount, []byte{}) + utils.WaitCctxMinedByInTxHash(r.Ctx, txHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + + tx, err := r.USDTZRC20.Approve(r.ZevmAuth, r.UniswapV2RouterAddr, big.NewInt(1e10)) + if err != nil { + return err + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + return errors.New("approve failed") + } + + previousValue := r.ZevmAuth.Value + r.ZevmAuth.Value = big.NewInt(1e10) + tx, err = r.UniswapV2Router.AddLiquidityETH( + r.ZevmAuth, + r.USDTZRC20Addr, + amount, + big.NewInt(0), + big.NewInt(0), + r.DeployerAddress, + big.NewInt(time.Now().Add(10*time.Minute).Unix()), + ) + r.ZevmAuth.Value = previousValue + if err != nil { + return err + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + return fmt.Errorf("add liquidity failed") + } + + return nil +} + +func sendInvalidUSDTDeposit(r *runner.E2ERunner, amount *big.Int) (string, error) { + USDT := r.USDTERC20 + tx, err := USDT.Approve(r.GoerliAuth, r.ERC20CustodyAddr, amount) + if err != nil { + return "", err + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) + + tx, err = r.ERC20Custody.Deposit( + r.GoerliAuth, + r.DeployerAddress.Bytes(), + r.USDTERC20Addr, + amount, + []byte("this is an invalid msg that will cause the contract to revert"), + ) + if err != nil { + return "", err + } + + r.Logger.Info("GOERLI tx sent: %s; to %s, nonce %d", tx.Hash().String(), tx.To().Hex(), tx.Nonce()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + return "", errors.New("expected the tx receipt to have status 1; got 0") + } + r.Logger.Info("GOERLI tx receipt: %d", receipt.Status) + r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) + r.Logger.Info(" to: %s", tx.To().String()) + r.Logger.Info(" value: %d", tx.Value()) + r.Logger.Info(" block num: %d", receipt.BlockNumber) + + return tx.Hash().Hex(), nil +} diff --git a/e2e/e2etests/test_erc20_withdraw.go b/e2e/e2etests/test_erc20_withdraw.go new file mode 100644 index 0000000000..9e26130224 --- /dev/null +++ b/e2e/e2etests/test_erc20_withdraw.go @@ -0,0 +1,72 @@ +package e2etests + +import ( + "math/big" + + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestERC20Withdraw(r *runner.E2ERunner) { + // approve + tx, err := r.ETHZRC20.Approve(r.ZevmAuth, r.USDTZRC20Addr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve failed") + } + r.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) + + // withdraw + tx, err = r.USDTZRC20.Withdraw(r.ZevmAuth, r.DeployerAddress.Bytes(), big.NewInt(1000)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status) + for _, log := range receipt.Logs { + event, err := r.USDTZRC20.ParseWithdrawal(*log) + if err != nil { + continue + } + r.Logger.Info( + " logs: from %s, to %x, value %d, gasfee %d", + event.From.Hex(), + event.To, + event.Value, + event.Gasfee, + ) + } + + // verify the withdraw value + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + verifyTransferAmountFromCCTX(r, cctx, 1000) +} + +// verifyTransferAmountFromCCTX verifies the transfer amount from the CCTX on Goerli +func verifyTransferAmountFromCCTX(r *runner.E2ERunner, cctx *crosschaintypes.CrossChainTx, amount int64) { + r.Logger.Info("outTx hash %s", cctx.GetCurrentOutTxParam().OutboundTxHash) + + receipt, err := r.GoerliClient.TransactionReceipt( + r.Ctx, + ethcommon.HexToHash(cctx.GetCurrentOutTxParam().OutboundTxHash), + ) + if err != nil { + panic(err) + } + r.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status) + for _, log := range receipt.Logs { + event, err := r.USDTERC20.ParseTransfer(*log) + if err != nil { + continue + } + r.Logger.Info(" logs: from %s, to %s, value %d", event.From.Hex(), event.To.Hex(), event.Value) + if event.Value.Int64() != amount { + panic("value is not correct") + } + } +} diff --git a/e2e/e2etests/test_eth_deposit.go b/e2e/e2etests/test_eth_deposit.go new file mode 100644 index 0000000000..21a70894b3 --- /dev/null +++ b/e2e/e2etests/test_eth_deposit.go @@ -0,0 +1,331 @@ +package e2etests + +import ( + "fmt" + + "math/big" + "strings" + + "cosmossdk.io/math" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + testcontract "github.com/zeta-chain/zetacore/testutil/contracts" + "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" +) + +// TestEtherDeposit tests deposit of ethers +func TestEtherDeposit(r *runner.E2ERunner) { + hash := r.DepositEtherWithAmount(false, big.NewInt(10000000000000000)) // in wei (0.01 eth) + + // wait for the cctx to be mined + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, hash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "deposit") +} + +// TestEtherDepositAndCall tests deposit of ethers calling a example contract +func TestEtherDepositAndCall(r *runner.E2ERunner) { + r.Logger.Info("Deploying example contract") + exampleAddr, _, exampleContract, err := testcontract.DeployExample(r.ZevmAuth, r.ZevmClient) + if err != nil { + panic(err) + } + r.Logger.Info("Example contract deployed") + + // preparing tx + goerliClient := r.GoerliClient + value := big.NewInt(1e18) + gasLimit := uint64(23000) + gasPrice, err := goerliClient.SuggestGasPrice(r.Ctx) + if err != nil { + panic(err) + } + nonce, err := goerliClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + if err != nil { + panic(err) + } + + data := append(exampleAddr.Bytes(), []byte("hello sailors")...) + tx := ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) + chainID, err := goerliClient.NetworkID(r.Ctx) + if err != nil { + panic(err) + } + deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) + if err != nil { + panic(err) + } + signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) + if err != nil { + panic(err) + } + + r.Logger.Info("Sending a cross-chain call to example contract") + err = goerliClient.SendTransaction(r.Ctx, signedTx) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("tx failed") + } + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { + panic(fmt.Sprintf("expected cctx status to be mined; got %s", cctx.CctxStatus.Status)) + } + + // Checking example contract has been called, bar value should be set to amount + bar, err := exampleContract.Bar(&bind.CallOpts{}) + if err != nil { + panic(err) + } + if bar.Cmp(value) != 0 { + panic(fmt.Sprintf("cross-chain call failed bar value %s should be equal to amount %s", bar.String(), value.String())) + } + r.Logger.Info("Cross-chain call succeeded") + + r.Logger.Info("Deploying reverter contract") + reverterAddr, _, _, err := testcontract.DeployReverter(r.ZevmAuth, r.ZevmClient) + if err != nil { + panic(err) + } + r.Logger.Info("Example reverter deployed") + + // preparing tx for reverter + gasPrice, err = goerliClient.SuggestGasPrice(r.Ctx) + if err != nil { + panic(err) + } + nonce, err = goerliClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + if err != nil { + panic(err) + } + + data = append(reverterAddr.Bytes(), []byte("hello sailors")...) + tx = ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) + signedTx, err = ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) + if err != nil { + panic(err) + } + + r.Logger.Info("Sending a cross-chain call to reverter contract") + err = goerliClient.SendTransaction(r.Ctx, signedTx) + if err != nil { + panic(err) + } + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("tx failed") + } + cctx = utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + panic(fmt.Sprintf("expected cctx status to be reverted; got %s", cctx.CctxStatus.Status)) + } + r.Logger.Info("Cross-chain call to reverter reverted") + + // check the status message contains revert error hash in case of revert + // 0xbfb4ebcf is the hash of "Foo()" + if !strings.Contains(cctx.CctxStatus.StatusMessage, "0xbfb4ebcf") { + panic(fmt.Sprintf("expected cctx status message to contain revert reason; got %s", cctx.CctxStatus.StatusMessage)) + } +} + +func TestDepositAndCallRefund(r *runner.E2ERunner) { + goerliClient := r.GoerliClient + + // in wei (10 eth) + value := big.NewInt(1e18) + value = value.Mul(value, big.NewInt(10)) + + nonce, err := goerliClient.PendingNonceAt(r.Ctx, r.DeployerAddress) + if err != nil { + panic(err) + } + + gasLimit := uint64(23000) // in units + gasPrice, err := goerliClient.SuggestGasPrice(r.Ctx) + if err != nil { + panic(err) + } + + data := append(r.BTCZRC20Addr.Bytes(), []byte("hello sailors")...) // this data + tx := ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) + chainID, err := goerliClient.NetworkID(r.Ctx) + if err != nil { + panic(err) + } + deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) + if err != nil { + panic(err) + } + + signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) + if err != nil { + panic(err) + } + err = goerliClient.SendTransaction(r.Ctx, signedTx) + if err != nil { + panic(err) + } + r.Logger.Info("GOERLI tx sent: %s; to %s, nonce %d", signedTx.Hash().String(), signedTx.To().Hex(), signedTx.Nonce()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("GOERLI tx receipt: %d", receipt.Status) + r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) + r.Logger.Info(" to: %s", signedTx.To().String()) + r.Logger.Info(" value: %d", signedTx.Value()) + r.Logger.Info(" block num: %d", receipt.BlockNumber) + + func() { + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.Info("cctx status message: %s", cctx.CctxStatus.StatusMessage) + revertTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash + r.Logger.Info("GOERLI revert tx receipt: status %d", receipt.Status) + + tx, _, err := r.GoerliClient.TransactionByHash(r.Ctx, ethcommon.HexToHash(revertTxHash)) + if err != nil { + panic(err) + } + receipt, err := r.GoerliClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(revertTxHash)) + if err != nil { + panic(err) + } + + printTxInfo := func() { + // debug info when test fails + r.Logger.Info(" tx: %+v", tx) + r.Logger.Info(" receipt: %+v", receipt) + r.Logger.Info("cctx http://localhost:1317/zeta-chain/crosschain/cctx/%s", cctx.Index) + } + + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + printTxInfo() + panic(fmt.Sprintf("expected cctx status to be PendingRevert; got %s", cctx.CctxStatus.Status)) + } + + if receipt.Status == 0 { + printTxInfo() + panic("expected the revert tx receipt to have status 1; got 0") + } + + if *tx.To() != r.DeployerAddress { + printTxInfo() + panic(fmt.Sprintf("expected tx to %s; got %s", r.DeployerAddress.Hex(), tx.To().Hex())) + } + + // the received value must be lower than the original value because of the paid fees for the revert tx + // we check that the value is still greater than 0 + if tx.Value().Cmp(value) != -1 || tx.Value().Cmp(big.NewInt(0)) != 1 { + printTxInfo() + panic(fmt.Sprintf("expected tx value %s; should be non-null and lower than %s", tx.Value().String(), value.String())) + } + + r.Logger.Info("REVERT tx receipt: %d", receipt.Status) + r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) + r.Logger.Info(" to: %s", tx.To().String()) + r.Logger.Info(" value: %s", tx.Value().String()) + r.Logger.Info(" block num: %d", receipt.BlockNumber) + }() +} + +// TestDepositEtherLiquidityCap tests depositing Ethers in a context where a liquidity cap is set +func TestDepositEtherLiquidityCap(r *runner.E2ERunner) { + supply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) + if err != nil { + panic(err) + } + + // Set a liquidity cap slightly above the current supply + r.Logger.Info("Setting a liquidity cap") + liquidityCap := math.NewUintFromBigInt(supply).Add(math.NewUint(1e16)) + msg := fungibletypes.NewMsgUpdateZRC20LiquidityCap( + r.ZetaTxServer.GetAccountAddress(0), + r.ETHZRC20Addr.Hex(), + liquidityCap, + ) + res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) + if err != nil { + panic(err) + } + r.Logger.Info("set liquidity cap tx hash: %s", res.TxHash) + + r.Logger.Info("Depositing more than liquidity cap should make cctx reverted") + signedTx, err := r.SendEther(r.TSSAddress, big.NewInt(1e17), nil) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) + } + r.Logger.Info("CCTX has been reverted") + + r.Logger.Info("Depositing less than liquidity cap should still succeed") + initialBal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + signedTx, err = r.SendEther(r.TSSAddress, big.NewInt(1e15), nil) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + expectedBalance := big.NewInt(0).Add(initialBal, big.NewInt(1e15)) + + bal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + if bal.Cmp(expectedBalance) != 0 { + panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) + } + r.Logger.Info("Deposit succeeded") + + r.Logger.Info("Removing the liquidity cap") + msg = fungibletypes.NewMsgUpdateZRC20LiquidityCap( + r.ZetaTxServer.GetAccountAddress(0), + r.ETHZRC20Addr.Hex(), + math.ZeroUint(), + ) + res, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) + if err != nil { + panic(err) + } + r.Logger.Info("remove liquidity cap tx hash: %s", res.TxHash) + initialBal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + signedTx, err = r.SendEther(r.TSSAddress, big.NewInt(1e17), nil) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + expectedBalance = big.NewInt(0).Add(initialBal, big.NewInt(1e17)) + + bal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + if bal.Cmp(expectedBalance) != 0 { + panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) + } + r.Logger.Info("New deposit succeeded") +} diff --git a/e2e/e2etests/test_eth_withdraw.go b/e2e/e2etests/test_eth_withdraw.go new file mode 100644 index 0000000000..1f6cd59897 --- /dev/null +++ b/e2e/e2etests/test_eth_withdraw.go @@ -0,0 +1,46 @@ +package e2etests + +import ( + "math/big" + + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +// TestEtherWithdraw tests the withdraw of ether +func TestEtherWithdraw(r *runner.E2ERunner) { + // approve + tx, err := r.ETHZRC20.Approve(r.ZevmAuth, r.ETHZRC20Addr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + r.Logger.EVMTransaction(*tx, "approve") + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve failed") + } + r.Logger.EVMReceipt(*receipt, "approve") + + // withdraw + tx, err = r.ETHZRC20.Withdraw(r.ZevmAuth, r.DeployerAddress.Bytes(), big.NewInt(100000)) + if err != nil { + panic(err) + } + r.Logger.EVMTransaction(*tx, "withdraw") + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("withdraw failed") + } + r.Logger.EVMReceipt(*receipt, "withdraw") + r.Logger.ZRC20Withdrawal(r.ETHZRC20, *receipt, "withdraw") + + // verify the withdraw value + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "withdraw") + if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { + panic("cctx status is not outbound mined") + } +} diff --git a/e2e/e2etests/test_message_passing.go b/e2e/e2etests/test_message_passing.go new file mode 100644 index 0000000000..f02e7a8e4d --- /dev/null +++ b/e2e/e2etests/test_message_passing.go @@ -0,0 +1,233 @@ +package e2etests + +import ( + "fmt" + "math/big" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + ethcommon "github.com/ethereum/go-ethereum/common" + zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" + "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + cctxtypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestMessagePassing(r *runner.E2ERunner) { + chainID, err := r.GoerliClient.ChainID(r.Ctx) + if err != nil { + panic(err) + } + + r.Logger.Info("Approving ConnectorEth to spend deployer's ZetaEth") + amount := big.NewInt(1e18) + amount = amount.Mul(amount, big.NewInt(10)) // 10 Zeta + auth := r.GoerliAuth + tx, err := r.ZetaEth.Approve(auth, r.ConnectorEthAddr, amount) + if err != nil { + panic(err) + } + + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } + r.Logger.Info("Approve tx receipt: %d", receipt.Status) + r.Logger.Info("Calling ConnectorEth.Send") + tx, err = r.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ + DestinationChainId: chainID, + DestinationAddress: r.DeployerAddress.Bytes(), + DestinationGasLimit: big.NewInt(400_000), + Message: nil, + ZetaValueAndGas: amount, + ZetaParams: nil, + }) + if err != nil { + panic(err) + } + + r.Logger.Info("ConnectorEth.Send tx hash: %s", tx.Hash().Hex()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } + r.Logger.Info("ConnectorEth.Send tx receipt: status %d", receipt.Status) + r.Logger.Info(" Logs:") + for _, log := range receipt.Logs { + sentLog, err := r.ConnectorEth.ParseZetaSent(*log) + if err == nil { + r.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) + r.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) + r.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) + r.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) + } + } + + r.Logger.Info("Waiting for ConnectorEth.Send CCTX to be mined...") + r.Logger.Info(" INTX hash: %s", receipt.TxHash.String()) + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { + panic(fmt.Sprintf( + "expected cctx status to be %s; got %s, message %s", + cctxtypes.CctxStatus_OutboundMined, + cctx.CctxStatus.Status.String(), + cctx.CctxStatus.StatusMessage, + )) + } + receipt, err = r.GoerliClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutTxParam().OutboundTxHash)) + if err != nil { + panic(err) + } + if receipt.Status != 1 { + panic("tx failed") + } + for _, log := range receipt.Logs { + event, err := r.ConnectorEth.ParseZetaReceived(*log) + if err == nil { + r.Logger.Info("Received ZetaSent event:") + r.Logger.Info(" Dest Addr: %s", event.DestinationAddress) + r.Logger.Info(" Zeta Value: %d", event.ZetaValue) + r.Logger.Info(" src chainid: %d", event.SourceChainId) + if event.ZetaValue.Cmp(cctx.GetCurrentOutTxParam().Amount.BigInt()) != 0 { + panic("Zeta value mismatch") + } + } + } +} + +func TestMessagePassingRevertFail(r *runner.E2ERunner) { + chainID, err := r.GoerliClient.ChainID(r.Ctx) + if err != nil { + panic(err) + } + + amount := big.NewInt(1e18) + amount = amount.Mul(amount, big.NewInt(10)) // 10 Zeta + auth := r.GoerliAuth + tx, err := r.ZetaEth.Approve(auth, r.ConnectorEthAddr, amount) + if err != nil { + panic(err) + } + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } + r.Logger.Info("Approve tx receipt: %d", receipt.Status) + r.Logger.Info("Calling ConnectorEth.Send") + tx, err = r.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ + DestinationChainId: chainID, + DestinationAddress: r.DeployerAddress.Bytes(), + DestinationGasLimit: big.NewInt(400_000), + Message: []byte("revert"), // non-empty message will cause revert, because the dest address is not a contract + ZetaValueAndGas: amount, + ZetaParams: nil, + }) + if err != nil { + panic(err) + } + r.Logger.Info("ConnectorEth.Send tx hash: %s", tx.Hash().Hex()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } + r.Logger.Info("ConnectorEth.Send tx receipt: status %d", receipt.Status) + r.Logger.Info(" Logs:") + for _, log := range receipt.Logs { + sentLog, err := r.ConnectorEth.ParseZetaSent(*log) + if err == nil { + r.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) + r.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) + r.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) + r.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) + } + } + + // expect revert tx to fail + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) + receipt, err = r.GoerliClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutTxParam().OutboundTxHash)) + if err != nil { + panic(err) + } + // expect revert tx to fail as well + if receipt.Status != 0 { + panic("expected revert tx to fail") + } + if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Aborted { + panic("expected cctx to be aborted") + } +} + +func TestMessagePassingRevertSuccess(r *runner.E2ERunner) { + chainID, err := r.GoerliClient.ChainID(r.Ctx) + if err != nil { + panic(err) + } + + amount := big.NewInt(1e18) + amount = amount.Mul(amount, big.NewInt(10)) // 10 Zeta + auth := r.GoerliAuth + + tx, err := r.ZetaEth.Approve(auth, r.TestDAppAddr, amount) + if err != nil { + panic(err) + } + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } + r.Logger.Info("Approve tx receipt: %d", receipt.Status) + + r.Logger.Info("Calling TestDApp.SendHello on contract address %s", r.TestDAppAddr.Hex()) + testDApp, err := testdapp.NewTestDApp(r.TestDAppAddr, r.GoerliClient) + if err != nil { + panic(err) + } + + res2, err := r.BankClient.SupplyOf(r.Ctx, &banktypes.QuerySupplyOfRequest{ + Denom: "azeta", + }) + if err != nil { + panic(err) + } + r.Logger.Info("$$$ Before: SUPPLY OF AZETA: %d", res2.Amount.Amount) + + tx, err = testDApp.SendHelloWorld(auth, r.TestDAppAddr, chainID, amount, true) + if err != nil { + panic(err) + } + r.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("TestDApp.SendHello tx receipt: status %d", receipt.Status) + + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Reverted { + panic("expected cctx to be reverted") + } + outTxHash := cctx.GetCurrentOutTxParam().OutboundTxHash + receipt, err = r.GoerliClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(outTxHash)) + if err != nil { + panic(err) + } + for _, log := range receipt.Logs { + event, err := r.ConnectorEth.ParseZetaReverted(*log) + if err == nil { + r.Logger.Info("ZetaReverted event: ") + r.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(event.DestinationAddress).Hex()) + r.Logger.Info(" Dest Chain: %d", event.DestinationChainId) + r.Logger.Info(" RemainingZetaValue: %d", event.RemainingZetaValue) + r.Logger.Info(" Message: %x", event.Message) + } + } + res3, err := r.BankClient.SupplyOf(r.Ctx, &banktypes.QuerySupplyOfRequest{ + Denom: "azeta", + }) + if err != nil { + panic(err) + } + r.Logger.Info("$$$ After: SUPPLY OF AZETA: %d", res3.Amount.Amount.BigInt()) + r.Logger.Info("$$$ Diff: SUPPLY OF AZETA: %d", res3.Amount.Amount.Sub(res2.Amount.Amount).BigInt()) +} diff --git a/e2e/e2etests/test_mytest.go b/e2e/e2etests/test_mytest.go new file mode 100644 index 0000000000..bcb7a011dc --- /dev/null +++ b/e2e/e2etests/test_mytest.go @@ -0,0 +1,9 @@ +package e2etests + +import ( + "github.com/zeta-chain/zetacore/e2e/runner" +) + +func TestMyTest(_ *runner.E2ERunner) { + // add your test here +} diff --git a/e2e/e2etests/test_pause_zrc20.go b/e2e/e2etests/test_pause_zrc20.go new file mode 100644 index 0000000000..72a1fb75f1 --- /dev/null +++ b/e2e/e2etests/test_pause_zrc20.go @@ -0,0 +1,185 @@ +package e2etests + +import ( + "fmt" + "math/big" + + "github.com/zeta-chain/zetacore/e2e/contracts/vault" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func TestPauseZRC20(r *runner.E2ERunner) { + // Setup vault used to test zrc20 interactions + r.Logger.Info("Deploying vault") + vaultAddr, _, vaultContract, err := vault.DeployVault(r.ZevmAuth, r.ZevmClient) + if err != nil { + panic(err) + } + // Approving vault to spend ZRC20 + tx, err := r.ETHZRC20.Approve(r.ZevmAuth, vaultAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("Vault approval should succeed") + } + tx, err = r.USDTZRC20.Approve(r.ZevmAuth, vaultAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("Vault approval should succeed") + } + + // Pause ETH ZRC20 + r.Logger.Info("Pausing ETH") + msg := fungibletypes.NewMsgUpdateZRC20PausedStatus( + r.ZetaTxServer.GetAccountAddress(0), + []string{r.ETHZRC20Addr.Hex()}, + fungibletypes.UpdatePausedStatusAction_PAUSE, + ) + res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) + if err != nil { + panic(err) + } + r.Logger.Info("pause zrc20 tx hash: %s", res.TxHash) + + // Fetch and check pause status + fcRes, err := r.FungibleClient.ForeignCoins(r.Ctx, &fungibletypes.QueryGetForeignCoinsRequest{ + Index: r.ETHZRC20Addr.Hex(), + }) + if err != nil { + panic(err) + } + if !fcRes.GetForeignCoins().Paused { + panic("ETH should be paused") + } + r.Logger.Info("ETH is paused") + + // Try operations with ETH ZRC20 + r.Logger.Info("Can no longer do operations on ETH ZRC20") + tx, err = r.ETHZRC20.Transfer(r.ZevmAuth, sample.EthAddress(), big.NewInt(1e5)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 1 { + panic("transfer should fail") + } + tx, err = r.ETHZRC20.Burn(r.ZevmAuth, big.NewInt(1e5)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 1 { + panic("burn should fail") + } + + // Operation on a contract that interact with ETH ZRC20 should fail + r.Logger.Info("Vault contract can no longer interact with ETH ZRC20: %s", r.ETHZRC20Addr.Hex()) + tx, err = vaultContract.Deposit(r.ZevmAuth, r.ETHZRC20Addr, big.NewInt(1e5)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 1 { + panic("deposit should fail") + } + r.Logger.Info("Operations all failed") + + // Check we can still interact with USDT ZRC20 + r.Logger.Info("Check other ZRC20 can still be operated") + tx, err = r.USDTZRC20.Transfer(r.ZevmAuth, sample.EthAddress(), big.NewInt(1e3)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("USDT transfer should succeed") + } + tx, err = vaultContract.Deposit(r.ZevmAuth, r.USDTZRC20Addr, big.NewInt(1e3)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("USDT vault deposit should succeed") + } + + // Check deposit revert when paused + signedTx, err := r.SendEther(r.TSSAddress, big.NewInt(1e17), nil) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.GoerliClient, signedTx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) + } + r.Logger.Info("CCTX has been reverted") + + // Unpause ETH ZRC20 + r.Logger.Info("Unpausing ETH") + msg = fungibletypes.NewMsgUpdateZRC20PausedStatus( + r.ZetaTxServer.GetAccountAddress(0), + []string{r.ETHZRC20Addr.Hex()}, + fungibletypes.UpdatePausedStatusAction_UNPAUSE, + ) + res, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) + if err != nil { + panic(err) + } + r.Logger.Info("unpause zrc20 tx hash: %s", res.TxHash) + + // Fetch and check pause status + fcRes, err = r.FungibleClient.ForeignCoins(r.Ctx, &fungibletypes.QueryGetForeignCoinsRequest{ + Index: r.ETHZRC20Addr.Hex(), + }) + if err != nil { + panic(err) + } + if fcRes.GetForeignCoins().Paused { + panic("ETH should be unpaused") + } + r.Logger.Info("ETH is unpaused") + + // Try operations with ETH ZRC20 + r.Logger.Info("Can do operations on ETH ZRC20 again") + tx, err = r.ETHZRC20.Transfer(r.ZevmAuth, sample.EthAddress(), big.NewInt(1e5)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("transfer should succeed") + } + tx, err = r.ETHZRC20.Burn(r.ZevmAuth, big.NewInt(1e5)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("burn should succeed") + } + + // Can deposit tokens into the vault again + tx, err = vaultContract.Deposit(r.ZevmAuth, r.ETHZRC20Addr, big.NewInt(1e5)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit should succeed") + } + + r.Logger.Info("Operations all succeeded") +} diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_btc_deposit.go b/e2e/e2etests/test_stress_btc_deposit.go similarity index 53% rename from contrib/localnet/orchestrator/smoketest/smoketests/test_stress_btc_deposit.go rename to e2e/e2etests/test_stress_btc_deposit.go index 7c4e3d680c..1fd5a2ea54 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_btc_deposit.go +++ b/e2e/e2etests/test_stress_btc_deposit.go @@ -1,25 +1,24 @@ -package smoketests +package e2etests import ( "fmt" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" "golang.org/x/sync/errgroup" ) // TestStressBTCDeposit tests the stressing deposit of BTC -func TestStressBTCDeposit(sm *runner.SmokeTestRunner) { +func TestStressBTCDeposit(r *runner.E2ERunner) { // number of deposits to perform numDeposits := 100 - sm.SetBtcAddress(sm.Name, false) + r.SetBtcAddress(r.Name, false) - sm.Logger.Print("starting stress test of %d deposits", numDeposits) + r.Logger.Print("starting stress test of %d deposits", numDeposits) // create a wait group to wait for all the deposits to complete var eg errgroup.Group @@ -27,11 +26,11 @@ func TestStressBTCDeposit(sm *runner.SmokeTestRunner) { // send the deposits for i := 0; i < numDeposits; i++ { i := i - txHash := sm.DepositBTCWithAmount(0.001) - sm.Logger.Print("index %d: starting deposit, tx hash: %s", i, txHash.String()) + txHash := r.DepositBTCWithAmount(0.001) + r.Logger.Print("index %d: starting deposit, tx hash: %s", i, txHash.String()) eg.Go(func() error { - return MonitorBTCDeposit(sm, txHash, i, time.Now()) + return MonitorBTCDeposit(r, txHash, i, time.Now()) }) } @@ -40,12 +39,12 @@ func TestStressBTCDeposit(sm *runner.SmokeTestRunner) { panic(err) } - sm.Logger.Print("all deposits completed") + r.Logger.Print("all deposits completed") } // MonitorBTCDeposit monitors the deposit of BTC, returns once the deposit is complete -func MonitorBTCDeposit(sm *runner.SmokeTestRunner, hash *chainhash.Hash, index int, startTime time.Time) error { - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, hash.String(), sm.CctxClient, sm.Logger, sm.ReceiptTimeout) +func MonitorBTCDeposit(r *runner.E2ERunner, hash *chainhash.Hash, index int, startTime time.Time) error { + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, hash.String(), r.CctxClient, r.Logger, r.ReceiptTimeout) if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { return fmt.Errorf( "index %d: deposit cctx failed with status %s, message %s, cctx index %s", @@ -56,7 +55,7 @@ func MonitorBTCDeposit(sm *runner.SmokeTestRunner, hash *chainhash.Hash, index i ) } timeToComplete := time.Now().Sub(startTime) - sm.Logger.Print("index %d: deposit cctx success in %s", index, timeToComplete.String()) + r.Logger.Print("index %d: deposit cctx success in %s", index, timeToComplete.String()) return nil } diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_btc_withdraw.go b/e2e/e2etests/test_stress_btc_withdraw.go similarity index 54% rename from contrib/localnet/orchestrator/smoketest/smoketests/test_stress_btc_withdraw.go rename to e2e/e2etests/test_stress_btc_withdraw.go index 38b692a7e9..eb9219230d 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_btc_withdraw.go +++ b/e2e/e2etests/test_stress_btc_withdraw.go @@ -1,4 +1,4 @@ -package smoketests +package e2etests import ( "fmt" @@ -7,18 +7,18 @@ import ( "github.com/btcsuite/btcutil" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" "golang.org/x/sync/errgroup" ) // TestStressBTCWithdraw tests the stressing withdraw of btc -func TestStressBTCWithdraw(sm *runner.SmokeTestRunner) { +func TestStressBTCWithdraw(r *runner.E2ERunner) { // number of withdraws to perform numWithdraws := 100 - sm.Logger.Print("starting stress test of %d withdraws", numWithdraws) + r.Logger.Print("starting stress test of %d withdraws", numWithdraws) // create a wait group to wait for all the withdraws to complete var eg errgroup.Group @@ -26,23 +26,23 @@ func TestStressBTCWithdraw(sm *runner.SmokeTestRunner) { // send the withdraws for i := 0; i < numWithdraws; i++ { i := i - tx, err := sm.BTCZRC20.Withdraw( - sm.ZevmAuth, - []byte(sm.BTCDeployerAddress.EncodeAddress()), + tx, err := r.BTCZRC20.Withdraw( + r.ZevmAuth, + []byte(r.BTCDeployerAddress.EncodeAddress()), big.NewInt(0.01*btcutil.SatoshiPerBitcoin), ) if err != nil { panic(err) } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status == 0 { - //sm.Logger.Info("index %d: withdraw evm tx failed", index) + //r.Logger.Info("index %d: withdraw evm tx failed", index) panic(fmt.Sprintf("index %d: withdraw btc tx %s failed", i, tx.Hash().Hex())) } - sm.Logger.Print("index %d: starting withdraw, tx hash: %s", i, tx.Hash().Hex()) + r.Logger.Print("index %d: starting withdraw, tx hash: %s", i, tx.Hash().Hex()) eg.Go(func() error { - return MonitorBTCWithdraw(sm, tx, i, time.Now()) + return MonitorBTCWithdraw(r, tx, i, time.Now()) }) } @@ -51,12 +51,12 @@ func TestStressBTCWithdraw(sm *runner.SmokeTestRunner) { panic(err) } - sm.Logger.Print("all withdraws completed") + r.Logger.Print("all withdraws completed") } // MonitorBTCWithdraw monitors the withdraw of BTC, returns once the withdraw is complete -func MonitorBTCWithdraw(sm *runner.SmokeTestRunner, tx *ethtypes.Transaction, index int, startTime time.Time) error { - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, tx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.ReceiptTimeout) +func MonitorBTCWithdraw(r *runner.E2ERunner, tx *ethtypes.Transaction, index int, startTime time.Time) error { + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.ReceiptTimeout) if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { return fmt.Errorf( "index %d: withdraw cctx failed with status %s, message %s, cctx index %s", @@ -67,7 +67,7 @@ func MonitorBTCWithdraw(sm *runner.SmokeTestRunner, tx *ethtypes.Transaction, in ) } timeToComplete := time.Now().Sub(startTime) - sm.Logger.Print("index %d: withdraw cctx success in %s", index, timeToComplete.String()) + r.Logger.Print("index %d: withdraw cctx success in %s", index, timeToComplete.String()) return nil } diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_eth_deposit.go b/e2e/e2etests/test_stress_eth_deposit.go similarity index 53% rename from contrib/localnet/orchestrator/smoketest/smoketests/test_stress_eth_deposit.go rename to e2e/e2etests/test_stress_eth_deposit.go index d12ba4efde..ea5f3919f5 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_eth_deposit.go +++ b/e2e/e2etests/test_stress_eth_deposit.go @@ -1,4 +1,4 @@ -package smoketests +package e2etests import ( "fmt" @@ -6,18 +6,18 @@ import ( "time" ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" "golang.org/x/sync/errgroup" ) // TestStressEtherDeposit tests the stressing deposit of ether -func TestStressEtherDeposit(sm *runner.SmokeTestRunner) { +func TestStressEtherDeposit(r *runner.E2ERunner) { // number of deposits to perform numDeposits := 100 - sm.Logger.Print("starting stress test of %d deposits", numDeposits) + r.Logger.Print("starting stress test of %d deposits", numDeposits) // create a wait group to wait for all the deposits to complete var eg errgroup.Group @@ -25,11 +25,11 @@ func TestStressEtherDeposit(sm *runner.SmokeTestRunner) { // send the deposits for i := 0; i < numDeposits; i++ { i := i - hash := sm.DepositERC20WithAmountAndMessage(big.NewInt(100000), []byte{}) - sm.Logger.Print("index %d: starting deposit, tx hash: %s", i, hash.Hex()) + hash := r.DepositERC20WithAmountAndMessage(big.NewInt(100000), []byte{}) + r.Logger.Print("index %d: starting deposit, tx hash: %s", i, hash.Hex()) eg.Go(func() error { - return MonitorEtherDeposit(sm, hash, i, time.Now()) + return MonitorEtherDeposit(r, hash, i, time.Now()) }) } @@ -38,12 +38,12 @@ func TestStressEtherDeposit(sm *runner.SmokeTestRunner) { panic(err) } - sm.Logger.Print("all deposits completed") + r.Logger.Print("all deposits completed") } // MonitorEtherDeposit monitors the deposit of ether, returns once the deposit is complete -func MonitorEtherDeposit(sm *runner.SmokeTestRunner, hash ethcommon.Hash, index int, startTime time.Time) error { - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, hash.Hex(), sm.CctxClient, sm.Logger, sm.ReceiptTimeout) +func MonitorEtherDeposit(r *runner.E2ERunner, hash ethcommon.Hash, index int, startTime time.Time) error { + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, hash.Hex(), r.CctxClient, r.Logger, r.ReceiptTimeout) if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { return fmt.Errorf( "index %d: deposit cctx failed with status %s, message %s, cctx index %s", @@ -54,7 +54,7 @@ func MonitorEtherDeposit(sm *runner.SmokeTestRunner, hash ethcommon.Hash, index ) } timeToComplete := time.Now().Sub(startTime) - sm.Logger.Print("index %d: deposit cctx success in %s", index, timeToComplete.String()) + r.Logger.Print("index %d: deposit cctx success in %s", index, timeToComplete.String()) return nil } diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_eth_withdraw.go b/e2e/e2etests/test_stress_eth_withdraw.go similarity index 52% rename from contrib/localnet/orchestrator/smoketest/smoketests/test_stress_eth_withdraw.go rename to e2e/e2etests/test_stress_eth_withdraw.go index a8802a0f8f..2e1114d2aa 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_stress_eth_withdraw.go +++ b/e2e/e2etests/test_stress_eth_withdraw.go @@ -1,24 +1,25 @@ -package smoketests +package e2etests import ( "fmt" + "math/big" "time" "golang.org/x/sync/errgroup" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) // TestStressEtherWithdraw tests the stressing withdraw of ether -func TestStressEtherWithdraw(sm *runner.SmokeTestRunner) { +func TestStressEtherWithdraw(r *runner.E2ERunner) { // number of withdraws to perform numWithdraws := 100 - sm.Logger.Print("starting stress test of %d withdraws", numWithdraws) + r.Logger.Print("starting stress test of %d withdraws", numWithdraws) // create a wait group to wait for all the withdraws to complete var eg errgroup.Group @@ -26,19 +27,19 @@ func TestStressEtherWithdraw(sm *runner.SmokeTestRunner) { // send the withdraws for i := 0; i < numWithdraws; i++ { i := i - tx, err := sm.ETHZRC20.Withdraw(sm.ZevmAuth, sm.DeployerAddress.Bytes(), big.NewInt(100000)) + tx, err := r.ETHZRC20.Withdraw(r.ZevmAuth, r.DeployerAddress.Bytes(), big.NewInt(100000)) if err != nil { panic(err) } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status == 0 { - //sm.Logger.Info("index %d: withdraw evm tx failed", index) + //r.Logger.Info("index %d: withdraw evm tx failed", index) panic(fmt.Sprintf("index %d: withdraw evm tx %s failed", i, tx.Hash().Hex())) } - sm.Logger.Print("index %d: starting withdraw, tx hash: %s", i, tx.Hash().Hex()) + r.Logger.Print("index %d: starting withdraw, tx hash: %s", i, tx.Hash().Hex()) eg.Go(func() error { - return MonitorEtherWithdraw(sm, tx, i, time.Now()) + return MonitorEtherWithdraw(r, tx, i, time.Now()) }) } @@ -47,12 +48,12 @@ func TestStressEtherWithdraw(sm *runner.SmokeTestRunner) { panic(err) } - sm.Logger.Print("all withdraws completed") + r.Logger.Print("all withdraws completed") } // MonitorEtherWithdraw monitors the withdraw of ether, returns once the withdraw is complete -func MonitorEtherWithdraw(sm *runner.SmokeTestRunner, tx *ethtypes.Transaction, index int, startTime time.Time) error { - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, tx.Hash().Hex(), sm.CctxClient, sm.Logger, sm.ReceiptTimeout) +func MonitorEtherWithdraw(r *runner.E2ERunner, tx *ethtypes.Transaction, index int, startTime time.Time) error { + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.ReceiptTimeout) if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { return fmt.Errorf( "index %d: withdraw cctx failed with status %s, message %s, cctx index %s", @@ -63,7 +64,7 @@ func MonitorEtherWithdraw(sm *runner.SmokeTestRunner, tx *ethtypes.Transaction, ) } timeToComplete := time.Now().Sub(startTime) - sm.Logger.Print("index %d: withdraw cctx success in %s", index, timeToComplete.String()) + r.Logger.Print("index %d: withdraw cctx success in %s", index, timeToComplete.String()) return nil } diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_update_bytecode.go b/e2e/e2etests/test_update_bytecode.go similarity index 51% rename from contrib/localnet/orchestrator/smoketest/smoketests/test_update_bytecode.go rename to e2e/e2etests/test_update_bytecode.go index 13377309ed..7c64def420 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_update_bytecode.go +++ b/e2e/e2etests/test_update_bytecode.go @@ -1,37 +1,37 @@ -package smoketests +package e2etests import ( "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/testzrc20" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/runner" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" + "github.com/zeta-chain/zetacore/e2e/contracts/testzrc20" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" "github.com/zeta-chain/zetacore/testutil/sample" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" ) // TestUpdateBytecode tests updating the bytecode of a zrc20 and interact with it -func TestUpdateBytecode(sm *runner.SmokeTestRunner) { +func TestUpdateBytecode(r *runner.E2ERunner) { // Random approval approved := sample.EthAddress() - tx, err := sm.ETHZRC20.Approve(sm.ZevmAuth, approved, big.NewInt(1e10)) + tx, err := r.ETHZRC20.Approve(r.ZevmAuth, approved, big.NewInt(1e10)) if err != nil { panic(err) } - receipt := utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status != 1 { panic("approval failed") } // Deploy the TestZRC20 contract - sm.Logger.Info("Deploying contract with new bytecode") + r.Logger.Info("Deploying contract with new bytecode") newZRC20Address, tx, newZRC20Contract, err := testzrc20.DeployTestZRC20( - sm.ZevmAuth, - sm.ZevmClient, + r.ZevmAuth, + r.ZevmClient, big.NewInt(5), - // #nosec G701 smoketest - always in range + // #nosec G701 test - always in range uint8(common.CoinType_Gas), ) if err != nil { @@ -39,96 +39,96 @@ func TestUpdateBytecode(sm *runner.SmokeTestRunner) { } // Wait for the contract to be deployed - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status != 1 { panic("contract deployment failed") } // Get the code hash of the new contract - codeHashRes, err := sm.FungibleClient.CodeHash(sm.Ctx, &fungibletypes.QueryCodeHashRequest{ + codeHashRes, err := r.FungibleClient.CodeHash(r.Ctx, &fungibletypes.QueryCodeHashRequest{ Address: newZRC20Address.String(), }) if err != nil { panic(err) } - sm.Logger.Info("New contract code hash: %s", codeHashRes.CodeHash) + r.Logger.Info("New contract code hash: %s", codeHashRes.CodeHash) // Get current info of the ZRC20 - name, err := sm.ETHZRC20.Name(&bind.CallOpts{}) + name, err := r.ETHZRC20.Name(&bind.CallOpts{}) if err != nil { panic(err) } - symbol, err := sm.ETHZRC20.Symbol(&bind.CallOpts{}) + symbol, err := r.ETHZRC20.Symbol(&bind.CallOpts{}) if err != nil { panic(err) } - decimals, err := sm.ETHZRC20.Decimals(&bind.CallOpts{}) + decimals, err := r.ETHZRC20.Decimals(&bind.CallOpts{}) if err != nil { panic(err) } - totalSupply, err := sm.ETHZRC20.TotalSupply(&bind.CallOpts{}) + totalSupply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { panic(err) } - balance, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + balance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { panic(err) } - approval, err := sm.ETHZRC20.Allowance(&bind.CallOpts{}, sm.DeployerAddress, approved) + approval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.DeployerAddress, approved) if err != nil { panic(err) } - sm.Logger.Info("Updating the bytecode of the ZRC20") + r.Logger.Info("Updating the bytecode of the ZRC20") msg := fungibletypes.NewMsgUpdateContractBytecode( - sm.ZetaTxServer.GetAccountAddress(0), - sm.ETHZRC20Addr.Hex(), + r.ZetaTxServer.GetAccountAddress(0), + r.ETHZRC20Addr.Hex(), codeHashRes.CodeHash, ) - res, err := sm.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) + res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) if err != nil { panic(err) } - sm.Logger.Info("Update zrc20 bytecode tx hash: %s", res.TxHash) + r.Logger.Info("Update zrc20 bytecode tx hash: %s", res.TxHash) // Get new info of the ZRC20 - sm.Logger.Info("Checking the state of the ZRC20 remains the same") - newName, err := sm.ETHZRC20.Name(&bind.CallOpts{}) + r.Logger.Info("Checking the state of the ZRC20 remains the same") + newName, err := r.ETHZRC20.Name(&bind.CallOpts{}) if err != nil { panic(err) } if name != newName { panic("name shouldn't change upon bytecode update") } - newSymbol, err := sm.ETHZRC20.Symbol(&bind.CallOpts{}) + newSymbol, err := r.ETHZRC20.Symbol(&bind.CallOpts{}) if err != nil { panic(err) } if symbol != newSymbol { panic("symbol shouldn't change upon bytecode update") } - newDecimals, err := sm.ETHZRC20.Decimals(&bind.CallOpts{}) + newDecimals, err := r.ETHZRC20.Decimals(&bind.CallOpts{}) if err != nil { panic(err) } if decimals != newDecimals { panic("decimals shouldn't change upon bytecode update") } - newTotalSupply, err := sm.ETHZRC20.TotalSupply(&bind.CallOpts{}) + newTotalSupply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { panic(err) } if totalSupply.Cmp(newTotalSupply) != 0 { panic("total supply shouldn't change upon bytecode update") } - newBalance, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + newBalance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { panic(err) } if balance.Cmp(newBalance) != 0 { panic("balance shouldn't change upon bytecode update") } - newApproval, err := sm.ETHZRC20.Allowance(&bind.CallOpts{}, sm.DeployerAddress, approved) + newApproval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.DeployerAddress, approved) if err != nil { panic(err) } @@ -136,16 +136,16 @@ func TestUpdateBytecode(sm *runner.SmokeTestRunner) { panic("approval shouldn't change upon bytecode update") } - sm.Logger.Info("Can interact with the new code of the contract") - testZRC20Contract, err := testzrc20.NewTestZRC20(sm.ETHZRC20Addr, sm.ZevmClient) + r.Logger.Info("Can interact with the new code of the contract") + testZRC20Contract, err := testzrc20.NewTestZRC20(r.ETHZRC20Addr, r.ZevmClient) if err != nil { panic(err) } - tx, err = testZRC20Contract.UpdateNewField(sm.ZevmAuth, big.NewInt(1e10)) + tx, err = testZRC20Contract.UpdateNewField(r.ZevmAuth, big.NewInt(1e10)) if err != nil { panic(err) } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status != 1 { panic("update new field failed") } @@ -157,12 +157,12 @@ func TestUpdateBytecode(sm *runner.SmokeTestRunner) { panic("new field value mismatch") } - sm.Logger.Info("Interacting with the bytecode contract doesn't disrupt the zrc20 contract") - tx, err = newZRC20Contract.UpdateNewField(sm.ZevmAuth, big.NewInt(1e5)) + r.Logger.Info("Interacting with the bytecode contract doesn't disrupt the zrc20 contract") + tx, err = newZRC20Contract.UpdateNewField(r.ZevmAuth, big.NewInt(1e5)) if err != nil { panic(err) } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status != 1 { panic("update new field failed") } @@ -182,16 +182,16 @@ func TestUpdateBytecode(sm *runner.SmokeTestRunner) { } // can continue to operate the ZRC20 - sm.Logger.Info("Checking the ZRC20 can continue to operate after state change") - tx, err = sm.ETHZRC20.Transfer(sm.ZevmAuth, approved, big.NewInt(1e14)) + r.Logger.Info("Checking the ZRC20 can continue to operate after state change") + tx, err = r.ETHZRC20.Transfer(r.ZevmAuth, approved, big.NewInt(1e14)) if err != nil { panic(err) } - receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) if receipt.Status != 1 { panic("transfer failed") } - newBalance, err = sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, approved) + newBalance, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, approved) if err != nil { panic(err) } diff --git a/e2e/e2etests/test_zeta_deposit.go b/e2e/e2etests/test_zeta_deposit.go new file mode 100644 index 0000000000..ac58399a21 --- /dev/null +++ b/e2e/e2etests/test_zeta_deposit.go @@ -0,0 +1,17 @@ +package e2etests + +import ( + "math/big" + + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" +) + +func TestZetaDeposit(r *runner.E2ERunner) { + // Deposit 1 Zeta + hash := r.DepositZetaWithAmount(big.NewInt(1e18)) + + // wait for the cctx to be mined + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, hash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "deposit") +} diff --git a/e2e/e2etests/test_zeta_withdraw.go b/e2e/e2etests/test_zeta_withdraw.go new file mode 100644 index 0000000000..daa35eab6f --- /dev/null +++ b/e2e/e2etests/test_zeta_withdraw.go @@ -0,0 +1,138 @@ +package e2etests + +import ( + "fmt" + + "math/big" + + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/connectorzevm.sol" + "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" + cctxtypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestZetaWithdraw(r *runner.E2ERunner) { + amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(10)) // 10 Zeta + + r.ZevmAuth.Value = amount + tx, err := r.WZeta.Deposit(r.ZevmAuth) + if err != nil { + panic(err) + } + r.ZevmAuth.Value = big.NewInt(0) + r.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "wzeta deposit") + if receipt.Status == 0 { + panic("deposit failed") + } + + chainID, err := r.GoerliClient.ChainID(r.Ctx) + if err != nil { + panic(err) + } + + tx, err = r.WZeta.Approve(r.ZevmAuth, r.ConnectorZEVMAddr, amount) + if err != nil { + panic(err) + } + r.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "wzeta approve") + if receipt.Status == 0 { + panic(fmt.Sprintf("approve failed, logs: %+v", receipt.Logs)) + } + + tx, err = r.ConnectorZEVM.Send(r.ZevmAuth, connectorzevm.ZetaInterfacesSendInput{ + DestinationChainId: chainID, + DestinationAddress: r.DeployerAddress.Bytes(), + DestinationGasLimit: big.NewInt(400_000), + Message: nil, + ZetaValueAndGas: amount, + ZetaParams: nil, + }) + if err != nil { + panic(err) + } + r.Logger.Info("send tx hash: %s", tx.Hash().Hex()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "send") + if receipt.Status == 0 { + panic(fmt.Sprintf("send failed, logs: %+v", receipt.Logs)) + + } + + r.Logger.Info(" Logs:") + for _, log := range receipt.Logs { + sentLog, err := r.ConnectorZEVM.ParseZetaSent(*log) + if err == nil { + r.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) + r.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) + r.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) + r.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) + } + } + r.Logger.Info("waiting for cctx status to change to final...") + + cctx := utils.WaitCctxMinedByInTxHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "zeta withdraw") + if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { + panic(fmt.Errorf( + "expected cctx status to be %s; got %s, message %s", + cctxtypes.CctxStatus_OutboundMined, + cctx.CctxStatus.Status.String(), + cctx.CctxStatus.StatusMessage, + )) + } +} + +func TestZetaWithdrawBTCRevert(r *runner.E2ERunner) { + r.ZevmAuth.Value = big.NewInt(1e18) // 1 Zeta + tx, err := r.WZeta.Deposit(r.ZevmAuth) + if err != nil { + panic(err) + } + r.ZevmAuth.Value = big.NewInt(0) + r.Logger.Info("Deposit tx hash: %s", tx.Hash().Hex()) + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "Deposit") + if receipt.Status != 1 { + panic("Deposit failed") + } + + tx, err = r.WZeta.Approve(r.ZevmAuth, r.ConnectorZEVMAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + r.Logger.Info("wzeta.approve tx hash: %s", tx.Hash().Hex()) + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "Approve") + if receipt.Status != 1 { + panic("Approve failed") + } + + tx, err = r.ConnectorZEVM.Send(r.ZevmAuth, connectorzevm.ZetaInterfacesSendInput{ + DestinationChainId: big.NewInt(common.BtcRegtestChain().ChainId), + DestinationAddress: r.DeployerAddress.Bytes(), + DestinationGasLimit: big.NewInt(400_000), + Message: nil, + ZetaValueAndGas: big.NewInt(1e17), + ZetaParams: nil, + }) + if err != nil { + panic(err) + } + r.Logger.Info("send tx hash: %s", tx.Hash().Hex()) + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "send") + if receipt.Status != 0 { + panic("Was able to send ZETA to BTC") + } +} diff --git a/e2e/e2etests/test_zrc20_swap.go b/e2e/e2etests/test_zrc20_swap.go new file mode 100644 index 0000000000..d513e2dde0 --- /dev/null +++ b/e2e/e2etests/test_zrc20_swap.go @@ -0,0 +1,96 @@ +package e2etests + +import ( + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/zetacore/e2e/runner" + "github.com/zeta-chain/zetacore/e2e/utils" +) + +func TestZRC20Swap(r *runner.E2ERunner) { + // TODO: move into setup and skip it if already initialized + // https://github.com/zeta-chain/node-private/issues/88 + // it is kept as is for now to be consistent with the old implementation + // if the tx fails due to already initialized, it will be ignored + tx, err := r.UniswapV2Factory.CreatePair(r.ZevmAuth, r.USDTZRC20Addr, r.ETHZRC20Addr) + if err != nil { + r.Logger.Print("ℹ️create pair error") + } else { + utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + } + + usdtEthPair, err := r.UniswapV2Factory.GetPair(&bind.CallOpts{}, r.USDTZRC20Addr, r.ETHZRC20Addr) + if err != nil { + panic(err) + } + r.Logger.Info("USDT-ETH pair receipt pair addr %s", usdtEthPair.Hex()) + + tx, err = r.USDTZRC20.Approve(r.ZevmAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("USDT ZRC20 approval receipt txhash %s status %d", receipt.TxHash, receipt.Status) + + tx, err = r.ETHZRC20.Approve(r.ZevmAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("ETH ZRC20 approval receipt txhash %s status %d", receipt.TxHash, receipt.Status) + + // temporarily increase gas limit to 400000 + previousGasLimit := r.ZevmAuth.GasLimit + defer func() { + r.ZevmAuth.GasLimit = previousGasLimit + }() + + r.ZevmAuth.GasLimit = 400000 + tx, err = r.UniswapV2Router.AddLiquidity( + r.ZevmAuth, + r.USDTZRC20Addr, + r.ETHZRC20Addr, + big.NewInt(90000), + big.NewInt(1000), + big.NewInt(90000), + big.NewInt(1000), + r.DeployerAddress, + big.NewInt(time.Now().Add(10*time.Minute).Unix()), + ) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("Add liquidity receipt txhash %s status %d", receipt.TxHash, receipt.Status) + + balETHBefore, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + ethOutAmout := big.NewInt(1) + tx, err = r.UniswapV2Router.SwapExactTokensForTokens( + r.ZevmAuth, + big.NewInt(1000), + ethOutAmout, + []ethcommon.Address{r.USDTZRC20Addr, r.ETHZRC20Addr}, + r.DeployerAddress, + big.NewInt(time.Now().Add(10*time.Minute).Unix()), + ) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZevmClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("Swap USDT for ETH ZRC20 %s status %d", receipt.TxHash, receipt.Status) + + balETHAfter, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + if err != nil { + panic(err) + } + ethDiff := big.NewInt(0).Sub(balETHAfter, balETHBefore) + if ethDiff.Cmp(ethOutAmout) < 0 { + panic("swap failed") + } +} diff --git a/contrib/localnet/orchestrator/smoketest/runner/accounting.go b/e2e/runner/accounting.go similarity index 51% rename from contrib/localnet/orchestrator/smoketest/runner/accounting.go rename to e2e/runner/accounting.go index 98cad6f2f8..495a881bc6 100644 --- a/contrib/localnet/orchestrator/smoketest/runner/accounting.go +++ b/e2e/runner/accounting.go @@ -19,85 +19,85 @@ type Response struct { Amount Amount `json:"amount"` } -func (sm *SmokeTestRunner) CheckZRC20ReserveAndSupply() error { - sm.Logger.Info("Checking ZRC20 Reserve and Supply") - if err := sm.checkEthTSSBalance(); err != nil { +func (runner *E2ERunner) CheckZRC20ReserveAndSupply() error { + runner.Logger.Info("Checking ZRC20 Reserve and Supply") + if err := runner.checkEthTSSBalance(); err != nil { return err } - if err := sm.checkUsdtTSSBalance(); err != nil { + if err := runner.checkUsdtTSSBalance(); err != nil { return err } - return sm.checkZetaTSSBalance() + return runner.checkZetaTSSBalance() } -func (sm *SmokeTestRunner) checkEthTSSBalance() error { - tssBal, err := sm.GoerliClient.BalanceAt(sm.Ctx, sm.TSSAddress, nil) +func (runner *E2ERunner) checkEthTSSBalance() error { + tssBal, err := runner.GoerliClient.BalanceAt(runner.Ctx, runner.TSSAddress, nil) if err != nil { return err } - zrc20Supply, err := sm.ETHZRC20.TotalSupply(&bind.CallOpts{}) + zrc20Supply, err := runner.ETHZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { return err } if tssBal.Cmp(zrc20Supply) < 0 { return fmt.Errorf("ETH: TSS balance (%d) < ZRC20 TotalSupply (%d) ", tssBal, zrc20Supply) } - sm.Logger.Info("ETH: TSS balance (%d) >= ZRC20 TotalSupply (%d)", tssBal, zrc20Supply) + runner.Logger.Info("ETH: TSS balance (%d) >= ZRC20 TotalSupply (%d)", tssBal, zrc20Supply) return nil } -func (sm *SmokeTestRunner) CheckBtcTSSBalance() error { - utxos, err := sm.BtcRPCClient.ListUnspent() +func (runner *E2ERunner) CheckBtcTSSBalance() error { + utxos, err := runner.BtcRPCClient.ListUnspent() if err != nil { return err } var btcBalance float64 for _, utxo := range utxos { - if utxo.Address == sm.BTCTSSAddress.EncodeAddress() { + if utxo.Address == runner.BTCTSSAddress.EncodeAddress() { btcBalance += utxo.Amount } } - zrc20Supply, err := sm.BTCZRC20.TotalSupply(&bind.CallOpts{}) + zrc20Supply, err := runner.BTCZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { return err } // check the balance in TSS is greater than the total supply on ZetaChain // the amount minted to initialize the pool is subtracted from the total supply - // #nosec G701 smoketest - always in range + // #nosec G701 test - always in range if int64(btcBalance*1e8) < (zrc20Supply.Int64() - 10000000) { - // #nosec G701 smoketest - always in range + // #nosec G701 test - always in range return fmt.Errorf( "BTC: TSS Balance (%d) < ZRC20 TotalSupply (%d)", int64(btcBalance*1e8), zrc20Supply.Int64()-10000000, ) } - // #nosec G701 smoketest - always in range - sm.Logger.Info("BTC: Balance (%d) >= ZRC20 TotalSupply (%d)", int64(btcBalance*1e8), zrc20Supply.Int64()-10000000) + // #nosec G701 test - always in range + runner.Logger.Info("BTC: Balance (%d) >= ZRC20 TotalSupply (%d)", int64(btcBalance*1e8), zrc20Supply.Int64()-10000000) return nil } -func (sm *SmokeTestRunner) checkUsdtTSSBalance() error { - usdtBal, err := sm.USDTERC20.BalanceOf(&bind.CallOpts{}, sm.ERC20CustodyAddr) +func (runner *E2ERunner) checkUsdtTSSBalance() error { + usdtBal, err := runner.USDTERC20.BalanceOf(&bind.CallOpts{}, runner.ERC20CustodyAddr) if err != nil { return err } - zrc20Supply, err := sm.USDTZRC20.TotalSupply(&bind.CallOpts{}) + zrc20Supply, err := runner.USDTZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { return err } if usdtBal.Cmp(zrc20Supply) < 0 { return fmt.Errorf("USDT: TSS balance (%d) < ZRC20 TotalSupply (%d) ", usdtBal, zrc20Supply) } - sm.Logger.Info("USDT: TSS balance (%d) >= ZRC20 TotalSupply (%d)", usdtBal, zrc20Supply) + runner.Logger.Info("USDT: TSS balance (%d) >= ZRC20 TotalSupply (%d)", usdtBal, zrc20Supply) return nil } -func (sm *SmokeTestRunner) checkZetaTSSBalance() error { - zetaLocked, err := sm.ConnectorEth.GetLockedAmount(&bind.CallOpts{}) +func (runner *E2ERunner) checkZetaTSSBalance() error { + zetaLocked, err := runner.ConnectorEth.GetLockedAmount(&bind.CallOpts{}) if err != nil { return err } @@ -117,9 +117,9 @@ func (sm *SmokeTestRunner) checkZetaTSSBalance() error { } zetaSupply, _ := big.NewInt(0).SetString(result.Amount.Amount, 10) if zetaLocked.Cmp(zetaSupply) < 0 { - sm.Logger.Info(fmt.Sprintf("ZETA: TSS balance (%d) < ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply)) + runner.Logger.Info(fmt.Sprintf("ZETA: TSS balance (%d) < ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply)) } else { - sm.Logger.Info("ZETA: TSS balance (%d) >= ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply) + runner.Logger.Info("ZETA: TSS balance (%d) >= ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply) } return nil } diff --git a/contrib/localnet/orchestrator/smoketest/runner/balances.go b/e2e/runner/balances.go similarity index 61% rename from contrib/localnet/orchestrator/smoketest/runner/balances.go rename to e2e/runner/balances.go index eb86122dc1..3147a60eda 100644 --- a/contrib/localnet/orchestrator/smoketest/runner/balances.go +++ b/e2e/runner/balances.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ) -// AccountBalances is a struct that contains the balances of the accounts used in the smoke test +// AccountBalances is a struct that contains the balances of the accounts used in the E2E test type AccountBalances struct { ZetaETH *big.Int ZetaZETA *big.Int @@ -22,47 +22,47 @@ type AccountBalances struct { BtcBTC string } -// AccountBalancesDiff is a struct that contains the difference in the balances of the accounts used in the smoke test +// AccountBalancesDiff is a struct that contains the difference in the balances of the accounts used in the E2E test type AccountBalancesDiff struct { ETH *big.Int ZETA *big.Int ERC20 *big.Int } -// GetAccountBalances returns the account balances of the accounts used in the smoke test -func (sm *SmokeTestRunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) { +// GetAccountBalances returns the account balances of the accounts used in the E2E test +func (runner *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) { // zevm - zetaZeta, err := sm.ZevmClient.BalanceAt(sm.Ctx, sm.DeployerAddress, nil) + zetaZeta, err := runner.ZevmClient.BalanceAt(runner.Ctx, runner.DeployerAddress, nil) if err != nil { return AccountBalances{}, err } - zetaWZeta, err := sm.WZeta.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + zetaWZeta, err := runner.WZeta.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { return AccountBalances{}, err } - zetaEth, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + zetaEth, err := runner.ETHZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { return AccountBalances{}, err } - zetaErc20, err := sm.USDTZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + zetaErc20, err := runner.USDTZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { return AccountBalances{}, err } - zetaBtc, err := sm.BTCZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + zetaBtc, err := runner.BTCZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { return AccountBalances{}, err } // evm - evmEth, err := sm.GoerliClient.BalanceAt(sm.Ctx, sm.DeployerAddress, nil) + evmEth, err := runner.GoerliClient.BalanceAt(runner.Ctx, runner.DeployerAddress, nil) if err != nil { return AccountBalances{}, err } - evmZeta, err := sm.ZetaEth.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + evmZeta, err := runner.ZetaEth.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { return AccountBalances{}, err } - evmErc20, err := sm.USDTERC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + evmErc20, err := runner.USDTERC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { return AccountBalances{}, err } @@ -70,7 +70,7 @@ func (sm *SmokeTestRunner) GetAccountBalances(skipBTC bool) (AccountBalances, er // bitcoin var BtcBTC string if !skipBTC { - if BtcBTC, err = sm.GetBitcoinBalance(); err != nil { + if BtcBTC, err = runner.GetBitcoinBalance(); err != nil { return AccountBalances{}, err } } @@ -89,18 +89,18 @@ func (sm *SmokeTestRunner) GetAccountBalances(skipBTC bool) (AccountBalances, er } // GetBitcoinBalance returns the spendable BTC balance of the BTC address -func (sm *SmokeTestRunner) GetBitcoinBalance() (string, error) { - addr, _, err := sm.GetBtcAddress() +func (runner *E2ERunner) GetBitcoinBalance() (string, error) { + addr, _, err := runner.GetBtcAddress() if err != nil { return "", fmt.Errorf("failed to get BTC address: %w", err) } - address, err := btcutil.DecodeAddress(addr, sm.BitcoinParams) + address, err := btcutil.DecodeAddress(addr, runner.BitcoinParams) if err != nil { return "", fmt.Errorf("failed to decode BTC address: %w", err) } - unspentList, err := sm.BtcRPCClient.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{address}) + unspentList, err := runner.BtcRPCClient.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{address}) if err != nil { return "", fmt.Errorf("failed to list unspent: %w", err) } @@ -116,49 +116,49 @@ func (sm *SmokeTestRunner) GetBitcoinBalance() (string, error) { return totalAmount.String(), nil } -// PrintAccountBalances shows the account balances of the accounts used in the smoke test +// PrintAccountBalances shows the account balances of the accounts used in the E2E test // Note: USDT is mentioned as erc20 here because we want to show the balance of any erc20 contract -func (sm *SmokeTestRunner) PrintAccountBalances(balances AccountBalances) { - sm.Logger.Print(" ---💰 Account info %s ---", sm.DeployerAddress.Hex()) +func (runner *E2ERunner) PrintAccountBalances(balances AccountBalances) { + runner.Logger.Print(" ---💰 Account info %s ---", runner.DeployerAddress.Hex()) // zevm - sm.Logger.Print("ZetaChain:") - sm.Logger.Print("* ZETA balance: %s", balances.ZetaZETA.String()) - sm.Logger.Print("* WZETA balance: %s", balances.ZetaWZETA.String()) - sm.Logger.Print("* ETH balance: %s", balances.ZetaETH.String()) - sm.Logger.Print("* ERC20 balance: %s", balances.ZetaERC20.String()) - sm.Logger.Print("* BTC balance: %s", balances.ZetaBTC.String()) + runner.Logger.Print("ZetaChain:") + runner.Logger.Print("* ZETA balance: %s", balances.ZetaZETA.String()) + runner.Logger.Print("* WZETA balance: %s", balances.ZetaWZETA.String()) + runner.Logger.Print("* ETH balance: %s", balances.ZetaETH.String()) + runner.Logger.Print("* ERC20 balance: %s", balances.ZetaERC20.String()) + runner.Logger.Print("* BTC balance: %s", balances.ZetaBTC.String()) // evm - sm.Logger.Print("EVM:") - sm.Logger.Print("* ZETA balance: %s", balances.EvmZETA.String()) - sm.Logger.Print("* ETH balance: %s", balances.EvmETH.String()) - sm.Logger.Print("* ERC20 balance: %s", balances.EvmERC20.String()) + runner.Logger.Print("EVM:") + runner.Logger.Print("* ZETA balance: %s", balances.EvmZETA.String()) + runner.Logger.Print("* ETH balance: %s", balances.EvmETH.String()) + runner.Logger.Print("* ERC20 balance: %s", balances.EvmERC20.String()) // bitcoin - sm.Logger.Print("Bitcoin:") - sm.Logger.Print("* BTC balance: %s", balances.BtcBTC) + runner.Logger.Print("Bitcoin:") + runner.Logger.Print("* BTC balance: %s", balances.BtcBTC) return } // PrintTotalDiff shows the difference in the account balances of the accounts used in the e2e test from two balances structs -func (sm *SmokeTestRunner) PrintTotalDiff(accoutBalancesDiff AccountBalancesDiff) { - sm.Logger.Print(" ---💰 Total gas spent ---") +func (runner *E2ERunner) PrintTotalDiff(accoutBalancesDiff AccountBalancesDiff) { + runner.Logger.Print(" ---💰 Total gas spent ---") // show the value only if it is not zero if accoutBalancesDiff.ZETA.Cmp(big.NewInt(0)) != 0 { - sm.Logger.Print("* ZETA spent: %s", accoutBalancesDiff.ZETA.String()) + runner.Logger.Print("* ZETA spent: %s", accoutBalancesDiff.ZETA.String()) } if accoutBalancesDiff.ETH.Cmp(big.NewInt(0)) != 0 { - sm.Logger.Print("* ETH spent: %s", accoutBalancesDiff.ETH.String()) + runner.Logger.Print("* ETH spent: %s", accoutBalancesDiff.ETH.String()) } if accoutBalancesDiff.ERC20.Cmp(big.NewInt(0)) != 0 { - sm.Logger.Print("* ERC20 spent: %s", accoutBalancesDiff.ERC20.String()) + runner.Logger.Print("* ERC20 spent: %s", accoutBalancesDiff.ERC20.String()) } } -// GetAccountBalancesDiff returns the difference in the account balances of the accounts used in the smoke test +// GetAccountBalancesDiff returns the difference in the account balances of the accounts used in the E2E test func GetAccountBalancesDiff(balancesBefore, balancesAfter AccountBalances) AccountBalancesDiff { balancesBeforeZeta := big.NewInt(0).Add(balancesBefore.ZetaZETA, balancesBefore.EvmZETA) balancesBeforeEth := big.NewInt(0).Add(balancesBefore.ZetaETH, balancesBefore.EvmETH) diff --git a/contrib/localnet/orchestrator/smoketest/runner/bitcoin.go b/e2e/runner/bitcoin.go similarity index 68% rename from contrib/localnet/orchestrator/smoketest/runner/bitcoin.go rename to e2e/runner/bitcoin.go index 849e4590af..05e4a9befe 100644 --- a/contrib/localnet/orchestrator/smoketest/runner/bitcoin.go +++ b/e2e/runner/bitcoin.go @@ -7,11 +7,6 @@ import ( "math/big" "time" - "github.com/zeta-chain/zetacore/common/bitcoin" - - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/utils" - crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" - "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" @@ -21,6 +16,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rs/zerolog/log" "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/common/bitcoin" + "github.com/zeta-chain/zetacore/e2e/utils" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" zetabitcoin "github.com/zeta-chain/zetacore/zetaclient/bitcoin" ) @@ -28,11 +26,11 @@ import ( var blockHeaderBTCTimeout = 5 * time.Minute // DepositBTCWithAmount deposits BTC on ZetaChain with a specific amount -func (sm *SmokeTestRunner) DepositBTCWithAmount(amount float64) (txHash *chainhash.Hash) { - sm.Logger.Print("⏳ depositing BTC into ZEVM") +func (runner *E2ERunner) DepositBTCWithAmount(amount float64) (txHash *chainhash.Hash) { + runner.Logger.Print("⏳ depositing BTC into ZEVM") // fetch utxos - utxos, err := sm.BtcRPCClient.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{sm.BTCDeployerAddress}) + utxos, err := runner.BtcRPCClient.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{runner.BTCDeployerAddress}) if err != nil { panic(err) } @@ -50,32 +48,32 @@ func (sm *SmokeTestRunner) DepositBTCWithAmount(amount float64) (txHash *chainha panic(fmt.Errorf("not enough spendable BTC to run the test; have %f", spendableAmount)) } - sm.Logger.Info("ListUnspent:") - sm.Logger.Info(" spendableAmount: %f", spendableAmount) - sm.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) - sm.Logger.Info("Now sending two txs to TSS address...") + runner.Logger.Info("ListUnspent:") + runner.Logger.Info(" spendableAmount: %f", spendableAmount) + runner.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) + runner.Logger.Info("Now sending two txs to TSS address...") amount = amount + zetabitcoin.DefaultDepositorFee - txHash, err = sm.SendToTSSFromDeployerToDeposit(sm.BTCTSSAddress, amount, utxos, sm.BtcRPCClient, sm.BTCDeployerAddress) + txHash, err = runner.SendToTSSFromDeployerToDeposit(runner.BTCTSSAddress, amount, utxos, runner.BtcRPCClient, runner.BTCDeployerAddress) if err != nil { panic(err) } - sm.Logger.Info("send BTC to TSS txHash: %s", txHash.String()) + runner.Logger.Info("send BTC to TSS txHash: %s", txHash.String()) return txHash } // DepositBTC deposits BTC on ZetaChain -func (sm *SmokeTestRunner) DepositBTC(testHeader bool) { - sm.Logger.Print("⏳ depositing BTC into ZEVM") +func (runner *E2ERunner) DepositBTC(testHeader bool) { + runner.Logger.Print("⏳ depositing BTC into ZEVM") startTime := time.Now() defer func() { - sm.Logger.Print("✅ BTC deposited in %s", time.Since(startTime)) + runner.Logger.Print("✅ BTC deposited in %s", time.Since(startTime)) }() // fetch utxos - btc := sm.BtcRPCClient - utxos, err := sm.BtcRPCClient.ListUnspent() + btc := runner.BtcRPCClient + utxos, err := runner.BtcRPCClient.ListUnspent() if err != nil { panic(err) } @@ -95,40 +93,40 @@ func (sm *SmokeTestRunner) DepositBTC(testHeader bool) { panic(fmt.Errorf("not enough spendable BTC UTXOs to run the test; have %d", spendableUTXOs)) } - sm.Logger.Info("ListUnspent:") - sm.Logger.Info(" spendableAmount: %f", spendableAmount) - sm.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) - sm.Logger.Info("Now sending two txs to TSS address...") + runner.Logger.Info("ListUnspent:") + runner.Logger.Info(" spendableAmount: %f", spendableAmount) + runner.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) + runner.Logger.Info("Now sending two txs to TSS address...") // send two transactions to the TSS address amount1 := 1.1 + zetabitcoin.DefaultDepositorFee - txHash1, err := sm.SendToTSSFromDeployerToDeposit(sm.BTCTSSAddress, amount1, utxos[:2], btc, sm.BTCDeployerAddress) + txHash1, err := runner.SendToTSSFromDeployerToDeposit(runner.BTCTSSAddress, amount1, utxos[:2], btc, runner.BTCDeployerAddress) if err != nil { panic(err) } amount2 := 0.05 + zetabitcoin.DefaultDepositorFee - txHash2, err := sm.SendToTSSFromDeployerToDeposit(sm.BTCTSSAddress, amount2, utxos[2:4], btc, sm.BTCDeployerAddress) + txHash2, err := runner.SendToTSSFromDeployerToDeposit(runner.BTCTSSAddress, amount2, utxos[2:4], btc, runner.BTCDeployerAddress) if err != nil { panic(err) } // send a donation to the TSS address to compensate for the funds minted automatically during pool creation // and prevent accounting errors - _, err = sm.SendToTSSFromDeployerWithMemo( - sm.BTCTSSAddress, + _, err = runner.SendToTSSFromDeployerWithMemo( + runner.BTCTSSAddress, 0.11, utxos[4:5], btc, []byte(zetabitcoin.DonationMessage), - sm.BTCDeployerAddress, + runner.BTCDeployerAddress, ) if err != nil { panic(err) } - sm.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") + runner.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") - cctx := utils.WaitCctxMinedByInTxHash(sm.Ctx, txHash2.String(), sm.CctxClient, sm.Logger, sm.CctxTimeout) + cctx := utils.WaitCctxMinedByInTxHash(runner.Ctx, txHash2.String(), runner.CctxClient, runner.Logger, runner.CctxTimeout) if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { panic(fmt.Sprintf( "expected mined status; got %s, message: %s", @@ -137,7 +135,7 @@ func (sm *SmokeTestRunner) DepositBTC(testHeader bool) { ) } - balance, err := sm.BTCZRC20.BalanceOf(&bind.CallOpts{}, sm.DeployerAddress) + balance, err := runner.BTCZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) if err != nil { panic(err) } @@ -148,21 +146,21 @@ func (sm *SmokeTestRunner) DepositBTC(testHeader bool) { // due to the high block throughput in localnet, ZetaClient might catch up slowly with the blocks // to optimize block header proof test, this test is directly executed here on the first deposit instead of having a separate test if testHeader { - sm.ProveBTCTransaction(txHash1) + runner.ProveBTCTransaction(txHash1) } } -func (sm *SmokeTestRunner) SendToTSSFromDeployerToDeposit( +func (runner *E2ERunner) SendToTSSFromDeployerToDeposit( to btcutil.Address, amount float64, inputUTXOs []btcjson.ListUnspentResult, btc *rpcclient.Client, btcDeployerAddress *btcutil.AddressWitnessPubKeyHash, ) (*chainhash.Hash, error) { - return sm.SendToTSSFromDeployerWithMemo(to, amount, inputUTXOs, btc, sm.DeployerAddress.Bytes(), btcDeployerAddress) + return runner.SendToTSSFromDeployerWithMemo(to, amount, inputUTXOs, btc, runner.DeployerAddress.Bytes(), btcDeployerAddress) } -func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( +func (runner *E2ERunner) SendToTSSFromDeployerWithMemo( to btcutil.Address, amount float64, inputUTXOs []btcjson.ListUnspentResult, @@ -196,7 +194,7 @@ func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( } // create raw - sm.Logger.Info("ADDRESS: %s, %s", btcDeployerAddress.EncodeAddress(), to.EncodeAddress()) + runner.Logger.Info("ADDRESS: %s, %s", btcDeployerAddress.EncodeAddress(), to.EncodeAddress()) tx, err := btcRPC.CreateRawTransaction(inputs, amountMap, nil) if err != nil { panic(err) @@ -207,7 +205,7 @@ func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( if err != nil { panic(err) } - sm.Logger.Info("nulldata (len %d): %x", len(nullData), nullData) + runner.Logger.Info("nulldata (len %d): %x", len(nullData), nullData) if err != nil { panic(err) } @@ -217,17 +215,17 @@ func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( // make sure that TxOut[0] is sent to "to" address; TxOut[2] is change to oneself. TxOut[1] is memo. if bytes.Compare(tx.TxOut[0].PkScript[2:], to.ScriptAddress()) != 0 { - sm.Logger.Info("tx.TxOut[0].PkScript: %x", tx.TxOut[0].PkScript) - sm.Logger.Info("to.ScriptAddress(): %x", to.ScriptAddress()) - sm.Logger.Info("swapping txout[0] with txout[2]") + runner.Logger.Info("tx.TxOut[0].PkScript: %x", tx.TxOut[0].PkScript) + runner.Logger.Info("to.ScriptAddress(): %x", to.ScriptAddress()) + runner.Logger.Info("swapping txout[0] with txout[2]") tx.TxOut[0], tx.TxOut[2] = tx.TxOut[2], tx.TxOut[0] } - sm.Logger.Info("raw transaction: \n") + runner.Logger.Info("raw transaction: \n") for idx, txout := range tx.TxOut { - sm.Logger.Info("txout %d", idx) - sm.Logger.Info(" value: %d", txout.Value) - sm.Logger.Info(" PkScript: %x", txout.PkScript) + runner.Logger.Info("txout %d", idx) + runner.Logger.Info(" value: %d", txout.Value) + runner.Logger.Info(" PkScript: %x", txout.PkScript) } inputsForSign := make([]btcjson.RawTxWitnessInput, len(inputs)) @@ -251,7 +249,7 @@ func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( if err != nil { panic(err) } - sm.Logger.Info("txid: %+v", txid) + runner.Logger.Info("txid: %+v", txid) _, err = btcRPC.GenerateToAddress(6, btcDeployerAddress, nil) if err != nil { panic(err) @@ -260,7 +258,7 @@ func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( if err != nil { panic(err) } - sm.Logger.Info("rawtx confirmation: %d", gtx.BlockIndex) + runner.Logger.Info("rawtx confirmation: %d", gtx.BlockIndex) rawtx, err := btcRPC.GetRawTransactionVerbose(txid) if err != nil { panic(err) @@ -270,25 +268,25 @@ func (sm *SmokeTestRunner) SendToTSSFromDeployerWithMemo( events := zetabitcoin.FilterAndParseIncomingTx( []btcjson.TxRawResult{*rawtx}, 0, - sm.BTCTSSAddress.EncodeAddress(), + runner.BTCTSSAddress.EncodeAddress(), &log.Logger, - sm.BitcoinParams, + runner.BitcoinParams, depositorFee, ) - sm.Logger.Info("bitcoin intx events:") + runner.Logger.Info("bitcoin intx events:") for _, event := range events { - sm.Logger.Info(" TxHash: %s", event.TxHash) - sm.Logger.Info(" From: %s", event.FromAddress) - sm.Logger.Info(" To: %s", event.ToAddress) - sm.Logger.Info(" Amount: %f", event.Value) - sm.Logger.Info(" Memo: %x", event.MemoBytes) + runner.Logger.Info(" TxHash: %s", event.TxHash) + runner.Logger.Info(" From: %s", event.FromAddress) + runner.Logger.Info(" To: %s", event.ToAddress) + runner.Logger.Info(" Amount: %f", event.Value) + runner.Logger.Info(" Memo: %x", event.MemoBytes) } return txid, nil } // MineBlocks mines blocks on the BTC chain at a rate of 1 blocks every 5 seconds // and returns a channel that can be used to stop the mining -func (sm *SmokeTestRunner) MineBlocks() chan struct{} { +func (runner *E2ERunner) MineBlocks() chan struct{} { stop := make(chan struct{}) go func() { for { @@ -296,7 +294,7 @@ func (sm *SmokeTestRunner) MineBlocks() chan struct{} { case <-stop: return default: - _, err := sm.BtcRPCClient.GenerateToAddress(1, sm.BTCDeployerAddress, nil) + _, err := runner.BtcRPCClient.GenerateToAddress(1, runner.BTCDeployerAddress, nil) if err != nil { panic(err) } @@ -308,9 +306,9 @@ func (sm *SmokeTestRunner) MineBlocks() chan struct{} { } // ProveBTCTransaction proves that a BTC transaction is in a block header and that the block header is in ZetaChain -func (sm *SmokeTestRunner) ProveBTCTransaction(txHash *chainhash.Hash) { +func (runner *E2ERunner) ProveBTCTransaction(txHash *chainhash.Hash) { // get tx result - btc := sm.BtcRPCClient + btc := runner.BtcRPCClient txResult, err := btc.GetTransaction(txHash) if err != nil { panic("should get outTx result") @@ -375,11 +373,11 @@ func (sm *SmokeTestRunner) ProveBTCTransaction(txHash *chainhash.Hash) { panic("timed out waiting for block header to show up in observer") } - _, err := sm.ObserverClient.GetBlockHeaderByHash(sm.Ctx, &observertypes.QueryGetBlockHeaderByHashRequest{ + _, err := runner.ObserverClient.GetBlockHeaderByHash(runner.Ctx, &observertypes.QueryGetBlockHeaderByHashRequest{ BlockHash: hash.CloneBytes(), }) if err != nil { - sm.Logger.Info("waiting for block header to show up in observer... current hash %s; err %s", hash.String(), err.Error()) + runner.Logger.Info("waiting for block header to show up in observer... current hash %s; err %s", hash.String(), err.Error()) } if err == nil { break @@ -388,7 +386,7 @@ func (sm *SmokeTestRunner) ProveBTCTransaction(txHash *chainhash.Hash) { } // verify merkle proof through RPC - res, err := sm.ObserverClient.Prove(sm.Ctx, &observertypes.QueryProveRequest{ + res, err := runner.ObserverClient.Prove(runner.Ctx, &observertypes.QueryProveRequest{ ChainId: common.BtcRegtestChain().ChainId, TxHash: txHash.String(), BlockHash: blockHash.String(), @@ -401,5 +399,5 @@ func (sm *SmokeTestRunner) ProveBTCTransaction(txHash *chainhash.Hash) { if !res.Valid { panic("txProof should be valid") } - sm.Logger.Info("OK: txProof verified for inTx: %s", txHash.String()) + runner.Logger.Info("OK: txProof verified for inTx: %s", txHash.String()) } diff --git a/e2e/runner/evm.go b/e2e/runner/evm.go new file mode 100644 index 0000000000..75eaf75c2b --- /dev/null +++ b/e2e/runner/evm.go @@ -0,0 +1,256 @@ +package runner + +import ( + "math/big" + "time" + + ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/common/ethereum" + "github.com/zeta-chain/zetacore/e2e/utils" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +var blockHeaderETHTimeout = 5 * time.Minute + +// WaitForTxReceiptOnEvm waits for a tx receipt on EVM +func (runner *E2ERunner) WaitForTxReceiptOnEvm(tx *ethtypes.Transaction) { + defer func() { + runner.Unlock() + }() + runner.Lock() + + receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + if receipt.Status != 1 { + panic("tx failed") + } +} + +// MintUSDTOnEvm mints USDT on EVM +// amountUSDT is a multiple of 1e18 +func (runner *E2ERunner) MintUSDTOnEvm(amountUSDT int64) { + defer func() { + runner.Unlock() + }() + runner.Lock() + + amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(amountUSDT)) + + tx, err := runner.USDTERC20.Mint(runner.GoerliAuth, amount) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + if receipt.Status == 0 { + panic("mint failed") + } + runner.Logger.Info("Mint receipt tx hash: %s", tx.Hash().Hex()) +} + +// SendUSDTOnEvm sends USDT to an address on EVM +// this allows the USDT contract deployer to funds other accounts on EVM +// amountUSDT is a multiple of 1e18 +func (runner *E2ERunner) SendUSDTOnEvm(address ethcommon.Address, amountUSDT int64) *ethtypes.Transaction { + // the deployer might be sending USDT in different goroutines + defer func() { + runner.Unlock() + }() + runner.Lock() + + amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(amountUSDT)) + + // transfer + tx, err := runner.USDTERC20.Transfer(runner.GoerliAuth, address, amount) + if err != nil { + panic(err) + } + return tx +} + +func (runner *E2ERunner) DepositERC20() ethcommon.Hash { + runner.Logger.Print("⏳ depositing ERC20 into ZEVM") + + return runner.DepositERC20WithAmountAndMessage(big.NewInt(1e18), []byte{}) +} + +func (runner *E2ERunner) DepositERC20WithAmountAndMessage(amount *big.Int, msg []byte) ethcommon.Hash { + // reset allowance, necessary for USDT + tx, err := runner.USDTERC20.Approve(runner.GoerliAuth, runner.ERC20CustodyAddr, big.NewInt(0)) + if err != nil { + panic(err) + } + receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve failed") + } + runner.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) + + tx, err = runner.USDTERC20.Approve(runner.GoerliAuth, runner.ERC20CustodyAddr, amount) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + if receipt.Status == 0 { + panic("approve failed") + } + runner.Logger.Info("USDT Approve receipt tx hash: %s", tx.Hash().Hex()) + + tx, err = runner.ERC20Custody.Deposit(runner.GoerliAuth, runner.DeployerAddress.Bytes(), runner.USDTERC20Addr, amount, msg) + runner.Logger.Print("TX: %v", tx) + if err != nil { + panic(err) + } + receipt = utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit failed") + } + runner.Logger.Info("Deposit receipt tx hash: %s, status %d", receipt.TxHash.Hex(), receipt.Status) + for _, log := range receipt.Logs { + event, err := runner.ERC20Custody.ParseDeposited(*log) + if err != nil { + continue + } + runner.Logger.Info("Deposited event:") + runner.Logger.Info(" Recipient address: %x", event.Recipient) + runner.Logger.Info(" ERC20 address: %s", event.Asset.Hex()) + runner.Logger.Info(" Amount: %d", event.Amount) + runner.Logger.Info(" Message: %x", event.Message) + } + return tx.Hash() +} + +// DepositEther sends Ethers into ZEVM +func (runner *E2ERunner) DepositEther(testHeader bool) ethcommon.Hash { + return runner.DepositEtherWithAmount(testHeader, big.NewInt(1000000000000000000)) // in wei (1 eth) +} + +// DepositEtherWithAmount sends Ethers into ZEVM +func (runner *E2ERunner) DepositEtherWithAmount(testHeader bool, amount *big.Int) ethcommon.Hash { + runner.Logger.Print("⏳ depositing Ethers into ZEVM") + + signedTx, err := runner.SendEther(runner.TSSAddress, amount, nil) + if err != nil { + panic(err) + } + runner.Logger.EVMTransaction(*signedTx, "send to TSS") + + receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, signedTx, runner.Logger, runner.ReceiptTimeout) + if receipt.Status == 0 { + panic("deposit failed") + } + runner.Logger.EVMReceipt(*receipt, "send to TSS") + + // due to the high block throughput in localnet, ZetaClient might catch up slowly with the blocks + // to optimize block header proof test, this test is directly executed here on the first deposit instead of having a separate test + if testHeader { + runner.ProveEthTransaction(receipt) + } + + return signedTx.Hash() +} + +// SendEther sends ethers to the TSS on Goerli +func (runner *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []byte) (*ethtypes.Transaction, error) { + goerliClient := runner.GoerliClient + + nonce, err := goerliClient.PendingNonceAt(runner.Ctx, runner.DeployerAddress) + if err != nil { + return nil, err + } + + gasLimit := uint64(30000) // in units + gasPrice, err := goerliClient.SuggestGasPrice(runner.Ctx) + if err != nil { + return nil, err + } + + tx := ethtypes.NewTransaction(nonce, runner.TSSAddress, value, gasLimit, gasPrice, data) + chainID, err := goerliClient.NetworkID(runner.Ctx) + if err != nil { + return nil, err + } + + deployerPrivkey, err := crypto.HexToECDSA(runner.DeployerPrivateKey) + if err != nil { + return nil, err + } + + signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) + if err != nil { + return nil, err + } + err = goerliClient.SendTransaction(runner.Ctx, signedTx) + if err != nil { + return nil, err + } + + return signedTx, nil +} + +// ProveEthTransaction proves an ETH transaction on ZetaChain +func (runner *E2ERunner) ProveEthTransaction(receipt *ethtypes.Receipt) { + startTime := time.Now() + + txHash := receipt.TxHash + blockHash := receipt.BlockHash + + // #nosec G701 test - always in range + txIndex := int(receipt.TransactionIndex) + + block, err := runner.GoerliClient.BlockByHash(runner.Ctx, blockHash) + if err != nil { + panic(err) + } + for { + // check timeout + if time.Since(startTime) > blockHeaderETHTimeout { + panic("timeout waiting for block header") + } + + _, err := runner.ObserverClient.GetBlockHeaderByHash(runner.Ctx, &observertypes.QueryGetBlockHeaderByHashRequest{ + BlockHash: blockHash.Bytes(), + }) + if err != nil { + runner.Logger.Info("WARN: block header not found; retrying... error: %s", err.Error()) + } else { + runner.Logger.Info("OK: block header found") + break + } + + time.Sleep(2 * time.Second) + } + + trie := ethereum.NewTrie(block.Transactions()) + if trie.Hash() != block.Header().TxHash { + panic("tx root hash & block tx root mismatch") + } + txProof, err := trie.GenerateProof(txIndex) + if err != nil { + panic("error generating txProof") + } + val, err := txProof.Verify(block.TxHash(), txIndex) + if err != nil { + panic("error verifying txProof") + } + var txx ethtypes.Transaction + err = txx.UnmarshalBinary(val) + if err != nil { + panic("error unmarshalling txProof'd tx") + } + res, err := runner.ObserverClient.Prove(runner.Ctx, &observertypes.QueryProveRequest{ + BlockHash: blockHash.Hex(), + TxIndex: int64(txIndex), + TxHash: txHash.Hex(), + Proof: common.NewEthereumProof(txProof), + ChainId: common.GoerliLocalnetChain().ChainId, + }) + if err != nil { + panic(err) + } + if !res.Valid { + panic("txProof invalid") // FIXME: don't do this in production + } + runner.Logger.Info("OK: txProof verified") +} diff --git a/contrib/localnet/orchestrator/smoketest/runner/logger.go b/e2e/runner/logger.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/runner/logger.go rename to e2e/runner/logger.go diff --git a/contrib/localnet/orchestrator/smoketest/runner/report.go b/e2e/runner/report.go similarity index 84% rename from contrib/localnet/orchestrator/smoketest/runner/report.go rename to e2e/runner/report.go index 1c8428a1a9..a502c442dd 100644 --- a/contrib/localnet/orchestrator/smoketest/runner/report.go +++ b/e2e/runner/report.go @@ -45,11 +45,11 @@ func (tr TestReports) String(prefix string) (string, error) { } // PrintTestReports prints the test reports -func (sm *SmokeTestRunner) PrintTestReports(tr TestReports) { - sm.Logger.Print(" ---📈 E2E Test Report ---") +func (runner *E2ERunner) PrintTestReports(tr TestReports) { + runner.Logger.Print(" ---📈 E2E Test Report ---") table, err := tr.String("") if err != nil { - sm.Logger.Print("Error rendering test report: %s", err) + runner.Logger.Print("Error rendering test report: %s", err) } - sm.Logger.PrintNoPrefix(table) + runner.Logger.PrintNoPrefix(table) } diff --git a/contrib/localnet/orchestrator/smoketest/runner/runner.go b/e2e/runner/runner.go similarity index 52% rename from contrib/localnet/orchestrator/smoketest/runner/runner.go rename to e2e/runner/runner.go index f968e2d9ec..528638b869 100644 --- a/contrib/localnet/orchestrator/smoketest/runner/runner.go +++ b/e2e/runner/runner.go @@ -7,11 +7,12 @@ import ( "sync" "time" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/connectorzevm.sol" - "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/wzeta.sol" + "github.com/zeta-chain/zetacore/e2e/contracts/contextapp" + "github.com/zeta-chain/zetacore/e2e/contracts/erc20" + "github.com/zeta-chain/zetacore/e2e/contracts/zevmswap" + "github.com/zeta-chain/zetacore/e2e/txserver" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -22,23 +23,21 @@ import ( "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol" zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol" zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/connectorzevm.sol" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/wzeta.sol" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-core/contracts/uniswapv2factory.sol" uniswapv2router "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-periphery/contracts/uniswapv2router02.sol" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/contextapp" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/erc20" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/contracts/zevmswap" - "github.com/zeta-chain/zetacore/contrib/localnet/orchestrator/smoketest/txserver" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) -// SmokeTestRunner stores all the clients and addresses needed for smoke test -// Exposes a method to run smoke test +// E2ERunner stores all the clients and addresses needed for E2E test +// Exposes a method to run E2E test // It also provides some helper functions -type SmokeTestRunner struct { +type E2ERunner struct { // accounts DeployerAddress ethcommon.Address DeployerPrivateKey string @@ -112,7 +111,7 @@ type SmokeTestRunner struct { mutex sync.Mutex } -func NewSmokeTestRunner( +func NewE2ERunner( ctx context.Context, name string, ctxCancel context.CancelFunc, @@ -131,8 +130,8 @@ func NewSmokeTestRunner( zevmAuth *bind.TransactOpts, btcRPCClient *rpcclient.Client, logger *Logger, -) *SmokeTestRunner { - return &SmokeTestRunner{ +) *E2ERunner { + return &E2ERunner{ Name: name, Ctx: ctx, CtxCancel: ctxCancel, @@ -160,25 +159,25 @@ func NewSmokeTestRunner( } } -// SmokeTestFunc is a function representing a smoke test -// It takes a SmokeTestRunner as an argument -type SmokeTestFunc func(*SmokeTestRunner) +// E2ETestFunc is a function representing a E2E test +// It takes a E2ERunner as an argument +type E2ETestFunc func(*E2ERunner) -// SmokeTest represents a smoke test with a name -type SmokeTest struct { +// E2ETest represents a E2E test with a name +type E2ETest struct { Name string Description string - SmokeTest SmokeTestFunc + E2ETest E2ETestFunc } -// RunSmokeTestsFromNames runs a list of smoke tests by name in a list of smoke tests -func (sm *SmokeTestRunner) RunSmokeTestsFromNames(smokeTests []SmokeTest, smokeTestNames ...string) error { - for _, smokeTestName := range smokeTestNames { - smokeTest, ok := findSmokeTest(smokeTestName, smokeTests) +// RunE2ETestsFromNames runs a list of E2E tests by name in a list of e2e tests +func (runner *E2ERunner) RunE2ETestsFromNames(e2eTests []E2ETest, e2eTestNames ...string) error { + for _, e2eTestName := range e2eTestNames { + e2eTest, ok := findE2ETest(e2eTestName, e2eTests) if !ok { - return fmt.Errorf("smoke test %s not found", smokeTestName) + return fmt.Errorf("e2e test %s not found", e2eTestName) } - if err := sm.RunSmokeTest(smokeTest, true); err != nil { + if err := runner.RunE2ETest(e2eTest, true); err != nil { return err } } @@ -186,40 +185,40 @@ func (sm *SmokeTestRunner) RunSmokeTestsFromNames(smokeTests []SmokeTest, smokeT return nil } -// RunSmokeTestsFromNamesIntoReport runs a list of smoke tests by name in a list of smoke tests and returns a report +// RunE2ETestsFromNamesIntoReport runs a list of e2e tests by name in a list of e2e tests and returns a report // The function doesn't return an error, it returns a report with the error -func (sm *SmokeTestRunner) RunSmokeTestsFromNamesIntoReport(smokeTests []SmokeTest, smokeTestNames ...string) (TestReports, error) { +func (runner *E2ERunner) RunE2ETestsFromNamesIntoReport(e2eTests []E2ETest, e2eTestNames ...string) (TestReports, error) { // get all tests so we can return an error if a test is not found - tests := make([]SmokeTest, 0, len(smokeTestNames)) - for _, smokeTestName := range smokeTestNames { - smokeTest, ok := findSmokeTest(smokeTestName, smokeTests) + tests := make([]E2ETest, 0, len(e2eTestNames)) + for _, e2eTestName := range e2eTestNames { + e2eTest, ok := findE2ETest(e2eTestName, e2eTests) if !ok { - return nil, fmt.Errorf("smoke test %s not found", smokeTestName) + return nil, fmt.Errorf("e2e test %s not found", e2eTestName) } - tests = append(tests, smokeTest) + tests = append(tests, e2eTest) } // go through all tests - reports := make(TestReports, 0, len(smokeTestNames)) + reports := make(TestReports, 0, len(e2eTestNames)) for _, test := range tests { // get info before test - balancesBefore, err := sm.GetAccountBalances(true) + balancesBefore, err := runner.GetAccountBalances(true) if err != nil { return nil, err } timeBefore := time.Now() // run test - testErr := sm.RunSmokeTest(test, false) + testErr := runner.RunE2ETest(test, false) if testErr != nil { - sm.Logger.Print("test %s failed: %s", test.Name, testErr.Error()) + runner.Logger.Print("test %s failed: %s", test.Name, testErr.Error()) } // wait 5 sec to make sure we get updated balances time.Sleep(5 * time.Second) // get info after test - balancesAfter, err := sm.GetAccountBalances(true) + balancesAfter, err := runner.GetAccountBalances(true) if err != nil { return nil, err } @@ -238,18 +237,18 @@ func (sm *SmokeTestRunner) RunSmokeTestsFromNamesIntoReport(smokeTests []SmokeTe return reports, nil } -// RunSmokeTests runs a list of smoke tests -func (sm *SmokeTestRunner) RunSmokeTests(smokeTests []SmokeTest) (err error) { - for _, smokeTest := range smokeTests { - if err := sm.RunSmokeTest(smokeTest, true); err != nil { +// RunE2ETests runs a list of e2e tests +func (runner *E2ERunner) RunE2ETests(e2eTests []E2ETest) (err error) { + for _, e2eTest := range e2eTests { + if err := runner.RunE2ETest(e2eTest, true); err != nil { return err } } return nil } -// RunSmokeTest runs a smoke test -func (sm *SmokeTestRunner) RunSmokeTest(smokeTestWithName SmokeTest, checkAccounting bool) (err error) { +// RunE2ETest runs a e2e test +func (runner *E2ERunner) RunE2ETest(e2eTestWithName E2ETest, checkAccounting bool) (err error) { // return an error on panic // https://github.com/zeta-chain/node/issues/1500 defer func() { @@ -257,116 +256,116 @@ func (sm *SmokeTestRunner) RunSmokeTest(smokeTestWithName SmokeTest, checkAccoun // print stack trace stack := make([]byte, 4096) n := runtime.Stack(stack, false) - err = fmt.Errorf("%s failed: %v, stack trace %s", smokeTestWithName.Name, r, stack[:n]) + err = fmt.Errorf("%s failed: %v, stack trace %s", e2eTestWithName.Name, r, stack[:n]) } }() startTime := time.Now() - sm.Logger.Print("⏳running - %s", smokeTestWithName.Description) + runner.Logger.Print("⏳running - %s", e2eTestWithName.Description) - // run smoke test - smokeTestWithName.SmokeTest(sm) + // run e2e test + e2eTestWithName.E2ETest(runner) //check supplies if checkAccounting { - if err := sm.CheckZRC20ReserveAndSupply(); err != nil { + if err := runner.CheckZRC20ReserveAndSupply(); err != nil { return err } } - sm.Logger.Print("✅ completed in %s - %s", time.Since(startTime), smokeTestWithName.Description) + runner.Logger.Print("✅ completed in %s - %s", time.Since(startTime), e2eTestWithName.Description) return err } -// findSmokeTest finds a smoke test by name -func findSmokeTest(name string, smokeTests []SmokeTest) (SmokeTest, bool) { - for _, test := range smokeTests { +// findE2ETest finds a e2e test by name +func findE2ETest(name string, e2eTests []E2ETest) (E2ETest, bool) { + for _, test := range e2eTests { if test.Name == name { return test, true } } - return SmokeTest{}, false + return E2ETest{}, false } -// CopyAddressesFrom copies addresses from another SmokeTestRunner that initialized the contracts -func (sm *SmokeTestRunner) CopyAddressesFrom(other *SmokeTestRunner) (err error) { +// CopyAddressesFrom copies addresses from another E2ETestRunner that initialized the contracts +func (runner *E2ERunner) CopyAddressesFrom(other *E2ERunner) (err error) { // copy TSS address - sm.TSSAddress = other.TSSAddress - sm.BTCTSSAddress = other.BTCTSSAddress + runner.TSSAddress = other.TSSAddress + runner.BTCTSSAddress = other.BTCTSSAddress // copy addresses - sm.ZetaEthAddr = other.ZetaEthAddr - sm.ConnectorEthAddr = other.ConnectorEthAddr - sm.ERC20CustodyAddr = other.ERC20CustodyAddr - sm.USDTERC20Addr = other.USDTERC20Addr - sm.USDTZRC20Addr = other.USDTZRC20Addr - sm.ETHZRC20Addr = other.ETHZRC20Addr - sm.BTCZRC20Addr = other.BTCZRC20Addr - sm.UniswapV2FactoryAddr = other.UniswapV2FactoryAddr - sm.UniswapV2RouterAddr = other.UniswapV2RouterAddr - sm.ConnectorZEVMAddr = other.ConnectorZEVMAddr - sm.WZetaAddr = other.WZetaAddr - sm.TestDAppAddr = other.TestDAppAddr - sm.ZEVMSwapAppAddr = other.ZEVMSwapAppAddr - sm.ContextAppAddr = other.ContextAppAddr - sm.SystemContractAddr = other.SystemContractAddr + runner.ZetaEthAddr = other.ZetaEthAddr + runner.ConnectorEthAddr = other.ConnectorEthAddr + runner.ERC20CustodyAddr = other.ERC20CustodyAddr + runner.USDTERC20Addr = other.USDTERC20Addr + runner.USDTZRC20Addr = other.USDTZRC20Addr + runner.ETHZRC20Addr = other.ETHZRC20Addr + runner.BTCZRC20Addr = other.BTCZRC20Addr + runner.UniswapV2FactoryAddr = other.UniswapV2FactoryAddr + runner.UniswapV2RouterAddr = other.UniswapV2RouterAddr + runner.ConnectorZEVMAddr = other.ConnectorZEVMAddr + runner.WZetaAddr = other.WZetaAddr + runner.TestDAppAddr = other.TestDAppAddr + runner.ZEVMSwapAppAddr = other.ZEVMSwapAppAddr + runner.ContextAppAddr = other.ContextAppAddr + runner.SystemContractAddr = other.SystemContractAddr // create instances of contracts - sm.ZetaEth, err = zetaeth.NewZetaEth(sm.ZetaEthAddr, sm.GoerliClient) + runner.ZetaEth, err = zetaeth.NewZetaEth(runner.ZetaEthAddr, runner.GoerliClient) if err != nil { return err } - sm.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(sm.ConnectorEthAddr, sm.GoerliClient) + runner.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(runner.ConnectorEthAddr, runner.GoerliClient) if err != nil { return err } - sm.ERC20Custody, err = erc20custody.NewERC20Custody(sm.ERC20CustodyAddr, sm.GoerliClient) + runner.ERC20Custody, err = erc20custody.NewERC20Custody(runner.ERC20CustodyAddr, runner.GoerliClient) if err != nil { return err } - sm.USDTERC20, err = erc20.NewUSDT(sm.USDTERC20Addr, sm.GoerliClient) + runner.USDTERC20, err = erc20.NewUSDT(runner.USDTERC20Addr, runner.GoerliClient) if err != nil { return err } - sm.USDTZRC20, err = zrc20.NewZRC20(sm.USDTZRC20Addr, sm.ZevmClient) + runner.USDTZRC20, err = zrc20.NewZRC20(runner.USDTZRC20Addr, runner.ZevmClient) if err != nil { return err } - sm.ETHZRC20, err = zrc20.NewZRC20(sm.ETHZRC20Addr, sm.ZevmClient) + runner.ETHZRC20, err = zrc20.NewZRC20(runner.ETHZRC20Addr, runner.ZevmClient) if err != nil { return err } - sm.BTCZRC20, err = zrc20.NewZRC20(sm.BTCZRC20Addr, sm.ZevmClient) + runner.BTCZRC20, err = zrc20.NewZRC20(runner.BTCZRC20Addr, runner.ZevmClient) if err != nil { return err } - sm.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(sm.UniswapV2FactoryAddr, sm.ZevmClient) + runner.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(runner.UniswapV2FactoryAddr, runner.ZevmClient) if err != nil { return err } - sm.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(sm.UniswapV2RouterAddr, sm.ZevmClient) + runner.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(runner.UniswapV2RouterAddr, runner.ZevmClient) if err != nil { return err } - sm.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(sm.ConnectorZEVMAddr, sm.ZevmClient) + runner.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(runner.ConnectorZEVMAddr, runner.ZevmClient) if err != nil { return err } - sm.WZeta, err = wzeta.NewWETH9(sm.WZetaAddr, sm.ZevmClient) + runner.WZeta, err = wzeta.NewWETH9(runner.WZetaAddr, runner.ZevmClient) if err != nil { return err } - sm.ZEVMSwapApp, err = zevmswap.NewZEVMSwapApp(sm.ZEVMSwapAppAddr, sm.ZevmClient) + runner.ZEVMSwapApp, err = zevmswap.NewZEVMSwapApp(runner.ZEVMSwapAppAddr, runner.ZevmClient) if err != nil { return err } - sm.ContextApp, err = contextapp.NewContextApp(sm.ContextAppAddr, sm.ZevmClient) + runner.ContextApp, err = contextapp.NewContextApp(runner.ContextAppAddr, runner.ZevmClient) if err != nil { return err } - sm.SystemContract, err = systemcontract.NewSystemContract(sm.SystemContractAddr, sm.ZevmClient) + runner.SystemContract, err = systemcontract.NewSystemContract(runner.SystemContractAddr, runner.ZevmClient) if err != nil { return err } @@ -374,38 +373,38 @@ func (sm *SmokeTestRunner) CopyAddressesFrom(other *SmokeTestRunner) (err error) } // Lock locks the mutex -func (sm *SmokeTestRunner) Lock() { - sm.mutex.Lock() +func (runner *E2ERunner) Lock() { + runner.mutex.Lock() } // Unlock unlocks the mutex -func (sm *SmokeTestRunner) Unlock() { - sm.mutex.Unlock() +func (runner *E2ERunner) Unlock() { + runner.mutex.Unlock() } // PrintContractAddresses prints the addresses of the contracts // the printed contracts are grouped in a zevm and evm section // there is a padding used to print the addresses at the same position -func (sm *SmokeTestRunner) PrintContractAddresses() { +func (runner *E2ERunner) PrintContractAddresses() { // zevm contracts - sm.Logger.Print(" --- 📜zEVM contracts ---") - sm.Logger.Print("SystemContract: %s", sm.SystemContractAddr.Hex()) - sm.Logger.Print("ETHZRC20: %s", sm.ETHZRC20Addr.Hex()) - sm.Logger.Print("USDTZRC20: %s", sm.USDTZRC20Addr.Hex()) - sm.Logger.Print("BTCZRC20: %s", sm.BTCZRC20Addr.Hex()) - sm.Logger.Print("UniswapFactory: %s", sm.UniswapV2FactoryAddr.Hex()) - sm.Logger.Print("UniswapRouter: %s", sm.UniswapV2RouterAddr.Hex()) - sm.Logger.Print("ConnectorZEVM: %s", sm.ConnectorZEVMAddr.Hex()) - sm.Logger.Print("WZeta: %s", sm.WZetaAddr.Hex()) - - sm.Logger.Print("ZEVMSwapApp: %s", sm.ZEVMSwapAppAddr.Hex()) - sm.Logger.Print("ContextApp: %s", sm.ContextAppAddr.Hex()) - sm.Logger.Print("TestDapp: %s", sm.TestDAppAddr.Hex()) + runner.Logger.Print(" --- 📜zEVM contracts ---") + runner.Logger.Print("SystemContract: %s", runner.SystemContractAddr.Hex()) + runner.Logger.Print("ETHZRC20: %s", runner.ETHZRC20Addr.Hex()) + runner.Logger.Print("USDTZRC20: %s", runner.USDTZRC20Addr.Hex()) + runner.Logger.Print("BTCZRC20: %s", runner.BTCZRC20Addr.Hex()) + runner.Logger.Print("UniswapFactory: %s", runner.UniswapV2FactoryAddr.Hex()) + runner.Logger.Print("UniswapRouter: %s", runner.UniswapV2RouterAddr.Hex()) + runner.Logger.Print("ConnectorZEVM: %s", runner.ConnectorZEVMAddr.Hex()) + runner.Logger.Print("WZeta: %s", runner.WZetaAddr.Hex()) + + runner.Logger.Print("ZEVMSwapApp: %s", runner.ZEVMSwapAppAddr.Hex()) + runner.Logger.Print("ContextApp: %s", runner.ContextAppAddr.Hex()) + runner.Logger.Print("TestDapp: %s", runner.TestDAppAddr.Hex()) // evm contracts - sm.Logger.Print(" --- 📜EVM contracts ---") - sm.Logger.Print("ZetaEth: %s", sm.ZetaEthAddr.Hex()) - sm.Logger.Print("ConnectorEth: %s", sm.ConnectorEthAddr.Hex()) - sm.Logger.Print("ERC20Custody: %s", sm.ERC20CustodyAddr.Hex()) - sm.Logger.Print("USDTERC20: %s", sm.USDTERC20Addr.Hex()) + runner.Logger.Print(" --- 📜EVM contracts ---") + runner.Logger.Print("ZetaEth: %s", runner.ZetaEthAddr.Hex()) + runner.Logger.Print("ConnectorEth: %s", runner.ConnectorEthAddr.Hex()) + runner.Logger.Print("ERC20Custody: %s", runner.ERC20CustodyAddr.Hex()) + runner.Logger.Print("USDTERC20: %s", runner.USDTERC20Addr.Hex()) } diff --git a/contrib/localnet/orchestrator/smoketest/runner/setup_bitcoin.go b/e2e/runner/setup_bitcoin.go similarity index 52% rename from contrib/localnet/orchestrator/smoketest/runner/setup_bitcoin.go rename to e2e/runner/setup_bitcoin.go index 52dfc2549c..5872fc4101 100644 --- a/contrib/localnet/orchestrator/smoketest/runner/setup_bitcoin.go +++ b/e2e/runner/setup_bitcoin.go @@ -10,36 +10,36 @@ import ( "github.com/btcsuite/btcutil" ) -func (sm *SmokeTestRunner) SetupBitcoinAccount(initNetwork bool) { - sm.Logger.Print("⚙️ setting up Bitcoin account") +func (runner *E2ERunner) SetupBitcoinAccount(initNetwork bool) { + runner.Logger.Print("⚙️ setting up Bitcoin account") startTime := time.Now() defer func() { - sm.Logger.Print("✅ Bitcoin account setup in %s\n", time.Since(startTime)) + runner.Logger.Print("✅ Bitcoin account setup in %s\n", time.Since(startTime)) }() - _, err := sm.BtcRPCClient.CreateWallet(sm.Name, rpcclient.WithCreateWalletBlank()) + _, err := runner.BtcRPCClient.CreateWallet(runner.Name, rpcclient.WithCreateWalletBlank()) if err != nil { if !strings.Contains(err.Error(), "Database already exists") { panic(err) } } - sm.SetBtcAddress(sm.Name, true) + runner.SetBtcAddress(runner.Name, true) if initNetwork { // import the TSS address - err = sm.BtcRPCClient.ImportAddress(sm.BTCTSSAddress.EncodeAddress()) + err = runner.BtcRPCClient.ImportAddress(runner.BTCTSSAddress.EncodeAddress()) if err != nil { panic(err) } // mine some blocks to get some BTC into the deployer address - _, err = sm.BtcRPCClient.GenerateToAddress(101, sm.BTCDeployerAddress, nil) + _, err = runner.BtcRPCClient.GenerateToAddress(101, runner.BTCDeployerAddress, nil) if err != nil { panic(err) } - _, err = sm.BtcRPCClient.GenerateToAddress(4, sm.BTCDeployerAddress, nil) + _, err = runner.BtcRPCClient.GenerateToAddress(4, runner.BTCDeployerAddress, nil) if err != nil { panic(err) } @@ -47,21 +47,21 @@ func (sm *SmokeTestRunner) SetupBitcoinAccount(initNetwork bool) { } // GetBtcAddress returns the BTC address of the deployer from its EVM private key -func (sm *SmokeTestRunner) GetBtcAddress() (string, string, error) { - skBytes, err := hex.DecodeString(sm.DeployerPrivateKey) +func (runner *E2ERunner) GetBtcAddress() (string, string, error) { + skBytes, err := hex.DecodeString(runner.DeployerPrivateKey) if err != nil { return "", "", err } sk, _ := btcec.PrivKeyFromBytes(btcec.S256(), skBytes) - privkeyWIF, err := btcutil.NewWIF(sk, sm.BitcoinParams, true) + privkeyWIF, err := btcutil.NewWIF(sk, runner.BitcoinParams, true) if err != nil { return "", "", err } address, err := btcutil.NewAddressWitnessPubKeyHash( btcutil.Hash160(privkeyWIF.SerializePubKey()), - sm.BitcoinParams, + runner.BitcoinParams, ) if err != nil { return "", "", err @@ -72,32 +72,32 @@ func (sm *SmokeTestRunner) GetBtcAddress() (string, string, error) { } // SetBtcAddress imports the deployer's private key into the Bitcoin node -func (sm *SmokeTestRunner) SetBtcAddress(name string, rescan bool) { - skBytes, err := hex.DecodeString(sm.DeployerPrivateKey) +func (runner *E2ERunner) SetBtcAddress(name string, rescan bool) { + skBytes, err := hex.DecodeString(runner.DeployerPrivateKey) if err != nil { panic(err) } sk, _ := btcec.PrivKeyFromBytes(btcec.S256(), skBytes) - privkeyWIF, err := btcutil.NewWIF(sk, sm.BitcoinParams, true) + privkeyWIF, err := btcutil.NewWIF(sk, runner.BitcoinParams, true) if err != nil { panic(err) } if rescan { - err = sm.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true) + err = runner.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true) if err != nil { panic(err) } } - sm.BTCDeployerAddress, err = btcutil.NewAddressWitnessPubKeyHash( + runner.BTCDeployerAddress, err = btcutil.NewAddressWitnessPubKeyHash( btcutil.Hash160(privkeyWIF.PrivKey.PubKey().SerializeCompressed()), - sm.BitcoinParams, + runner.BitcoinParams, ) if err != nil { panic(err) } - sm.Logger.Info("BTCDeployerAddress: %s", sm.BTCDeployerAddress.EncodeAddress()) + runner.Logger.Info("BTCDeployerAddress: %s", runner.BTCDeployerAddress.EncodeAddress()) } diff --git a/e2e/runner/setup_evm.go b/e2e/runner/setup_evm.go new file mode 100644 index 0000000000..27674a6e5d --- /dev/null +++ b/e2e/runner/setup_evm.go @@ -0,0 +1,185 @@ +package runner + +import ( + "math/big" + "time" + + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol" + zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol" + zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" + "github.com/zeta-chain/zetacore/e2e/config" + "github.com/zeta-chain/zetacore/e2e/contracts/erc20" + "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" + "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/zetaclient/evm" +) + +const ( + ContractsConfigFile = "contracts.toml" +) + +// SetEVMContractsFromConfig set EVM contracts for e2e test from the config +func (runner *E2ERunner) SetEVMContractsFromConfig() { + conf, err := config.ReadConfig(ContractsConfigFile) + if err != nil { + panic(err) + } + + // Set ZetaEthAddr + runner.ZetaEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ZetaEthAddress) + runner.ZetaEth, err = zetaeth.NewZetaEth(runner.ZetaEthAddr, runner.GoerliClient) + if err != nil { + panic(err) + } + + // Set ConnectorEthAddr + runner.ConnectorEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ConnectorEthAddr) + runner.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(runner.ConnectorEthAddr, runner.GoerliClient) + if err != nil { + panic(err) + } +} + +// SetupEVM setup contracts on EVM for e2e test +func (runner *E2ERunner) SetupEVM(contractsDeployed bool) { + runner.Logger.Print("⚙️ setting up Goerli network") + startTime := time.Now() + defer func() { + runner.Logger.Info("EVM setup took %s\n", time.Since(startTime)) + }() + + // TODO: put this logic outside of this function + // We use this config to be consistent with the old implementation + // https://github.com/zeta-chain/node-private/issues/41 + if contractsDeployed { + runner.SetEVMContractsFromConfig() + return + } + conf := config.DefaultConfig() + + runner.Logger.InfoLoud("Deploy ZetaETH ConnectorETH ERC20Custody USDT\n") + + // donate to the TSS address to avoid account errors because deploying gas token ZRC20 will automatically mint + // gas token on ZetaChain to initialize the pool + txDonation, err := runner.SendEther(runner.TSSAddress, big.NewInt(101000000000000000), []byte(evm.DonationMessage)) + if err != nil { + panic(err) + } + + runner.Logger.Info("Deploying ZetaEth contract") + zetaEthAddr, txZetaEth, ZetaEth, err := zetaeth.DeployZetaEth( + runner.GoerliAuth, + runner.GoerliClient, + runner.DeployerAddress, + big.NewInt(21_000_000_000), + ) + if err != nil { + panic(err) + } + runner.ZetaEth = ZetaEth + runner.ZetaEthAddr = zetaEthAddr + conf.Contracts.EVM.ZetaEthAddress = zetaEthAddr.String() + runner.Logger.Info("ZetaEth contract address: %s, tx hash: %s", zetaEthAddr.Hex(), zetaEthAddr.Hash().Hex()) + + runner.Logger.Info("Deploying ZetaConnectorEth contract") + connectorEthAddr, txConnector, ConnectorEth, err := zetaconnectoreth.DeployZetaConnectorEth( + runner.GoerliAuth, + runner.GoerliClient, + zetaEthAddr, + runner.TSSAddress, + runner.DeployerAddress, + runner.DeployerAddress, + ) + if err != nil { + panic(err) + } + runner.ConnectorEth = ConnectorEth + runner.ConnectorEthAddr = connectorEthAddr + conf.Contracts.EVM.ConnectorEthAddr = connectorEthAddr.String() + + runner.Logger.Info("ZetaConnectorEth contract address: %s, tx hash: %s", connectorEthAddr.Hex(), txConnector.Hash().Hex()) + + runner.Logger.Info("Deploying ERC20Custody contract") + erc20CustodyAddr, txCustody, ERC20Custody, err := erc20custody.DeployERC20Custody( + runner.GoerliAuth, + runner.GoerliClient, + runner.DeployerAddress, + runner.DeployerAddress, + big.NewInt(0), + big.NewInt(1e18), + ethcommon.HexToAddress("0x"), + ) + if err != nil { + panic(err) + } + runner.ERC20CustodyAddr = erc20CustodyAddr + runner.ERC20Custody = ERC20Custody + runner.Logger.Info("ERC20Custody contract address: %s, tx hash: %s", erc20CustodyAddr.Hex(), txCustody.Hash().Hex()) + + runner.Logger.Info("Deploying USDT contract") + usdtAddr, txUSDT, usdt, err := erc20.DeployUSDT(runner.GoerliAuth, runner.GoerliClient, "USDT", "USDT", 6) + if err != nil { + panic(err) + } + runner.USDTERC20 = usdt + runner.USDTERC20Addr = usdtAddr + runner.Logger.Info("USDT contract address: %s, tx hash: %s", usdtAddr.Hex(), txUSDT.Hash().Hex()) + + // deploy TestDApp contract + appAddr, txApp, _, err := testdapp.DeployTestDApp(runner.GoerliAuth, runner.GoerliClient, runner.ConnectorEthAddr, runner.ZetaEthAddr) + if err != nil { + panic(err) + } + runner.TestDAppAddr = appAddr + runner.Logger.Info("TestDApp contract address: %s, tx hash: %s", appAddr.Hex(), txApp.Hash().Hex()) + + // check contract deployment receipt + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txDonation, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("GOERLI donation tx failed") + } + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txZetaEth, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("ZetaEth deployment failed") + } + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txConnector, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("ZetaConnectorEth deployment failed") + } + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txCustody, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("ERC20Custody deployment failed") + } + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txUSDT, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("USDT deployment failed") + } + receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txApp, runner.Logger, runner.ReceiptTimeout) + if receipt.Status != 1 { + panic("TestDApp deployment failed") + } + + // initialize custody contract + runner.Logger.Info("Whitelist USDT") + txWhitelist, err := ERC20Custody.Whitelist(runner.GoerliAuth, usdtAddr) + if err != nil { + panic(err) + } + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txWhitelist, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("USDT whitelist failed") + } + + runner.Logger.Info("Set TSS address") + txCustody, err = ERC20Custody.UpdateTSSAddress(runner.GoerliAuth, runner.TSSAddress) + if err != nil { + panic(err) + } + if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, txCustody, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { + panic("USDT update TSS address failed") + } + runner.Logger.Info("TSS set receipt tx hash: %s", txCustody.Hash().Hex()) + + // save config containing contract addresses + // TODO: put this logic outside of this function in a general config + // We use this config to be consistent with the old implementation + // https://github.com/zeta-chain/node-private/issues/41 + if err := config.WriteConfig(ContractsConfigFile, conf); err != nil { + panic(err) + } +} diff --git a/e2e/runner/setup_zeta.go b/e2e/runner/setup_zeta.go new file mode 100644 index 0000000000..6cfc6890a0 --- /dev/null +++ b/e2e/runner/setup_zeta.go @@ -0,0 +1,200 @@ +package runner + +import ( + "math/big" + "time" + + "github.com/zeta-chain/zetacore/e2e/contracts/contextapp" + "github.com/zeta-chain/zetacore/e2e/contracts/zevmswap" + utils2 "github.com/zeta-chain/zetacore/e2e/utils" + + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/connectorzevm.sol" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/wzeta.sol" + + "github.com/btcsuite/btcutil" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" + "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-core/contracts/uniswapv2factory.sol" + uniswapv2router "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-periphery/contracts/uniswapv2router02.sol" + "github.com/zeta-chain/zetacore/common" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +// SetTSSAddresses set TSS addresses from information queried from ZetaChain +func (runner *E2ERunner) SetTSSAddresses() error { + runner.Logger.Print("⚙️ setting up TSS address") + + btcChainID, err := common.GetBTCChainIDFromChainParams(runner.BitcoinParams) + if err != nil { + return err + } + + res := &observertypes.QueryGetTssAddressResponse{} + for i := 0; ; i++ { + res, err = runner.ObserverClient.GetTssAddress(runner.Ctx, &observertypes.QueryGetTssAddressRequest{ + BitcoinChainId: btcChainID, + }) + if err != nil { + if i%10 == 0 { + runner.Logger.Info("ObserverClient.TSS error %s", err.Error()) + runner.Logger.Info("TSS not ready yet, waiting for TSS to be appear in zetacore network...") + } + time.Sleep(1 * time.Second) + continue + } + break + } + + tssAddress := ethcommon.HexToAddress(res.Eth) + + btcTSSAddress, err := btcutil.DecodeAddress(res.Btc, runner.BitcoinParams) + if err != nil { + panic(err) + } + + runner.TSSAddress = tssAddress + runner.BTCTSSAddress = btcTSSAddress + + return nil +} + +// SetZEVMContracts set contracts for the ZEVM +func (runner *E2ERunner) SetZEVMContracts() { + runner.Logger.Print("⚙️ deploying system contracts and ZRC20s on ZEVM") + startTime := time.Now() + defer func() { + runner.Logger.Info("System contract deployments took %s\n", time.Since(startTime)) + }() + + // deploy system contracts and ZRC20 contracts on ZetaChain + uniswapV2FactoryAddr, uniswapV2RouterAddr, zevmConnectorAddr, wzetaAddr, usdtZRC20Addr, err := runner.ZetaTxServer.DeploySystemContractsAndZRC20( + utils2.FungibleAdminName, + runner.USDTERC20Addr.Hex(), + ) + if err != nil { + panic(err) + } + + // Set USDTZRC20Addr + runner.USDTZRC20Addr = ethcommon.HexToAddress(usdtZRC20Addr) + runner.USDTZRC20, err = zrc20.NewZRC20(runner.USDTZRC20Addr, runner.ZevmClient) + if err != nil { + panic(err) + } + + // UniswapV2FactoryAddr + runner.UniswapV2FactoryAddr = ethcommon.HexToAddress(uniswapV2FactoryAddr) + runner.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(runner.UniswapV2FactoryAddr, runner.ZevmClient) + if err != nil { + panic(err) + } + + // UniswapV2RouterAddr + runner.UniswapV2RouterAddr = ethcommon.HexToAddress(uniswapV2RouterAddr) + runner.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(runner.UniswapV2RouterAddr, runner.ZevmClient) + if err != nil { + panic(err) + } + + // ZevmConnectorAddr + runner.ConnectorZEVMAddr = ethcommon.HexToAddress(zevmConnectorAddr) + runner.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(runner.ConnectorZEVMAddr, runner.ZevmClient) + if err != nil { + panic(err) + } + + // WZetaAddr + runner.WZetaAddr = ethcommon.HexToAddress(wzetaAddr) + runner.WZeta, err = wzeta.NewWETH9(runner.WZetaAddr, runner.ZevmClient) + if err != nil { + panic(err) + } + + // query system contract address from the chain + systemContractRes, err := runner.FungibleClient.SystemContract( + runner.Ctx, + &fungibletypes.QueryGetSystemContractRequest{}, + ) + if err != nil { + panic(err) + } + systemContractAddr := ethcommon.HexToAddress(systemContractRes.SystemContract.SystemContract) + + SystemContract, err := systemcontract.NewSystemContract( + systemContractAddr, + runner.ZevmClient, + ) + if err != nil { + panic(err) + } + + runner.SystemContract = SystemContract + runner.SystemContractAddr = systemContractAddr + + // set ZRC20 contracts + runner.SetupETHZRC20() + runner.SetupBTCZRC20() + + // deploy ZEVMSwapApp and ContextApp + zevmSwapAppAddr, txZEVMSwapApp, zevmSwapApp, err := zevmswap.DeployZEVMSwapApp( + runner.ZevmAuth, + runner.ZevmClient, + runner.UniswapV2RouterAddr, + runner.SystemContractAddr, + ) + if err != nil { + panic(err) + } + + contextAppAddr, txContextApp, contextApp, err := contextapp.DeployContextApp(runner.ZevmAuth, runner.ZevmClient) + if err != nil { + panic(err) + } + + receipt := utils2.MustWaitForTxReceipt(runner.Ctx, runner.ZevmClient, txZEVMSwapApp, runner.Logger, runner.ReceiptTimeout) + if receipt.Status != 1 { + panic("ZEVMSwapApp deployment failed") + } + runner.ZEVMSwapAppAddr = zevmSwapAppAddr + runner.ZEVMSwapApp = zevmSwapApp + + receipt = utils2.MustWaitForTxReceipt(runner.Ctx, runner.ZevmClient, txContextApp, runner.Logger, runner.ReceiptTimeout) + if receipt.Status != 1 { + panic("ContextApp deployment failed") + } + runner.ContextAppAddr = contextAppAddr + runner.ContextApp = contextApp +} + +func (runner *E2ERunner) SetupETHZRC20() { + ethZRC20Addr, err := runner.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(common.GoerliLocalnetChain().ChainId)) + if err != nil { + panic(err) + } + if (ethZRC20Addr == ethcommon.Address{}) { + panic("eth zrc20 not found") + } + runner.ETHZRC20Addr = ethZRC20Addr + ethZRC20, err := zrc20.NewZRC20(ethZRC20Addr, runner.ZevmClient) + if err != nil { + panic(err) + } + runner.ETHZRC20 = ethZRC20 +} + +func (runner *E2ERunner) SetupBTCZRC20() { + BTCZRC20Addr, err := runner.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(common.BtcRegtestChain().ChainId)) + if err != nil { + panic(err) + } + runner.BTCZRC20Addr = BTCZRC20Addr + runner.Logger.Info("BTCZRC20Addr: %s", BTCZRC20Addr.Hex()) + BTCZRC20, err := zrc20.NewZRC20(BTCZRC20Addr, runner.ZevmClient) + if err != nil { + panic(err) + } + runner.BTCZRC20 = BTCZRC20 +} diff --git a/e2e/runner/zeta.go b/e2e/runner/zeta.go new file mode 100644 index 0000000000..b5df8145d9 --- /dev/null +++ b/e2e/runner/zeta.go @@ -0,0 +1,112 @@ +package runner + +import ( + "fmt" + "math/big" + + utils2 "github.com/zeta-chain/zetacore/e2e/utils" + + ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +// WaitForMinedCCTX waits for a cctx to be mined from a tx +func (runner *E2ERunner) WaitForMinedCCTX(txHash ethcommon.Hash) { + defer func() { + runner.Unlock() + }() + runner.Lock() + + cctx := utils2.WaitCctxMinedByInTxHash(runner.Ctx, txHash.Hex(), runner.CctxClient, runner.Logger, runner.CctxTimeout) + if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { + panic(fmt.Sprintf("expected cctx status to be mined; got %s, message: %s", + cctx.CctxStatus.Status.String(), + cctx.CctxStatus.StatusMessage), + ) + } +} + +// SendZetaOnEvm sends ZETA to an address on EVM +// this allows the ZETA contract deployer to funds other accounts on EVM +func (runner *E2ERunner) SendZetaOnEvm(address ethcommon.Address, zetaAmount int64) *ethtypes.Transaction { + // the deployer might be sending ZETA in different goroutines + defer func() { + runner.Unlock() + }() + runner.Lock() + + amount := big.NewInt(1e18) + amount = amount.Mul(amount, big.NewInt(zetaAmount)) + tx, err := runner.ZetaEth.Transfer(runner.GoerliAuth, address, amount) + if err != nil { + panic(err) + } + return tx +} + +// DepositZeta deposits ZETA on ZetaChain from the ZETA smart contract on EVM +func (runner *E2ERunner) DepositZeta() ethcommon.Hash { + amount := big.NewInt(1e18) + amount = amount.Mul(amount, big.NewInt(100)) // 100 Zeta + + return runner.DepositZetaWithAmount(amount) +} + +// DepositZetaWithAmount deposits ZETA on ZetaChain from the ZETA smart contract on EVM with the specified amount +func (runner *E2ERunner) DepositZetaWithAmount(amount *big.Int) ethcommon.Hash { + tx, err := runner.ZetaEth.Approve(runner.GoerliAuth, runner.ConnectorEthAddr, amount) + if err != nil { + panic(err) + } + runner.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + + receipt := utils2.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + runner.Logger.EVMReceipt(*receipt, "approve") + if receipt.Status != 1 { + panic("approve tx failed") + } + + // query the chain ID using zevm client + zetaChainID, err := runner.ZevmClient.ChainID(runner.Ctx) + if err != nil { + panic(err) + } + + tx, err = runner.ConnectorEth.Send(runner.GoerliAuth, zetaconnectoreth.ZetaInterfacesSendInput{ + // TODO: allow user to specify destination chain id + // https://github.com/zeta-chain/node-private/issues/41 + DestinationChainId: zetaChainID, + DestinationAddress: runner.DeployerAddress.Bytes(), + DestinationGasLimit: big.NewInt(250_000), + Message: nil, + ZetaValueAndGas: amount, + ZetaParams: nil, + }) + if err != nil { + panic(err) + } + runner.Logger.Info("Send tx hash: %s", tx.Hash().Hex()) + + receipt = utils2.MustWaitForTxReceipt(runner.Ctx, runner.GoerliClient, tx, runner.Logger, runner.ReceiptTimeout) + runner.Logger.EVMReceipt(*receipt, "send") + if receipt.Status != 1 { + panic(fmt.Sprintf("expected tx receipt status to be 1; got %d", receipt.Status)) + } + + runner.Logger.Info(" Logs:") + for _, log := range receipt.Logs { + sentLog, err := runner.ConnectorEth.ParseZetaSent(*log) + if err == nil { + runner.Logger.Info(" Connector: %s", runner.ConnectorEthAddr.String()) + runner.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) + runner.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) + runner.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) + runner.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) + runner.Logger.Info(" Block Num: %d", log.BlockNumber) + } + } + + return tx.Hash() +} diff --git a/contrib/localnet/orchestrator/smoketest/txserver/zeta_tx_server.go b/e2e/txserver/zeta_tx_server.go similarity index 99% rename from contrib/localnet/orchestrator/smoketest/txserver/zeta_tx_server.go rename to e2e/txserver/zeta_tx_server.go index ee63851a74..5ab36c514a 100644 --- a/contrib/localnet/orchestrator/smoketest/txserver/zeta_tx_server.go +++ b/e2e/txserver/zeta_tx_server.go @@ -39,7 +39,7 @@ import ( observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) -// ZetaTxServer is a ZetaChain tx server for smoke test +// ZetaTxServer is a ZetaChain tx server for E2E test type ZetaTxServer struct { clientCtx client.Context txFactory tx.Factory diff --git a/contrib/localnet/orchestrator/smoketest/utils/evm.go b/e2e/utils/evm.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/utils/evm.go rename to e2e/utils/evm.go diff --git a/contrib/localnet/orchestrator/smoketest/utils/utils.go b/e2e/utils/utils.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/utils/utils.go rename to e2e/utils/utils.go diff --git a/contrib/localnet/orchestrator/smoketest/utils/zetacore.go b/e2e/utils/zetacore.go similarity index 100% rename from contrib/localnet/orchestrator/smoketest/utils/zetacore.go rename to e2e/utils/zetacore.go diff --git a/readme.md b/readme.md index 08b8c1d882..16204d6629 100644 --- a/readme.md +++ b/readme.md @@ -29,7 +29,7 @@ EVM-compatibility. ## Building the zetacored/zetaclientd binaries For the Athens 3 testnet, clone this repository, checkout the latest release tag, and type the following command to build the binaries: ``` -make install-testnet +make install ``` to build. @@ -73,7 +73,7 @@ documentation for all the messages in that module. ## Running tests To check that the source code is working as expected, refer to the manual on how -to [run the smoke test](./contrib/localnet/README.md). +to [run the E2E test](./LOCAL_TESTING.md). ## Community diff --git a/x/crosschain/types/tx.pb.go b/x/crosschain/types/tx.pb.go index 054713350d..650ef991dd 100644 --- a/x/crosschain/types/tx.pb.go +++ b/x/crosschain/types/tx.pb.go @@ -1088,9 +1088,9 @@ type MsgVoteOnObservedInboundTx struct { SenderChainId int64 `protobuf:"varint,3,opt,name=sender_chain_id,json=senderChainId,proto3" json:"sender_chain_id,omitempty"` Receiver string `protobuf:"bytes,4,opt,name=receiver,proto3" json:"receiver,omitempty"` ReceiverChain int64 `protobuf:"varint,5,opt,name=receiver_chain,json=receiverChain,proto3" json:"receiver_chain,omitempty"` - // string zeta_burnt = 6; + // string zeta_burnt = 6; Amount github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,6,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"amount"` - // string mMint = 7; + // string mMint = 7; Message string `protobuf:"bytes,8,opt,name=message,proto3" json:"message,omitempty"` InTxHash string `protobuf:"bytes,9,opt,name=in_tx_hash,json=inTxHash,proto3" json:"in_tx_hash,omitempty"` InBlockHeight uint64 `protobuf:"varint,10,opt,name=in_block_height,json=inBlockHeight,proto3" json:"in_block_height,omitempty"` diff --git a/zetaclient/bitcoin/bitcoin_client_rpc_test.go b/zetaclient/bitcoin/bitcoin_client_rpc_test.go index 3b16f0d55c..83ba9b426c 100644 --- a/zetaclient/bitcoin/bitcoin_client_rpc_test.go +++ b/zetaclient/bitcoin/bitcoin_client_rpc_test.go @@ -53,7 +53,7 @@ func (suite *BitcoinClientTestSuite) SetupTest() { btc := client.rpcClient - _, err = btc.CreateWallet("smoketest") + _, err = btc.CreateWallet("e2e") suite.Require().NoError(err) addr, err := btc.GetNewAddress("test") suite.Require().NoError(err) diff --git a/zetaclient/config/config_chain.go b/zetaclient/config/config_chain.go index f932be7305..369ebb994b 100644 --- a/zetaclient/config/config_chain.go +++ b/zetaclient/config/config_chain.go @@ -40,7 +40,7 @@ func New() Config { } var bitcoinConfigRegnet = &BTCConfig{ - RPCUsername: "smoketest", + RPCUsername: "e2e", RPCPassword: "123", RPCHost: "bitcoin:18443", RPCParams: "regtest",