From c6474133b52af8d32c08f9e91704fa39f80f7657 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 16 Sep 2024 16:42:26 +0200 Subject: [PATCH] test: bridge e2e testing (#57) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * tests: PoC bridge testing with bats * Run bats in e2e * Remove unused make lines * test: Send EOA and deploy contract E2E tests using Bats (#69) * feat: add helper functions for contract deployment and sending transactions using cast commands * feat: send EOA transaction test basic * feat: deploy ERC20Mock contract E2E test --------- Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> --- .github/workflows/lint.yml | 9 +- .github/workflows/test-e2e.yml | 4 + .golangci.yml | 86 ++- Makefile | 20 - aggoracle/oracle.go | 9 +- aggregator/aggregator.go | 18 +- aggregator/profitabilitychecker.go | 12 +- aggregator/prover/prover.go | 14 +- claimsponsor/claimsponsor.go | 10 +- cmd/run.go | 1 + config/types/duration_test.go | 2 +- .../datacommittee/datacommittee.go | 10 +- etherman/errors.go | 4 +- hex/hex.go | 6 +- l1infotree/hash.go | 2 +- l1infotree/tree.go | 4 +- l1infotreesync/processor.go | 11 +- lastgersync/processor.go | 10 +- log/log.go | 2 +- log/log_test.go | 2 +- merkletree/key.go | 6 +- merkletree/split.go | 20 +- reorgdetector/reorgdetector.go | 2 +- rpc/bridge.go | 10 +- sequencesender/seqsendertypes/types.go | 5 +- sequencesender/sequencesender.go | 30 +- sequencesender/txbuilder/banana_base.go | 2 +- sequencesender/txbuilder/banana_base_test.go | 2 +- sequencesender/txbuilder/interface.go | 2 +- .../txbuilder/validium_cond_num_batches.go | 2 +- .../txbuilder/zkevm_cond_max_size.go | 1 - state/encoding_batch_v2_test.go | 4 +- state/helper.go | 2 +- state/pgstatestorage/proof.go | 4 +- sync/evmdownloader.go | 2 +- test/Makefile | 2 + test/basic-e2e.bats | 49 ++ test/bridge-e2e.bats | 71 ++ test/config/test.kurtosis_template.toml | 1 - test/contracts/erc20mock/ERC20Mock.json | 657 ++++++++++++++++++ test/e2e.bats | 10 + test/helpers/aggoracle_e2e.go | 8 +- test/helpers/common-setup.bash | 13 + test/helpers/common.bash | 187 +++++ test/helpers/lxly-bridge-test.bash | 77 ++ test/run-e2e.sh | 5 +- test/scripts/env.sh | 1 + test/scripts/kurtosis_prepare_params_yml.sh | 15 +- tree/testvectors/types.go | 4 +- 49 files changed, 1251 insertions(+), 179 deletions(-) create mode 100644 test/basic-e2e.bats create mode 100644 test/bridge-e2e.bats create mode 100644 test/contracts/erc20mock/ERC20Mock.json create mode 100644 test/e2e.bats create mode 100644 test/helpers/common-setup.bash create mode 100644 test/helpers/common.bash create mode 100644 test/helpers/lxly-bridge-test.bash diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e644f97b..bdad36b2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,8 @@ jobs: go-version: 1.21.x - name: Checkout code uses: actions/checkout@v3 - - name: Lint - run: | - make install-linter - make lint + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: v1.61 + args: --timeout=30m diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 670ce8b3..b20bb982 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -57,8 +57,12 @@ jobs: repository: 0xPolygon/kurtosis-cdk path: "kurtosis-cdk" + - name: Setup Bats and bats libs + uses: bats-core/bats-action@2.0.0 + - name: Test run: make test-e2e-${{ matrix.e2e-group }} working-directory: test env: KURTOSIS_FOLDER: ${{ github.workspace }}/kurtosis-cdk + BATS_LIB_PATH: /usr/lib/ diff --git a/.golangci.yml b/.golangci.yml index 5dd6e0ec..98197d74 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,50 +3,45 @@ run: timeout: 3m tests: true - # default is true. Enables skipping of directories: - # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ skip-dirs-use-default: true - skip-dirs: - - tests - - aggregator/db/migrations service: - golangci-lint-version: 1.59.1 + golangci-lint-version: 1.61.0 linters: disable-all: true enable: - - whitespace # Tool for detection of leading and trailing whitespace - # - wsl # Forces you to use empty lines - - wastedassign # Finds wasted assignment statements - - unconvert # Unnecessary type conversions - - tparallel # Detects inappropriate usage of t.Parallel() method in your Go test codes - - thelper # Detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - stylecheck # Stylecheck is a replacement for golint - - prealloc # Finds slice declarations that could potentially be pre-allocated - - predeclared # Finds code that shadows one of Go's predeclared identifiers - - nolintlint # Ill-formed or insufficient nolint directives - # - nlreturn # Checks for a new line before return and branch statements to increase code clarity - - misspell # Misspelled English words in comments - - makezero # Finds slice declarations with non-zero initial length - - lll # Long lines - - importas # Enforces consistent import aliases - - gosec # Security problems - - gofmt # Whether the code was gofmt-ed - - goimports # Unused imports - - goconst # Repeated strings that could be replaced by a constant - - forcetypeassert # Finds forced type assertions - - dogsled # Checks assignments with too many blank identifiers (e.g. x, , , _, := f()) - - dupl # Code clone detection - - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error - - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13 - - gocritic # gocritic is a Go source code linter that maintains checks that are not in other linters - - errcheck # Errcheck is a go lint rule for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - # - godox # Godox is a linter for TODOs and FIXMEs left in the code - - gci # Gci is a linter for checking the consistency of the code with the go code style guide - - gomnd # Gomnd is a linter for magic numbers - # - revive - - unparam # Unparam is a linter for unused function parameters + - whitespace # Tool for detection of leading and trailing whitespace + # - wsl # Forces you to use empty lines + - wastedassign # Finds wasted assignment statements + - unconvert # Unnecessary type conversions + - tparallel # Detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # Detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - stylecheck # Stylecheck is a replacement for golint + - prealloc # Finds slice declarations that could potentially be pre-allocated + - predeclared # Finds code that shadows one of Go's predeclared identifiers + - nolintlint # Ill-formed or insufficient nolint directives + # - nlreturn # Checks for a new line before return and branch statements to increase code clarity + - misspell # Misspelled English words in comments + - makezero # Finds slice declarations with non-zero initial length + - lll # Long lines + - importas # Enforces consistent import aliases + - gosec # Security problems + - gofmt # Whether the code was gofmt-ed + - goimports # Unused imports + - goconst # Repeated strings that could be replaced by a constant + - forcetypeassert # Finds forced type assertions + - dogsled # Checks assignments with too many blank identifiers (e.g. x, , , _, := f()) + - dupl # Code clone detection + - errname # Checks that sentinel errors are prefixed with Err and error types are suffixed with Error + - errorlint # Error wrapping introduced in Go 1.13 + - gocritic # gocritic is a Go source code linter that maintains checks that are not in other linters + - errcheck # Errcheck is a go lint rule for checking for unchecked errors + # - godox # Linter for TODOs and FIXMEs left in the code + - gci # Gci checks the consistency of the code with the Go code style guide + - mnd # mnd is a linter for magic numbers + # - revive + - unparam # Unused function parameters linters-settings: gofmt: @@ -54,20 +49,19 @@ linters-settings: gocritic: enabled-checks: - ruleguard - # settings: - # ruleguard: - # rules: "./gorules/rules.go" revive: rules: - - name: exported - arguments: - - disableStutteringCheck + - name: exported + arguments: + - disableStutteringCheck goconst: min-len: 3 min-occurrences: 3 + gosec: + excludes: + - G115 # Potential integer overflow when converting between integer types issues: - # new-from-rev: origin/develop # report only new issues with reference to develop branch whole-files: true exclude-rules: - path: '(_test\.go|^test/.*)' @@ -78,9 +72,11 @@ issues: - path: 'etherman/contracts/contracts_(banana|elderberry)\.go' linters: - dupl + exclude-dirs: + - tests + - aggregator/db/migrations include: - EXC0012 # Exported (.+) should have comment( \(or a comment on this block\))? or be unexported - EXC0013 # Package comment should be of the form "(.+)... - EXC0014 # Comment on exported (.+) should be of the form "(.+)..." - EXC0015 # Should have a package comment - \ No newline at end of file diff --git a/Makefile b/Makefile index 7f8ff33b..c653ec1e 100644 --- a/Makefile +++ b/Makefile @@ -20,15 +20,6 @@ LDFLAGS += -X 'github.com/0xPolygon/cdk.GitRev=$(GITREV)' LDFLAGS += -X 'github.com/0xPolygon/cdk.GitBranch=$(GITBRANCH)' LDFLAGS += -X 'github.com/0xPolygon/cdk.BuildDate=$(DATE)' -# Variables -VENV = .venv -VENV_PYTHON = $(VENV)/bin/python -SYSTEM_PYTHON = $(or $(shell which python3), $(shell which python)) -PYTHON = $(or $(wildcard $(VENV_PYTHON)), "install_first_venv") -GENERATE_SCHEMA_DOC = $(VENV)/bin/generate-schema-doc -GENERATE_DOC_PATH = "docs/config-file/" -GENERATE_DOC_TEMPLATES_PATH = "docs/config-file/templates/" - # Check dependencies # Check for Go .PHONY: check-go @@ -87,22 +78,11 @@ test-unit: .PHONY: test-seq_sender test-seq_sender: trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -short -race -p 1 -covermode=atomic -coverprofile=../coverage.out -timeout 200s ./sequencesender/... - - -.PHONY: install-linter -install-linter: ## Installs the linter - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.54.2 .PHONY: lint lint: ## Runs the linter export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/golangci-lint run --timeout 5m -$(VENV_PYTHON): - rm -rf $(VENV) - $(SYSTEM_PYTHON) -m venv $(VENV) - -venv: $(VENV_PYTHON) - .PHONY: generate-code-from-proto generate-code-from-proto: ## Generates code from proto files cd proto/src/proto/aggregator/v1 && protoc --proto_path=. --proto_path=../../../../include --go_out=../../../../../aggregator/prover --go-grpc_out=../../../../../aggregator/prover --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative aggregator.proto diff --git a/aggoracle/oracle.go b/aggoracle/oracle.go index edbddd77..1ba94d7a 100644 --- a/aggoracle/oracle.go +++ b/aggoracle/oracle.go @@ -66,12 +66,15 @@ func (a *AggOracle) Start(ctx context.Context) { case <-a.ticker.C: blockNumToFetch, gerToInject, err = a.getLastFinalisedGER(ctx, blockNumToFetch) if err != nil { - if errors.Is(err, l1infotreesync.ErrBlockNotProcessed) { + switch { + case errors.Is(err, l1infotreesync.ErrBlockNotProcessed): a.logger.Debugf("syncer is not ready for the block %d", blockNumToFetch) - } else if errors.Is(err, l1infotreesync.ErrNotFound) { + + case errors.Is(err, l1infotreesync.ErrNotFound): blockNumToFetch = 0 a.logger.Debugf("syncer has not found any GER until block %d", blockNumToFetch) - } else { + + default: a.logger.Error("error calling getLastFinalisedGER: ", err) } diff --git a/aggregator/aggregator.go b/aggregator/aggregator.go index 6c033f9f..a97d72f9 100644 --- a/aggregator/aggregator.go +++ b/aggregator/aggregator.go @@ -279,7 +279,7 @@ func (a *Aggregator) handleReorg(reorgData synchronizer.ReorgExecutionResult) { "Halting the aggregator due to a L1 reorg. " + "Reorged data has been deleted, so it is safe to manually restart the aggregator.", ) - time.Sleep(10 * time.Second) //nolint:gomnd + time.Sleep(10 * time.Second) //nolint:mnd } } @@ -377,6 +377,7 @@ func (a *Aggregator) handleRollbackBatches(rollbackData synchronizer.RollbackBat } marshalledBookMark, err = proto.Marshal(bookMark) + //nolint:gocritic if err != nil { a.logger.Error("failed to marshal bookmark: %v", err) } else { @@ -405,7 +406,7 @@ func (a *Aggregator) handleRollbackBatches(rollbackData synchronizer.RollbackBat a.halted.Store(true) for { a.logger.Errorf("Halting the aggregator due to an error handling rollback batches event: %v", err) - time.Sleep(10 * time.Second) //nolint:gomnd + time.Sleep(10 * time.Second) //nolint:mnd } } } @@ -1149,6 +1150,7 @@ func (a *Aggregator) validateEligibleFinalProof( batchNumberToVerify := lastVerifiedBatchNum + 1 if proof.BatchNumber != batchNumberToVerify { + //nolint:gocritic if proof.BatchNumber < batchNumberToVerify && proof.BatchNumberFinal >= batchNumberToVerify { // We have a proof that contains some batches below the last batch verified, anyway can be eligible as final proof @@ -1728,8 +1730,9 @@ func (a *Aggregator) buildInputProver( l1InfoTreeData := map[uint32]*prover.L1Data{} forcedBlockhashL1 := common.Hash{} l1InfoRoot := batchToVerify.L1InfoRoot.Bytes() + //nolint:gocritic if !isForcedBatch { - tree, err := l1infotree.NewL1InfoTree(a.logger, 32, [][32]byte{}) //nolint:gomnd + tree, err := l1infotree.NewL1InfoTree(a.logger, 32, [][32]byte{}) //nolint:mnd if err != nil { return nil, err } @@ -1741,7 +1744,10 @@ func (a *Aggregator) buildInputProver( aLeaves := make([][32]byte, len(leaves)) for i, leaf := range leaves { - aLeaves[i] = l1infotree.HashLeafData(leaf.GlobalExitRoot, leaf.PreviousBlockHash, uint64(leaf.Timestamp.Unix())) + aLeaves[i] = l1infotree.HashLeafData( + leaf.GlobalExitRoot, + leaf.PreviousBlockHash, + uint64(leaf.Timestamp.Unix())) } for _, l2blockRaw := range batchRawData.Blocks { @@ -1836,7 +1842,7 @@ func (a *Aggregator) buildInputProver( return inputProver, nil } -func (a *Aggregator) getWitness(batchNumber uint64, URL string, fullWitness bool) ([]byte, error) { +func (a *Aggregator) getWitness(batchNumber uint64, url string, fullWitness bool) ([]byte, error) { var ( witness string response rpc.Response @@ -1850,7 +1856,7 @@ func (a *Aggregator) getWitness(batchNumber uint64, URL string, fullWitness bool a.logger.Infof("Requesting witness for batch %d of type %s", batchNumber, witnessType) - response, err = rpc.JSONRPCCall(URL, "zkevm_getBatchWitness", batchNumber, witnessType) + response, err = rpc.JSONRPCCall(url, "zkevm_getBatchWitness", batchNumber, witnessType) if err != nil { return nil, err } diff --git a/aggregator/profitabilitychecker.go b/aggregator/profitabilitychecker.go index 225cedb9..f05799eb 100644 --- a/aggregator/profitabilitychecker.go +++ b/aggregator/profitabilitychecker.go @@ -36,7 +36,7 @@ func NewTxProfitabilityCheckerBase( // IsProfitable checks pol collateral with min reward func (pc *TxProfitabilityCheckerBase) IsProfitable(ctx context.Context, polCollateral *big.Int) (bool, error) { - //if pc.IntervalAfterWhichBatchSentAnyway != 0 { + // if pc.IntervalAfterWhichBatchSentAnyway != 0 { // ok, err := isConsolidatedBatchAppeared(ctx, pc.State, pc.IntervalAfterWhichBatchSentAnyway) // if err != nil { // return false, err @@ -44,7 +44,7 @@ func (pc *TxProfitabilityCheckerBase) IsProfitable(ctx context.Context, polColla // if ok { // return true, nil // } - //} + // } return polCollateral.Cmp(pc.MinReward) >= 0, nil } @@ -64,7 +64,7 @@ func NewTxProfitabilityCheckerAcceptAll(state stateInterface, interval time.Dura // IsProfitable validate batch anyway and don't check anything func (pc *TxProfitabilityCheckerAcceptAll) IsProfitable(ctx context.Context, polCollateral *big.Int) (bool, error) { - //if pc.IntervalAfterWhichBatchSentAnyway != 0 { + // if pc.IntervalAfterWhichBatchSentAnyway != 0 { // ok, err := isConsolidatedBatchAppeared(ctx, pc.State, pc.IntervalAfterWhichBatchSentAnyway) // if err != nil { // return false, err @@ -72,12 +72,12 @@ func (pc *TxProfitabilityCheckerAcceptAll) IsProfitable(ctx context.Context, pol // if ok { // return true, nil // } - //} + // } return true, nil } // TODO: now it's impossible to check, when batch got consolidated, bcs it's not saved -//func isConsolidatedBatchAppeared(ctx context.Context, state stateInterface, +// func isConsolidatedBatchAppeared(ctx context.Context, state stateInterface, // intervalAfterWhichBatchConsolidatedAnyway time.Duration) (bool, error) { // batch, err := state.GetLastVerifiedBatch(ctx, nil) // if err != nil { @@ -89,4 +89,4 @@ func (pc *TxProfitabilityCheckerAcceptAll) IsProfitable(ctx context.Context, pol // } // // return false, err -//} +// } diff --git a/aggregator/prover/prover.go b/aggregator/prover/prover.go index cd6df050..8cb13b1d 100644 --- a/aggregator/prover/prover.go +++ b/aggregator/prover/prover.go @@ -443,13 +443,13 @@ func fea2scalar(v []uint64) *big.Int { return big.NewInt(0) } res := new(big.Int).SetUint64(v[0]) - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[1]), 32)) //nolint:gomnd - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[2]), 64)) //nolint:gomnd - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[3]), 96)) //nolint:gomnd - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[4]), 128)) //nolint:gomnd - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[5]), 160)) //nolint:gomnd - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[6]), 192)) //nolint:gomnd - res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[7]), 224)) //nolint:gomnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[1]), 32)) //nolint:mnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[2]), 64)) //nolint:mnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[3]), 96)) //nolint:mnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[4]), 128)) //nolint:mnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[5]), 160)) //nolint:mnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[6]), 192)) //nolint:mnd + res.Add(res, new(big.Int).Lsh(new(big.Int).SetUint64(v[7]), 224)) //nolint:mnd return res } diff --git a/claimsponsor/claimsponsor.go b/claimsponsor/claimsponsor.go index 30eb9123..fbcdca73 100644 --- a/claimsponsor/claimsponsor.go +++ b/claimsponsor/claimsponsor.go @@ -263,15 +263,19 @@ func (c *ClaimSponsor) AddClaimToQueue(ctx context.Context, claim *Claim) error var queuePosition uint64 lastQueuePosition, _, err := getLastQueueIndex(tx) - if errors.Is(err, ErrNotFound) { + switch { + case errors.Is(err, ErrNotFound): queuePosition = 0 - } else if err != nil { + + case err != nil: tx.Rollback() return err - } else { + + default: queuePosition = lastQueuePosition + 1 } + err = tx.Put(queueTable, dbCommon.Uint64ToBytes(queuePosition), claim.Key()) if err != nil { tx.Rollback() diff --git a/cmd/run.go b/cmd/run.go index 1eb86839..773c5e24 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -102,6 +102,7 @@ func start(cliCtx *cli.Context) error { // start aggregator in a goroutine, checking for errors go func() { if err := aggregator.Start(); err != nil { + aggregator.Stop() log.Fatal(err) } }() diff --git a/config/types/duration_test.go b/config/types/duration_test.go index 71e06a04..c11bd083 100644 --- a/config/types/duration_test.go +++ b/config/types/duration_test.go @@ -43,7 +43,7 @@ func TestDurationUnmarshal(t *testing.T) { err = json.Unmarshal(input, &d) if testCase.expectedResult != nil { - require.Equal(t, (*testCase.expectedResult).Nanoseconds(), d.Nanoseconds()) + require.Equal(t, testCase.expectedResult.Nanoseconds(), d.Nanoseconds()) } if err != nil { diff --git a/dataavailability/datacommittee/datacommittee.go b/dataavailability/datacommittee/datacommittee.go index bb74984c..01b96a13 100644 --- a/dataavailability/datacommittee/datacommittee.go +++ b/dataavailability/datacommittee/datacommittee.go @@ -2,10 +2,10 @@ package datacommittee import ( "crypto/ecdsa" + "crypto/rand" "errors" "fmt" "math/big" - "math/rand" "sort" "strings" @@ -93,7 +93,11 @@ func (d *Backend) Init() error { if committee != nil { d.committeeMembers = committee.Members if len(committee.Members) > 0 { - selectedCommitteeMember = rand.Intn(len(committee.Members)) //nolint:gosec + nBig, err := rand.Int(rand.Reader, big.NewInt(int64(len(committee.Members)))) + if err != nil { + return err + } + selectedCommitteeMember = int(nBig.Int64()) } } d.selectedCommitteeMember = selectedCommitteeMember @@ -304,7 +308,7 @@ func (d *Backend) requestSignatureFromMember(ctx context.Context, signedSequence // request c := client.New(member.URL) d.logger.Infof("sending request to sign the sequence to %s at %s", member.Addr.Hex(), member.URL) - //funcSign must call something like that c.SignSequenceBanana(ctx, signedSequence) + // funcSign must call something like that c.SignSequenceBanana(ctx, signedSequence) signature, err := funcSign(c) if err != nil { diff --git a/etherman/errors.go b/etherman/errors.go index c4fd9387..a2d748e7 100644 --- a/etherman/errors.go +++ b/etherman/errors.go @@ -10,9 +10,9 @@ var ( ErrGasRequiredExceedsAllowance = errors.New("gas required exceeds allowance") // ErrContentLengthTooLarge content length is too large ErrContentLengthTooLarge = errors.New("content length too large") - //ErrTimestampMustBeInsideRange Timestamp must be inside range + // ErrTimestampMustBeInsideRange Timestamp must be inside range ErrTimestampMustBeInsideRange = errors.New("timestamp must be inside range") - //ErrInsufficientAllowance insufficient allowance + // ErrInsufficientAllowance insufficient allowance ErrInsufficientAllowance = errors.New("insufficient allowance") // ErrBothGasPriceAndMaxFeeGasAreSpecified both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified ErrBothGasPriceAndMaxFeeGasAreSpecified = errors.New( diff --git a/hex/hex.go b/hex/hex.go index 7e5b1d01..c7e1f860 100644 --- a/hex/hex.go +++ b/hex/hex.go @@ -68,7 +68,7 @@ func DecodeUint64(str string) uint64 { // EncodeUint64 encodes a number as a hex string with 0x prefix. func EncodeUint64(i uint64) string { - enc := make([]byte, 2, 10) //nolint:gomnd + enc := make([]byte, 2, 10) //nolint:mnd copy(enc, "0x") return string(strconv.AppendUint(enc, i, Base)) @@ -83,9 +83,9 @@ func DecodeNibble(in byte) uint64 { case in >= '0' && in <= '9': return uint64(in - '0') case in >= 'A' && in <= 'F': - return uint64(in - 'A' + 10) //nolint:gomnd + return uint64(in - 'A' + 10) //nolint:mnd case in >= 'a' && in <= 'f': - return uint64(in - 'a' + 10) //nolint:gomnd + return uint64(in - 'a' + 10) //nolint:mnd default: return BadNibble } diff --git a/l1infotree/hash.go b/l1infotree/hash.go index 120ba6c6..5a33f5a3 100644 --- a/l1infotree/hash.go +++ b/l1infotree/hash.go @@ -37,7 +37,7 @@ func generateZeroHashes(height uint8) [][32]byte { // HashLeafData calculates the keccak hash of the leaf values. func HashLeafData(ger, prevBlockHash common.Hash, minTimestamp uint64) [32]byte { var res [32]byte - t := make([]byte, 8) //nolint:gomnd + t := make([]byte, 8) //nolint:mnd binary.BigEndian.PutUint64(t, minTimestamp) copy(res[:], keccak256.Hash(ger.Bytes(), prevBlockHash.Bytes(), t)) diff --git a/l1infotree/tree.go b/l1infotree/tree.go index 38d66381..f3ad6d36 100644 --- a/l1infotree/tree.go +++ b/l1infotree/tree.go @@ -112,7 +112,7 @@ func (mt *L1InfoTree) ComputeMerkleProof(gerIndex uint32, leaves [][32]byte) ([] if index >= uint32(len(leaves)) { siblings = append(siblings, mt.zeroHashes[h]) } else { - if index%2 == 1 { //If it is odd + if index%2 == 1 { // If it is odd siblings = append(siblings, leaves[index-1]) } else { // It is even siblings = append(siblings, leaves[index+1]) @@ -130,7 +130,7 @@ func (mt *L1InfoTree) ComputeMerkleProof(gerIndex uint32, leaves [][32]byte) ([] } // Find the index of the leaf in the next level of the tree. // Divide the index by 2 to find the position in the upper level - index = uint32(float64(index) / 2) //nolint:gomnd + index = uint32(float64(index) / 2) //nolint:mnd ns = nsi leaves = hashes } diff --git a/l1infotreesync/processor.go b/l1infotreesync/processor.go index 781d4478..c76d7aac 100644 --- a/l1infotreesync/processor.go +++ b/l1infotreesync/processor.go @@ -77,7 +77,7 @@ type L1InfoTreeLeaf struct { // Hash as expected by the tree func (l *L1InfoTreeLeaf) hash() ethCommon.Hash { var res [32]byte - t := make([]byte, 8) //nolint:gomnd + t := make([]byte, 8) //nolint:mnd binary.BigEndian.PutUint64(t, l.Timestamp) copy(res[:], keccak256.Hash(l.globalExitRoot().Bytes(), l.PreviousBlockHash.Bytes(), t)) return res @@ -245,14 +245,17 @@ func (p *processor) ProcessBlock(ctx context.Context, b sync.Block) error { var initialL1InfoIndex uint32 var l1InfoLeavesAdded uint32 lastIndex, err := p.getLastIndex(tx) - if errors.Is(err, ErrNotFound) { + + switch { + case errors.Is(err, ErrNotFound): initialL1InfoIndex = 0 err = nil - } else if err != nil { + case err != nil: return fmt.Errorf("err: %w", err) - } else { + default: initialL1InfoIndex = lastIndex + 1 } + for _, e := range b.Events { event, ok := e.(Event) if !ok { diff --git a/lastgersync/processor.go b/lastgersync/processor.go index 049b2847..628ea04a 100644 --- a/lastgersync/processor.go +++ b/lastgersync/processor.go @@ -141,13 +141,15 @@ func (p *processor) ProcessBlock(ctx context.Context, block sync.Block) error { var lastIndex int64 if lenEvents > 0 { li, err := p.getLastIndexWithTx(tx) - if errors.Is(err, ErrNotFound) { + switch { + case errors.Is(err, ErrNotFound): lastIndex = -1 - } else if err != nil { - tx.Rollback() + case err != nil: + tx.Rollback() return err - } else { + + default: lastIndex = int64(li) } } diff --git a/log/log.go b/log/log.go index 201c8790..b6d9d1cc 100644 --- a/log/log.go +++ b/log/log.go @@ -97,7 +97,7 @@ func NewLogger(cfg Config) (*zap.SugaredLogger, *zap.AtomicLevel, error) { defer logger.Sync() //nolint:errcheck // skip 2 callers: one for our wrapper methods and one for the package functions - withOptions := logger.WithOptions(zap.AddCallerSkip(2)) //nolint:gomnd + withOptions := logger.WithOptions(zap.AddCallerSkip(2)) //nolint:mnd return withOptions.Sugar(), &level, nil } diff --git a/log/log_test.go b/log/log_test.go index 9d33bcd0..9a596608 100644 --- a/log/log_test.go +++ b/log/log_test.go @@ -20,7 +20,7 @@ func TestLog(t *testing.T) { cfg := Config{ Environment: EnvironmentDevelopment, Level: "debug", - Outputs: []string{"stderr"}, //[]string{"stdout", "test.log"} + Outputs: []string{"stderr"}, // []string{"stdout", "test.log"} } Init(cfg) diff --git a/merkletree/key.go b/merkletree/key.go index 1fd6feec..7926df60 100644 --- a/merkletree/key.go +++ b/merkletree/key.go @@ -127,14 +127,14 @@ func HashContractBytecode(code []byte) ([]uint64, error) { ) // add 0x01 - code = append(code, 0x01) //nolint:gomnd + code = append(code, 0x01) //nolint:mnd // add padding for len(code)%(56) != 0 { - code = append(code, 0x00) //nolint:gomnd + code = append(code, 0x00) //nolint:mnd } - code[len(code)-1] = code[len(code)-1] | 0x80 //nolint:gomnd + code[len(code)-1] = code[len(code)-1] | 0x80 //nolint:mnd numHashes := int(math.Ceil(float64(len(code)) / float64(maxBytesToAdd))) diff --git a/merkletree/split.go b/merkletree/split.go index 77189b20..e264807a 100644 --- a/merkletree/split.go +++ b/merkletree/split.go @@ -17,16 +17,16 @@ const wordLength = 64 // scalar2fea splits a *big.Int into array of 32bit uint64 values. func scalar2fea(value *big.Int) []uint64 { - val := make([]uint64, 8) //nolint:gomnd - mask, _ := new(big.Int).SetString("FFFFFFFF", 16) //nolint:gomnd + val := make([]uint64, 8) //nolint:mnd + mask, _ := new(big.Int).SetString("FFFFFFFF", 16) //nolint:mnd val[0] = new(big.Int).And(value, mask).Uint64() - val[1] = new(big.Int).And(new(big.Int).Rsh(value, 32), mask).Uint64() //nolint:gomnd - val[2] = new(big.Int).And(new(big.Int).Rsh(value, 64), mask).Uint64() //nolint:gomnd - val[3] = new(big.Int).And(new(big.Int).Rsh(value, 96), mask).Uint64() //nolint:gomnd - val[4] = new(big.Int).And(new(big.Int).Rsh(value, 128), mask).Uint64() //nolint:gomnd - val[5] = new(big.Int).And(new(big.Int).Rsh(value, 160), mask).Uint64() //nolint:gomnd - val[6] = new(big.Int).And(new(big.Int).Rsh(value, 192), mask).Uint64() //nolint:gomnd - val[7] = new(big.Int).And(new(big.Int).Rsh(value, 224), mask).Uint64() //nolint:gomnd + val[1] = new(big.Int).And(new(big.Int).Rsh(value, 32), mask).Uint64() //nolint:mnd + val[2] = new(big.Int).And(new(big.Int).Rsh(value, 64), mask).Uint64() //nolint:mnd + val[3] = new(big.Int).And(new(big.Int).Rsh(value, 96), mask).Uint64() //nolint:mnd + val[4] = new(big.Int).And(new(big.Int).Rsh(value, 128), mask).Uint64() //nolint:mnd + val[5] = new(big.Int).And(new(big.Int).Rsh(value, 160), mask).Uint64() //nolint:mnd + val[6] = new(big.Int).And(new(big.Int).Rsh(value, 192), mask).Uint64() //nolint:mnd + val[7] = new(big.Int).And(new(big.Int).Rsh(value, 224), mask).Uint64() //nolint:mnd return val } @@ -69,7 +69,7 @@ func StringToh4(str string) ([]uint64, error) { func scalarToh4(s *big.Int) []uint64 { b := ScalarToFilledByteSlice(s) - r := make([]uint64, 4) //nolint:gomnd + r := make([]uint64, 4) //nolint:mnd f, _ := hex.DecodeHex("0xFFFFFFFFFFFFFFFF") fbe := binary.BigEndian.Uint64(f) diff --git a/reorgdetector/reorgdetector.go b/reorgdetector/reorgdetector.go index 22c4693e..7a995bac 100644 --- a/reorgdetector/reorgdetector.go +++ b/reorgdetector/reorgdetector.go @@ -134,7 +134,7 @@ func (rd *ReorgDetector) detectReorgInTrackedList(ctx context.Context) error { headersCacheLock.Lock() currentHeader, ok := headersCache[hdr.Num] if !ok || currentHeader == nil { - if currentHeader, err = rd.client.HeaderByNumber(ctx, big.NewInt(int64(hdr.Num))); err != nil { + if currentHeader, err = rd.client.HeaderByNumber(ctx, new(big.Int).SetUint64(hdr.Num)); err != nil { headersCacheLock.Unlock() return fmt.Errorf("failed to get the header: %w", err) } diff --git a/rpc/bridge.go b/rpc/bridge.go index cd0d6855..23c67409 100644 --- a/rpc/bridge.go +++ b/rpc/bridge.go @@ -173,12 +173,14 @@ func (b *BridgeEndpoints) ClaimProof( return zeroHex, rpc.NewRPCError(rpc.DefaultErrorCode, fmt.Sprintf("failed to get rollup exit proof, error: %s", err)) } var proofLocalExitRoot [32]common.Hash - if networkID == 0 { + switch { + case networkID == 0: proofLocalExitRoot, err = b.bridgeL1.GetProof(ctx, depositCount, info.MainnetExitRoot) if err != nil { return zeroHex, rpc.NewRPCError(rpc.DefaultErrorCode, fmt.Sprintf("failed to get local exit proof, error: %s", err)) } - } else if networkID == b.networkID { + + case networkID == b.networkID: localExitRoot, err := b.l1InfoTree.GetLocalExitRoot(ctx, networkID, info.RollupExitRoot) if err != nil { return zeroHex, rpc.NewRPCError( @@ -193,12 +195,14 @@ func (b *BridgeEndpoints) ClaimProof( fmt.Sprintf("failed to get local exit proof, error: %s", err), ) } - } else { + + default: return zeroHex, rpc.NewRPCError( rpc.DefaultErrorCode, fmt.Sprintf("this client does not support network %d", networkID), ) } + return ClaimProof{ ProofLocalExitRoot: proofLocalExitRoot, ProofRollupExitRoot: proofRollupExitRoot, diff --git a/sequencesender/seqsendertypes/types.go b/sequencesender/seqsendertypes/types.go index 21b5834e..5d903dc5 100644 --- a/sequencesender/seqsendertypes/types.go +++ b/sequencesender/seqsendertypes/types.go @@ -5,7 +5,7 @@ import ( ) type Batch interface { - //underlyingType *ethmantypes.Batch + // underlyingType *ethmantypes.Batch DeepCopy() Batch LastCoinbase() common.Address ForcedBatchTimestamp() uint64 @@ -40,7 +40,4 @@ type Sequence interface { String() string // WRITE SetLastVirtualBatchNumber(batchNumber uint64) - //SetL1InfoRoot(hash common.Hash) - //SetOldAccInputHash(hash common.Hash) - //SetAccInputHash(hash common.Hash) } diff --git a/sequencesender/sequencesender.go b/sequencesender/sequencesender.go index 263e729b..3431d3fe 100644 --- a/sequencesender/sequencesender.go +++ b/sequencesender/sequencesender.go @@ -429,7 +429,8 @@ func (s *SequenceSender) getResultAndUpdateEthTx(ctx context.Context, txHash com } txResult, err := s.ethTxManager.Result(ctx, txHash) - if errors.Is(err, ethtxmanager.ErrNotFound) { + switch { + case errors.Is(err, ethtxmanager.ErrNotFound): s.logger.Infof("transaction %v does not exist in ethtxmanager. Marking it", txHash) txData.OnMonitor = false // Resend tx @@ -437,10 +438,12 @@ func (s *SequenceSender) getResultAndUpdateEthTx(ctx context.Context, txHash com if errSend == nil { txData.OnMonitor = false } - } else if err != nil { + + case err != nil: s.logger.Errorf("error getting result for tx %v: %v", txHash, err) return err - } else { + + default: s.updateEthTxResult(txData, txResult) } @@ -882,21 +885,22 @@ func (s *SequenceSender) handleReceivedDataStream( } } - // Already virtualized - if l2Block.BatchNumber <= s.fromStreamBatch { + switch { + case l2Block.BatchNumber <= s.fromStreamBatch: + // Already virtualized if l2Block.BatchNumber != s.latestStreamBatch { s.logger.Infof("skipped! batch already virtualized, number %d", l2Block.BatchNumber) } - } else if !s.validStream && l2Block.BatchNumber == s.fromStreamBatch+1 { + + case !s.validStream && l2Block.BatchNumber == s.fromStreamBatch+1: // Initial case after startup s.addNewSequenceBatch(l2Block) s.validStream = true - } else { + + case l2Block.BatchNumber > s.wipBatch: // Handle whether it's only a new block or also a new batch - if l2Block.BatchNumber > s.wipBatch { - // Create new sequential batch - s.addNewSequenceBatch(l2Block) - } + // Create new sequential batch + s.addNewSequenceBatch(l2Block) } // Latest stream batch @@ -1271,7 +1275,7 @@ func (s *SequenceSender) marginTimeElapsed( // Check the time difference between L2 block and currentTime var timeDiff int64 if l2BlockTimestamp >= currentTime { - //L2 block timestamp is above currentTime, negative timeDiff. We do in this way to avoid uint64 overflow + // L2 block timestamp is above currentTime, negative timeDiff. We do in this way to avoid uint64 overflow timeDiff = int64(-(l2BlockTimestamp - currentTime)) } else { timeDiff = int64(currentTime - l2BlockTimestamp) @@ -1280,7 +1284,7 @@ func (s *SequenceSender) marginTimeElapsed( // Check if the time difference is less than timeMargin (L1BlockTimestampMargin) if timeDiff < timeMargin { var waitTime int64 - if timeDiff < 0 { //L2 block timestamp is above currentTime + if timeDiff < 0 { // L2 block timestamp is above currentTime waitTime = timeMargin + (-timeDiff) } else { waitTime = timeMargin - timeDiff diff --git a/sequencesender/txbuilder/banana_base.go b/sequencesender/txbuilder/banana_base.go index a48efd23..7b451ed8 100644 --- a/sequencesender/txbuilder/banana_base.go +++ b/sequencesender/txbuilder/banana_base.go @@ -114,7 +114,7 @@ func (t *TxBuilderBananaBase) NewSequence( return nil, err } - oldAccInputHash := common.BytesToHash(accInputHash[:]) //copy it + oldAccInputHash := common.BytesToHash(accInputHash[:]) // copy it for _, batch := range sequence.Batches { infoRootHash := sequence.L1InfoRoot diff --git a/sequencesender/txbuilder/banana_base_test.go b/sequencesender/txbuilder/banana_base_test.go index 5386e287..af4b05c0 100644 --- a/sequencesender/txbuilder/banana_base_test.go +++ b/sequencesender/txbuilder/banana_base_test.go @@ -32,7 +32,7 @@ func TestBananaBaseNewSequenceEmpty(t *testing.T) { require.NotNil(t, seq) require.NoError(t, err) // TODO check values - //require.Equal(t, lastAcc, seq.LastAccInputHash()) + // require.Equal(t, lastAcc, seq.LastAccInputHash()) } func TestBananaBaseNewBatchFromL2Block(t *testing.T) { diff --git a/sequencesender/txbuilder/interface.go b/sequencesender/txbuilder/interface.go index 905aa855..f9a6275d 100644 --- a/sequencesender/txbuilder/interface.go +++ b/sequencesender/txbuilder/interface.go @@ -31,7 +31,7 @@ type TxBuilder interface { } type CondNewSequence interface { - //NewSequenceIfWorthToSend Return nil, nil if the sequence is not worth sending + // NewSequenceIfWorthToSend Return nil, nil if the sequence is not worth sending NewSequenceIfWorthToSend( ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, ) (seqsendertypes.Sequence, error) diff --git a/sequencesender/txbuilder/validium_cond_num_batches.go b/sequencesender/txbuilder/validium_cond_num_batches.go index 14a0bddf..35173d8e 100644 --- a/sequencesender/txbuilder/validium_cond_num_batches.go +++ b/sequencesender/txbuilder/validium_cond_num_batches.go @@ -23,7 +23,7 @@ func NewConditionalNewSequenceNumBatches(maxBatchesForL1 uint64) *ConditionalNew func (c *ConditionalNewSequenceNumBatches) NewSequenceIfWorthToSend( ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, ) (seqsendertypes.Sequence, error) { - if c.maxBatchesForL1 != MaxBatchesForL1Disabled && len(sequenceBatches) >= int(c.maxBatchesForL1) { + if c.maxBatchesForL1 != MaxBatchesForL1Disabled && uint64(len(sequenceBatches)) >= c.maxBatchesForL1 { log.Infof( "sequence should be sent to L1, because MaxBatchesForL1 (%d) has been reached", c.maxBatchesForL1, diff --git a/sequencesender/txbuilder/zkevm_cond_max_size.go b/sequencesender/txbuilder/zkevm_cond_max_size.go index dff4636e..66eb9446 100644 --- a/sequencesender/txbuilder/zkevm_cond_max_size.go +++ b/sequencesender/txbuilder/zkevm_cond_max_size.go @@ -61,7 +61,6 @@ func (c *ConditionalNewSequenceMaxSize) NewSequenceIfWorthToSend( sequenceBatches, err = handleEstimateGasSendSequenceErr(sequence.Batches(), err) if sequenceBatches != nil { // Handling the error gracefully, re-processing the sequence as a sanity check - //sequence, err = s.newSequenceBanana(sequenceBatches, s.cfg.L2Coinbase) sequence, err = txBuilder.NewSequence(ctx, sequenceBatches, l2Coinbase) if err != nil { return nil, err diff --git a/state/encoding_batch_v2_test.go b/state/encoding_batch_v2_test.go index 30b16d23..d263b5c7 100644 --- a/state/encoding_batch_v2_test.go +++ b/state/encoding_batch_v2_test.go @@ -117,8 +117,8 @@ func TestDecodeBatchV2(t *testing.T) { require.NoError(t, err) batchL2Data2, err := hex.DecodeString(codedL2Block2) require.NoError(t, err) - batch := append(batchL2Data, batchL2Data2...) - decodedBatch, err := DecodeBatchV2(batch) + batchL2Data = append(batchL2Data, batchL2Data2...) + decodedBatch, err := DecodeBatchV2(batchL2Data) require.NoError(t, err) require.Equal(t, 2, len(decodedBatch.Blocks)) require.Equal(t, uint32(0x73e6af6f), decodedBatch.Blocks[0].DeltaTimestamp) diff --git a/state/helper.go b/state/helper.go index aeedb8fe..7f2b64be 100644 --- a/state/helper.go +++ b/state/helper.go @@ -63,7 +63,7 @@ func prepareRLPTxData(tx *types.Transaction) ([]byte, error) { return nil, err } - newV := new(big.Int).Add(big.NewInt(ether155V), big.NewInt(int64(sign))) + newV := new(big.Int).Add(big.NewInt(ether155V), new(big.Int).SetUint64(sign)) newRPadded := fmt.Sprintf("%064s", r.Text(hex.Base)) newSPadded := fmt.Sprintf("%064s", s.Text(hex.Base)) newVPadded := fmt.Sprintf("%02s", newV.Text(hex.Base)) diff --git a/state/pgstatestorage/proof.go b/state/pgstatestorage/proof.go index a5ae6331..fa32fc99 100644 --- a/state/pgstatestorage/proof.go +++ b/state/pgstatestorage/proof.go @@ -257,9 +257,9 @@ func toPostgresInterval(duration string) (string, error) { return "", state.ErrUnsupportedDuration } - isMoreThanOne := duration[0] != '1' || len(duration) > 2 //nolint:gomnd + isMoreThanOne := duration[0] != '1' || len(duration) > 2 //nolint:mnd if isMoreThanOne { - pgUnit = pgUnit + "s" + pgUnit += "s" } return fmt.Sprintf("%s %s", duration[:len(duration)-1], pgUnit), nil diff --git a/sync/evmdownloader.go b/sync/evmdownloader.go index 1e70d12f..c9c4e661 100644 --- a/sync/evmdownloader.go +++ b/sync/evmdownloader.go @@ -246,7 +246,7 @@ func (d *EVMDownloaderImplementation) GetLogs(ctx context.Context, fromBlock, to func (d *EVMDownloaderImplementation) GetBlockHeader(ctx context.Context, blockNum uint64) EVMBlockHeader { attempts := 0 for { - header, err := d.ethClient.HeaderByNumber(ctx, big.NewInt(int64(blockNum))) + header, err := d.ethClient.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNum)) if err != nil { attempts++ d.log.Errorf("error getting block header for block %d, err: %v", blockNum, err) diff --git a/test/Makefile b/test/Makefile index 86bd147e..0c50ec35 100644 --- a/test/Makefile +++ b/test/Makefile @@ -25,10 +25,12 @@ generate-mocks-da: ## Generates mocks for dataavailability, using mockery tool .PHONY: test-e2e-elderberry-validium test-e2e-elderberry-validium: stop ## Runs e2e tests checking elderberry/validium ./run-e2e.sh cdk-validium + bats . .PHONY: test-e2e-elderberry-rollup test-e2e-elderberry-rollup: stop ## Runs e2e tests checking elderberry/rollup ./run-e2e.sh rollup + bats . .PHONY: stop stop: diff --git a/test/basic-e2e.bats b/test/basic-e2e.bats new file mode 100644 index 00000000..cbd845f5 --- /dev/null +++ b/test/basic-e2e.bats @@ -0,0 +1,49 @@ +setup() { + load 'helpers/common-setup' + load 'helpers/common' + _common_setup + + readonly enclave=${ENCLAVE:-cdk-v1} + readonly node=${KURTOSIS_NODE:-cdk-erigon-node-001} + readonly rpc_url=${RPC_URL:-$(kurtosis port print "$enclave" "$node" http-rpc)} + readonly private_key=${SENDER_PRIVATE_KEY:-"12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"} + readonly receiver=${RECEIVER:-"0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6"} +} + +@test "Send EOA transaction" { + local value="10ether" + + run sendTx "$private_key" "$receiver" "$value" + assert_success + assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)" +} + +@test "Deploy ERC20Mock contract" { + local contract_artifact="./contracts/erc20mock/ERC20Mock.json" + + # Deploy ERC20Mock + run deployContract "$private_key" "$contract_artifact" + assert_success + contract_addr=$(echo "$output" | tail -n 1) + + # Mint ERC20 tokens + local mintFnSig="function mint(address receiver, uint256 amount)" + local amount="5" + + run sendTx "$private_key" "$contract_addr" "$mintFnSig" "$receiver" "$amount" + assert_success + assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)" + + # Assert that balance is correct + local balanceOfFnSig="function balanceOf(address) (uint256)" + run queryContract "$contract_addr" "$balanceOfFnSig" "$receiver" + assert_success + receiverBalance=$(echo "$output" | tail -n 1) + + # Convert balance and amount to a standard format for comparison (e.g., remove any leading/trailing whitespace) + receiverBalance=$(echo "$receiverBalance" | xargs) + amount=$(echo "$amount" | xargs) + + # Check if the balance is equal to the amount + assert_equal "$receiverBalance" "$amount" +} diff --git a/test/bridge-e2e.bats b/test/bridge-e2e.bats new file mode 100644 index 00000000..98443b3b --- /dev/null +++ b/test/bridge-e2e.bats @@ -0,0 +1,71 @@ +setup() { + load 'helpers/common-setup' + _common_setup + + readonly data_availability_mode=${DATA_AVAILABILITY_MODE:-"cdk-validium"} + $PROJECT_ROOT/test/scripts/kurtosis_prepare_params_yml.sh ../kurtosis-cdk $data_availability_mode + [ $? -ne 0 ] && echo "Error preparing params.yml" && exit 1 + + # Check if the genesis file is already downloaded + if [ ! -f "./tmp/cdk/genesis/genesis.json" ]; then + mkdir -p ./tmp/cdk + kurtosis files download cdk-v1 genesis ./tmp/cdk/genesis + [ $? -ne 0 ] && echo "Error downloading genesis file" && exit 1 + fi + # Download the genesis file + readonly bridge_default_address=$(jq -r ".genesis[] | select(.contractName == \"PolygonZkEVMBridge proxy\") | .address" ./tmp/cdk/genesis/genesis.json) + + readonly skey=${SENDER_PRIVATE_KEY:-"12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"} + readonly destination_net=${DESTINATION_NET:-"1"} + readonly destination_addr=${DESTINATION_ADDRESS:-"0x0bb7AA0b4FdC2D2862c088424260e99ed6299148"} + readonly ether_value=${ETHER_VALUE:-"0.0200000054"} + readonly token_addr=${TOKEN_ADDRESS:-"0x0000000000000000000000000000000000000000"} + readonly is_forced=${IS_FORCED:-"true"} + readonly bridge_addr=${BRIDGE_ADDRESS:-$bridge_default_address} + readonly meta_bytes=${META_BYTES:-"0x"} + + readonly l1_rpc_url=${L1_ETH_RPC_URL:-"$(kurtosis port print cdk-v1 el-1-geth-lighthouse rpc)"} + readonly l2_rpc_url=${L2_ETH_RPC_URL:-"$(kurtosis port print cdk-v1 cdk-erigon-node-001 http-rpc)"} + readonly bridge_api_url=${BRIDGE_API_URL:-"$(kurtosis port print cdk-v1 zkevm-bridge-service-001 rpc)"} + + readonly dry_run=${DRY_RUN:-"false"} + + readonly amount=$(cast to-wei $ether_value ether) + readonly current_addr="$(cast wallet address --private-key $skey)" + readonly l1_rpc_network_id=$(cast call --rpc-url $l1_rpc_url $bridge_addr 'networkID()(uint32)') + readonly l2_rpc_network_id=$(cast call --rpc-url $l2_rpc_url $bridge_addr 'networkID()(uint32)') +} + +@test "Run deposit" { + load 'helpers/lxly-bridge-test' + echo "Running LxLy deposit" >&3 + run deposit + assert_success + assert_output --partial 'transactionHash' +} + +@test "Run claim" { + load 'helpers/lxly-bridge-test' + echo "Running LxLy claim" + + # The script timeout (in seconds). + timeout="120" + start_time=$(date +%s) + end_time=$((start_time + timeout)) + + while true; do + current_time=$(date +%s) + if ((current_time > end_time)); then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ❌ Exiting... Timeout reached!" + exit 1 + fi + + run claim + if [ $status -eq 0 ]; then + break + fi + sleep 10 + done + + assert_success +} diff --git a/test/config/test.kurtosis_template.toml b/test/config/test.kurtosis_template.toml index 62bffeb8..66471c6a 100644 --- a/test/config/test.kurtosis_template.toml +++ b/test/config/test.kurtosis_template.toml @@ -71,7 +71,6 @@ AggLayerTxTimeout = "5m" AggLayerURL = "" MaxWitnessRetrievalWorkers = 2 SyncModeOnlyEnabled = false -UseFullWitness = false SequencerPrivateKey = {} [Aggregator.DB] Name = "aggregator_db" diff --git a/test/contracts/erc20mock/ERC20Mock.json b/test/contracts/erc20mock/ERC20Mock.json new file mode 100644 index 00000000..e27ddd00 --- /dev/null +++ b/test/contracts/erc20mock/ERC20Mock.json @@ -0,0 +1,657 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MockERC20", + "sourceName": "contracts/mocks/MockERC20.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60806040523480156200001157600080fd5b50604080518082018252600480825263151154d560e21b60208084018290528451808601909552918452908301529081816005620000508382620002ca565b5060066200005f8282620002ca565b50506007805460ff191690555062000079600033620000d9565b620000a57f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633620000d9565b620000d17f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620000d9565b505062000396565b620000e58282620000e9565b5050565b620000f5828262000114565b60008281526001602052604090206200010f9082620001b4565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000e5576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001703390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001cb836001600160a01b038416620001d4565b90505b92915050565b60008181526001830160205260408120546200021d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001ce565b506000620001ce565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200025157607f821691505b6020821081036200027257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200010f57600081815260208120601f850160051c81016020861015620002a15750805b601f850160051c820191505b81811015620002c257828155600101620002ad565b505050505050565b81516001600160401b03811115620002e657620002e662000226565b620002fe81620002f784546200023c565b8462000278565b602080601f8311600181146200033657600084156200031d5750858301515b600019600386901b1c1916600185901b178555620002c2565b600085815260208120601f198616915b82811015620003675788860151825594840194600190910190840162000346565b5085821015620003865787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6117fa80620003a66000396000f3fe608060405234801561001057600080fd5b50600436106101845760003560e01c806370a08231116100d9578063a457c2d711610087578063a457c2d714610336578063a9059cbb14610349578063ca15c8731461035c578063d53913931461036f578063d547741f14610396578063dd62ed3e146103a9578063e63ab1e9146103bc57600080fd5b806370a08231146102a457806379cc6790146102cd5780638456cb59146102e05780639010d07c146102e857806391d148541461031357806395d89b4114610326578063a217fddf1461032e57600080fd5b8063313ce56711610136578063313ce5671461023657806336568abe1461024557806339509351146102585780633f4ba83a1461026b57806340c10f191461027357806342966c68146102865780635c975abb1461029957600080fd5b806301ffc9a71461018957806306fdde03146101b1578063095ea7b3146101c657806318160ddd146101d957806323b872dd146101eb578063248a9ca3146101fe5780632f2ff15d14610221575b600080fd5b61019c610197366004611460565b6103d1565b60405190151581526020015b60405180910390f35b6101b96103fc565b6040516101a891906114ae565b61019c6101d43660046114fd565b61048e565b6004545b6040519081526020016101a8565b61019c6101f9366004611527565b6104a6565b6101dd61020c366004611563565b60009081526020819052604090206001015490565b61023461022f36600461157c565b6104ca565b005b604051601281526020016101a8565b61023461025336600461157c565b6104f4565b61019c6102663660046114fd565b610577565b610234610599565b6102346102813660046114fd565b610617565b610234610294366004611563565b6106a4565b60075460ff1661019c565b6101dd6102b23660046115a8565b6001600160a01b031660009081526002602052604090205490565b6102346102db3660046114fd565b6106b1565b6102346106c6565b6102fb6102f63660046115c3565b610740565b6040516001600160a01b0390911681526020016101a8565b61019c61032136600461157c565b61075f565b6101b9610788565b6101dd600081565b61019c6103443660046114fd565b610797565b61019c6103573660046114fd565b610812565b6101dd61036a366004611563565b610820565b6101dd7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102346103a436600461157c565b610837565b6101dd6103b73660046115e5565b61085c565b6101dd60008051602061178583398151915281565b60006001600160e01b03198216635a05180f60e01b14806103f657506103f682610887565b92915050565b60606005805461040b9061160f565b80601f01602080910402602001604051908101604052809291908181526020018280546104379061160f565b80156104845780601f1061045957610100808354040283529160200191610484565b820191906000526020600020905b81548152906001019060200180831161046757829003601f168201915b5050505050905090565b60003361049c8185856108bc565b5060019392505050565b6000336104b48582856109e0565b6104bf858585610a5a565b506001949350505050565b6000828152602081905260409020600101546104e581610bfe565b6104ef8383610c08565b505050565b6001600160a01b03811633146105695760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105738282610c2a565b5050565b60003361049c81858561058a838361085c565b610594919061165f565b6108bc565b6105b16000805160206117858339815191523361075f565b61060d5760405162461bcd60e51b8152602060048201526039602482015260008051602061176583398151915260448201527876652070617573657220726f6c6520746f20756e706175736560381b6064820152608401610560565b610615610c4c565b565b6106417f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63361075f565b61069a5760405162461bcd60e51b815260206004820152603660248201526000805160206117658339815191526044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b6064820152608401610560565b6105738282610c9e565b6106ae3382610d59565b50565b6106bc8233836109e0565b6105738282610d59565b6106de6000805160206117858339815191523361075f565b6107385760405162461bcd60e51b8152602060048201526037602482015260008051602061176583398151915260448201527676652070617573657220726f6c6520746f20706175736560481b6064820152608401610560565b610615610e87565b60008281526001602052604081206107589083610ec4565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606006805461040b9061160f565b600033816107a5828661085c565b9050838110156108055760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610560565b6104bf82868684036108bc565b60003361049c818585610a5a565b60008181526001602052604081206103f690610ed0565b60008281526020819052604090206001015461085281610bfe565b6104ef8383610c2a565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b60006001600160e01b03198216637965db0b60e01b14806103f657506301ffc9a760e01b6001600160e01b03198316146103f6565b6001600160a01b03831661091e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610560565b6001600160a01b03821661097f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610560565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006109ec848461085c565b90506000198114610a545781811015610a475760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610560565b610a5484848484036108bc565b50505050565b6001600160a01b038316610abe5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610560565b6001600160a01b038216610b205760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610560565b610b2b838383610eda565b6001600160a01b03831660009081526002602052604090205481811015610ba35760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610560565b6001600160a01b0380851660008181526002602052604080822086860390559286168082529083902080548601905591516000805160206117a583398151915290610bf19086815260200190565b60405180910390a3610a54565b6106ae8133610ee5565b610c128282610f3e565b60008281526001602052604090206104ef9082610fc2565b610c348282610fd7565b60008281526001602052604090206104ef908261103c565b610c54611051565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610cf45760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610560565b610d0060008383610eda565b8060046000828254610d12919061165f565b90915550506001600160a01b0382166000818152600260209081526040808320805486019055518481526000805160206117a5833981519152910160405180910390a35050565b6001600160a01b038216610db95760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610560565b610dc582600083610eda565b6001600160a01b03821660009081526002602052604090205481811015610e395760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610560565b6001600160a01b03831660008181526002602090815260408083208686039055600480548790039055518581529192916000805160206117a5833981519152910160405180910390a3505050565b610e8f61109a565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610c813390565b600061075883836110e0565b60006103f6825490565b6104ef83838361110a565b610eef828261075f565b61057357610efc81611170565b610f07836020611182565b604051602001610f18929190611672565b60408051601f198184030181529082905262461bcd60e51b8252610560916004016114ae565b610f48828261075f565b610573576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610f7e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610758836001600160a01b03841661131e565b610fe1828261075f565b15610573576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610758836001600160a01b03841661136d565b60075460ff166106155760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610560565b60075460ff16156106155760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610560565b60008260000182815481106110f7576110f76116e1565b9060005260206000200154905092915050565b60075460ff16156104ef5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610560565b60606103f66001600160a01b03831660145b606060006111918360026116f7565b61119c90600261165f565b67ffffffffffffffff8111156111b4576111b461170e565b6040519080825280601f01601f1916602001820160405280156111de576020820181803683370190505b509050600360fc1b816000815181106111f9576111f96116e1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611228576112286116e1565b60200101906001600160f81b031916908160001a905350600061124c8460026116f7565b61125790600161165f565b90505b60018111156112cf576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061128b5761128b6116e1565b1a60f81b8282815181106112a1576112a16116e1565b60200101906001600160f81b031916908160001a90535060049490941c936112c881611724565b905061125a565b5083156107585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610560565b6000818152600183016020526040812054611365575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556103f6565b5060006103f6565b6000818152600183016020526040812054801561145657600061139160018361173b565b85549091506000906113a59060019061173b565b905081811461140a5760008660000182815481106113c5576113c56116e1565b90600052602060002001549050808760000184815481106113e8576113e86116e1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061141b5761141b61174e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506103f6565b60009150506103f6565b60006020828403121561147257600080fd5b81356001600160e01b03198116811461075857600080fd5b60005b838110156114a557818101518382015260200161148d565b50506000910152565b60208152600082518060208401526114cd81604085016020870161148a565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146114f857600080fd5b919050565b6000806040838503121561151057600080fd5b611519836114e1565b946020939093013593505050565b60008060006060848603121561153c57600080fd5b611545846114e1565b9250611553602085016114e1565b9150604084013590509250925092565b60006020828403121561157557600080fd5b5035919050565b6000806040838503121561158f57600080fd5b8235915061159f602084016114e1565b90509250929050565b6000602082840312156115ba57600080fd5b610758826114e1565b600080604083850312156115d657600080fd5b50508035926020909101359150565b600080604083850312156115f857600080fd5b611601836114e1565b915061159f602084016114e1565b600181811c9082168061162357607f821691505b60208210810361164357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103f6576103f6611649565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516116a481601785016020880161148a565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516116d581602884016020880161148a565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176103f6576103f6611649565b634e487b7160e01b600052604160045260246000fd5b60008161173357611733611649565b506000190190565b818103818111156103f6576103f6611649565b634e487b7160e01b600052603160045260246000fdfe45524332305072657365744d696e7465725061757365723a206d75737420686165d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220d5a22b9391b8f37e5b49e43cc1eabfcea8be6d7b5aa0a84dc5daa1b7a05730f364736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101845760003560e01c806370a08231116100d9578063a457c2d711610087578063a457c2d714610336578063a9059cbb14610349578063ca15c8731461035c578063d53913931461036f578063d547741f14610396578063dd62ed3e146103a9578063e63ab1e9146103bc57600080fd5b806370a08231146102a457806379cc6790146102cd5780638456cb59146102e05780639010d07c146102e857806391d148541461031357806395d89b4114610326578063a217fddf1461032e57600080fd5b8063313ce56711610136578063313ce5671461023657806336568abe1461024557806339509351146102585780633f4ba83a1461026b57806340c10f191461027357806342966c68146102865780635c975abb1461029957600080fd5b806301ffc9a71461018957806306fdde03146101b1578063095ea7b3146101c657806318160ddd146101d957806323b872dd146101eb578063248a9ca3146101fe5780632f2ff15d14610221575b600080fd5b61019c610197366004611460565b6103d1565b60405190151581526020015b60405180910390f35b6101b96103fc565b6040516101a891906114ae565b61019c6101d43660046114fd565b61048e565b6004545b6040519081526020016101a8565b61019c6101f9366004611527565b6104a6565b6101dd61020c366004611563565b60009081526020819052604090206001015490565b61023461022f36600461157c565b6104ca565b005b604051601281526020016101a8565b61023461025336600461157c565b6104f4565b61019c6102663660046114fd565b610577565b610234610599565b6102346102813660046114fd565b610617565b610234610294366004611563565b6106a4565b60075460ff1661019c565b6101dd6102b23660046115a8565b6001600160a01b031660009081526002602052604090205490565b6102346102db3660046114fd565b6106b1565b6102346106c6565b6102fb6102f63660046115c3565b610740565b6040516001600160a01b0390911681526020016101a8565b61019c61032136600461157c565b61075f565b6101b9610788565b6101dd600081565b61019c6103443660046114fd565b610797565b61019c6103573660046114fd565b610812565b6101dd61036a366004611563565b610820565b6101dd7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102346103a436600461157c565b610837565b6101dd6103b73660046115e5565b61085c565b6101dd60008051602061178583398151915281565b60006001600160e01b03198216635a05180f60e01b14806103f657506103f682610887565b92915050565b60606005805461040b9061160f565b80601f01602080910402602001604051908101604052809291908181526020018280546104379061160f565b80156104845780601f1061045957610100808354040283529160200191610484565b820191906000526020600020905b81548152906001019060200180831161046757829003601f168201915b5050505050905090565b60003361049c8185856108bc565b5060019392505050565b6000336104b48582856109e0565b6104bf858585610a5a565b506001949350505050565b6000828152602081905260409020600101546104e581610bfe565b6104ef8383610c08565b505050565b6001600160a01b03811633146105695760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105738282610c2a565b5050565b60003361049c81858561058a838361085c565b610594919061165f565b6108bc565b6105b16000805160206117858339815191523361075f565b61060d5760405162461bcd60e51b8152602060048201526039602482015260008051602061176583398151915260448201527876652070617573657220726f6c6520746f20756e706175736560381b6064820152608401610560565b610615610c4c565b565b6106417f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63361075f565b61069a5760405162461bcd60e51b815260206004820152603660248201526000805160206117658339815191526044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b6064820152608401610560565b6105738282610c9e565b6106ae3382610d59565b50565b6106bc8233836109e0565b6105738282610d59565b6106de6000805160206117858339815191523361075f565b6107385760405162461bcd60e51b8152602060048201526037602482015260008051602061176583398151915260448201527676652070617573657220726f6c6520746f20706175736560481b6064820152608401610560565b610615610e87565b60008281526001602052604081206107589083610ec4565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606006805461040b9061160f565b600033816107a5828661085c565b9050838110156108055760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610560565b6104bf82868684036108bc565b60003361049c818585610a5a565b60008181526001602052604081206103f690610ed0565b60008281526020819052604090206001015461085281610bfe565b6104ef8383610c2a565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b60006001600160e01b03198216637965db0b60e01b14806103f657506301ffc9a760e01b6001600160e01b03198316146103f6565b6001600160a01b03831661091e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610560565b6001600160a01b03821661097f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610560565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006109ec848461085c565b90506000198114610a545781811015610a475760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610560565b610a5484848484036108bc565b50505050565b6001600160a01b038316610abe5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610560565b6001600160a01b038216610b205760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610560565b610b2b838383610eda565b6001600160a01b03831660009081526002602052604090205481811015610ba35760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610560565b6001600160a01b0380851660008181526002602052604080822086860390559286168082529083902080548601905591516000805160206117a583398151915290610bf19086815260200190565b60405180910390a3610a54565b6106ae8133610ee5565b610c128282610f3e565b60008281526001602052604090206104ef9082610fc2565b610c348282610fd7565b60008281526001602052604090206104ef908261103c565b610c54611051565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610cf45760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610560565b610d0060008383610eda565b8060046000828254610d12919061165f565b90915550506001600160a01b0382166000818152600260209081526040808320805486019055518481526000805160206117a5833981519152910160405180910390a35050565b6001600160a01b038216610db95760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610560565b610dc582600083610eda565b6001600160a01b03821660009081526002602052604090205481811015610e395760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610560565b6001600160a01b03831660008181526002602090815260408083208686039055600480548790039055518581529192916000805160206117a5833981519152910160405180910390a3505050565b610e8f61109a565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610c813390565b600061075883836110e0565b60006103f6825490565b6104ef83838361110a565b610eef828261075f565b61057357610efc81611170565b610f07836020611182565b604051602001610f18929190611672565b60408051601f198184030181529082905262461bcd60e51b8252610560916004016114ae565b610f48828261075f565b610573576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610f7e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610758836001600160a01b03841661131e565b610fe1828261075f565b15610573576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610758836001600160a01b03841661136d565b60075460ff166106155760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610560565b60075460ff16156106155760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610560565b60008260000182815481106110f7576110f76116e1565b9060005260206000200154905092915050565b60075460ff16156104ef5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610560565b60606103f66001600160a01b03831660145b606060006111918360026116f7565b61119c90600261165f565b67ffffffffffffffff8111156111b4576111b461170e565b6040519080825280601f01601f1916602001820160405280156111de576020820181803683370190505b509050600360fc1b816000815181106111f9576111f96116e1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611228576112286116e1565b60200101906001600160f81b031916908160001a905350600061124c8460026116f7565b61125790600161165f565b90505b60018111156112cf576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061128b5761128b6116e1565b1a60f81b8282815181106112a1576112a16116e1565b60200101906001600160f81b031916908160001a90535060049490941c936112c881611724565b905061125a565b5083156107585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610560565b6000818152600183016020526040812054611365575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556103f6565b5060006103f6565b6000818152600183016020526040812054801561145657600061139160018361173b565b85549091506000906113a59060019061173b565b905081811461140a5760008660000182815481106113c5576113c56116e1565b90600052602060002001549050808760000184815481106113e8576113e86116e1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061141b5761141b61174e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506103f6565b60009150506103f6565b60006020828403121561147257600080fd5b81356001600160e01b03198116811461075857600080fd5b60005b838110156114a557818101518382015260200161148d565b50506000910152565b60208152600082518060208401526114cd81604085016020870161148a565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146114f857600080fd5b919050565b6000806040838503121561151057600080fd5b611519836114e1565b946020939093013593505050565b60008060006060848603121561153c57600080fd5b611545846114e1565b9250611553602085016114e1565b9150604084013590509250925092565b60006020828403121561157557600080fd5b5035919050565b6000806040838503121561158f57600080fd5b8235915061159f602084016114e1565b90509250929050565b6000602082840312156115ba57600080fd5b610758826114e1565b600080604083850312156115d657600080fd5b50508035926020909101359150565b600080604083850312156115f857600080fd5b611601836114e1565b915061159f602084016114e1565b600181811c9082168061162357607f821691505b60208210810361164357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103f6576103f6611649565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516116a481601785016020880161148a565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516116d581602884016020880161148a565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176103f6576103f6611649565b634e487b7160e01b600052604160045260246000fd5b60008161173357611733611649565b506000190190565b818103818111156103f6576103f6611649565b634e487b7160e01b600052603160045260246000fdfe45524332305072657365744d696e7465725061757365723a206d75737420686165d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220d5a22b9391b8f37e5b49e43cc1eabfcea8be6d7b5aa0a84dc5daa1b7a05730f364736f6c63430008130033", + "linkReferences": {}, + "deployedLinkReferences": {} + } + \ No newline at end of file diff --git a/test/e2e.bats b/test/e2e.bats new file mode 100644 index 00000000..c85e33ce --- /dev/null +++ b/test/e2e.bats @@ -0,0 +1,10 @@ +setup() { + load 'helpers/common-setup' + _common_setup +} + +@test "Verify batches" { + echo "Waiting 10 minutes to get some verified batch...." + run $PROJECT_ROOT/test/scripts/batch_verification_monitor.sh 0 600 + assert_success +} diff --git a/test/helpers/aggoracle_e2e.go b/test/helpers/aggoracle_e2e.go index b7bb504c..8b5073fb 100644 --- a/test/helpers/aggoracle_e2e.go +++ b/test/helpers/aggoracle_e2e.go @@ -64,7 +64,7 @@ func SetupAggoracleWithEVMChain(t *testing.T) *AggoracleWithEVMChainEnv { ctx := context.Background() l1Client, syncer, gerL1Contract, gerL1Addr, bridgeL1Contract, bridgeL1Addr, authL1, rd := CommonSetup(t) sender, l2Client, gerL2Contract, gerL2Addr, bridgeL2Contract, bridgeL2Addr, authL2, ethTxManMockL2 := EVMSetup(t) - oracle, err := aggoracle.New(log.GetDefaultLogger(), sender, l1Client.Client(), syncer, etherman.LatestBlock, time.Millisecond*20) //nolint:gomnd + oracle, err := aggoracle.New(log.GetDefaultLogger(), sender, l1Client.Client(), syncer, etherman.LatestBlock, time.Millisecond*20) //nolint:mnd require.NoError(t, err) go oracle.Start(ctx) @@ -144,7 +144,7 @@ func EVMSetup(t *testing.T) ( require.NoError(t, err) ethTxManMock := NewEthTxManMock(t, l2Client, authL2) sender, err := chaingersender.NewEVMChainGERSender(log.GetDefaultLogger(), - gerL2Addr, authL2.From, l2Client.Client(), ethTxManMock, 0, time.Millisecond*50) //nolint:gomnd + gerL2Addr, authL2.From, l2Client.Client(), ethTxManMock, 0, time.Millisecond*50) //nolint:mnd require.NoError(t, err) return sender, l2Client, gerL2Sc, gerL2Addr, bridgeL2Sc, bridgeL2Addr, authL2, ethTxManMock @@ -170,7 +170,7 @@ func newSimulatedL1(auth *bind.TransactOpts) ( return nil, common.Address{}, nil, common.Address{}, nil, fmt.Errorf("failed to create transactor: %w", err) } - balance, _ := new(big.Int).SetString(initialBalance, 10) //nolint:gomnd + balance, _ := new(big.Int).SetString(initialBalance, 10) //nolint:mnd address := auth.From genesisAlloc := map[common.Address]types.Account{ address: { @@ -279,7 +279,7 @@ func newSimulatedEVMAggSovereignChain(auth *bind.TransactOpts) ( return nil, common.Address{}, nil, common.Address{}, nil, fmt.Errorf("failed to create transactor: %w", err) } - balance, _ := new(big.Int).SetString(initialBalance, 10) //nolint:gomnd + balance, _ := new(big.Int).SetString(initialBalance, 10) //nolint:mnd address := auth.From precalculatedBridgeAddr := crypto.CreateAddress(authDeployer.From, 1) diff --git a/test/helpers/common-setup.bash b/test/helpers/common-setup.bash new file mode 100644 index 00000000..b7691366 --- /dev/null +++ b/test/helpers/common-setup.bash @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +_common_setup() { + bats_load_library 'bats-support' + bats_load_library 'bats-assert' + + # get the containing directory of this file + # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0, + # as those will point to the bats executable's location or the preprocessed file respectively + PROJECT_ROOT="$( cd "$( dirname "$BATS_TEST_FILENAME" )/.." >/dev/null 2>&1 && pwd )" + # make executables in src/ visible to PATH + PATH="$PROJECT_ROOT/src:$PATH" +} diff --git a/test/helpers/common.bash b/test/helpers/common.bash new file mode 100644 index 00000000..709bf843 --- /dev/null +++ b/test/helpers/common.bash @@ -0,0 +1,187 @@ +#!/usr/bin/env bash + +function deployContract() { + local private_key="$1" + local contract_artifact="$2" + + # Check if rpc_url is available + if [[ -z "$rpc_url" ]]; then + echo "Error: rpc_url environment variable is not set." + return 1 + fi + + if [[ ! -f "$contract_artifact" ]]; then + echo "Error: Contract artifact '$contract_artifact' does not exist." + return 1 + fi + + # Get the sender address + local senderAddr=$(cast wallet address "$private_key") + if [[ $? -ne 0 ]]; then + echo "Error: Failed to retrieve sender address." + return 1 + fi + + echo "Attempting to deploy contract artifact '$contract_artifact' to $rpc_url (sender: $senderAddr)" >&3 + + # Get bytecode from the contract artifact + local bytecode=$(jq -r .bytecode "$contract_artifact") + if [[ -z "$bytecode" || "$bytecode" == "null" ]]; then + echo "Error: Failed to read bytecode from $contract_artifact" + return 1 + fi + + # Send the transaction and capture the output + local cast_output=$(cast send --rpc-url "$rpc_url" \ + --private-key "$private_key" \ + --legacy \ + --create "$bytecode" \ + 2>&1) + + # Check if cast send was successful + if [[ $? -ne 0 ]]; then + echo "Error: Failed to send transaction." + echo "$cast_output" + return 1 + fi + + echo "Deploy contract output:" >&3 + echo "$cast_output" >&3 + + # Extract the contract address from the output + local deployed_contract_address=$(echo "$cast_output" | grep 'contractAddress' | sed 's/contractAddress\s\+//') + echo "Deployed contract address: $deployed_contract_address" >&3 + + if [[ -z "$deployed_contract_address" ]]; then + echo "Error: Failed to extract deployed contract address" + return 1 + fi + + if [[ ! "$deployed_contract_address" =~ ^0x[a-fA-F0-9]{40}$ ]]; then + echo "Error: Invalid contract address $deployed_contract_address" + return 1 + fi + + # Print contract address for return + echo "$deployed_contract_address" + + return 0 +} + +function sendTx() { + # Check if at least 3 arguments are provided + if [[ $# -lt 3 ]]; then + echo "Usage: sendTx [ ...]" + return 1 + fi + + local private_key="$1" # Sender private key + local account_addr="$2" # Receiver address + local value_or_function_sig="$3" # Value or function signature + + # Error handling: Ensure the receiver is a valid Ethereum address + if [[ ! "$account_addr" =~ ^0x[a-fA-F0-9]{40}$ ]]; then + echo "Error: Invalid receiver address '$account_addr'." + return 1 + fi + + shift 3 # Shift the first 3 arguments (private_key, account_addr, value_or_function_sig) + + local senderAddr + senderAddr=$(cast wallet address "$private_key") + if [[ $? -ne 0 ]]; then + echo "Error: Failed to extract the sender address for $private_key" + return 1 + fi + + # Check if the first remaining argument is a numeric value (Ether to be transferred) + if [[ "$value_or_function_sig" =~ ^[0-9]+(ether)?$ ]]; then + # Case: EOA transaction (Ether transfer) + echo "Sending EOA transaction (RPC URL: $rpc_url, sender: $senderAddr) to: $account_addr " \ + "with value: $value_or_function_sig" >&3 + + cast_output=$(cast send --rpc-url "$rpc_url" \ + --private-key "$private_key" \ + "$account_addr" --value "$value_or_function_sig" \ + --legacy \ + 2>&1) + else + # Case: Smart contract transaction (contract interaction with function signature and parameters) + local params=("$@") # Collect all remaining arguments as function parameters + + echo "Function signature: '$value_or_function_sig'" >&3 + + # Verify if the function signature starts with "function" + if [[ ! "$value_or_function_sig" =~ ^function\ .+\(.+\)$ ]]; then + echo "Error: Invalid function signature format '$value_or_function_sig'." + return 1 + fi + + echo "Sending smart contract transaction (RPC URL: $rpc_url, sender: $senderAddr) to $account_addr" \ + "with function signature: '$value_or_function_sig' and params: ${params[*]}" >&3 + + # Send the smart contract interaction using cast + cast_output=$(cast send --rpc-url "$rpc_url" \ + --private-key "$private_key" \ + "$account_addr" "$value_or_function_sig" "${params[@]}" \ + --legacy \ + 2>&1) + fi + + # Check if the transaction was successful + if [[ $? -ne 0 ]]; then + echo "Error: Failed to send transaction. The cast send output:" + echo "$cast_output" + return 1 + fi + + # Extract the transaction hash from the output + local tx_hash=$(echo "$cast_output" | grep 'transactionHash' | awk '{print $2}' | tail -n 1) + echo "Tx hash: $tx_hash" + + if [[ -z "$tx_hash" ]]; then + echo "Error: Failed to extract transaction hash." + return 1 + fi + + echo "Transaction successful (transaction hash: $tx_hash)" + + return 0 +} + +function queryContract() { + local addr="$1" # Contract address + local funcSignature="$2" # Function signature + shift 2 # Shift past the first two arguments + local params=("$@") # Collect remaining arguments as parameters array + + echo "Querying state of $addr account (RPC URL: $rpc_url) with function signature: '$funcSignature' and params: ${params[*]}" >&3 + + # Check if rpc_url is available + if [[ -z "$rpc_url" ]]; then + echo "Error: rpc_url environment variable is not set." + return 1 + fi + + # Check if the contract address is valid + if [[ ! "$addr" =~ ^0x[a-fA-F0-9]{40}$ ]]; then + echo "Error: Invalid contract address '$addr'." + return 1 + fi + + # Call the contract using `cast call` + local result + result=$(cast call --rpc-url "$rpc_url" "$addr" "$funcSignature" "${params[@]}" 2>&1) + + # Check if the call was successful + if [[ $? -ne 0 ]]; then + echo "Error: Failed to query contract." + echo "$result" + return 1 + fi + + # Return the result (contract query response) + echo "$result" + + return 0 +} diff --git a/test/helpers/lxly-bridge-test.bash b/test/helpers/lxly-bridge-test.bash new file mode 100644 index 00000000..bbaf45e1 --- /dev/null +++ b/test/helpers/lxly-bridge-test.bash @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Error code reference https://hackmd.io/WwahVBZERJKdfK3BbKxzQQ +function deposit () { + readonly deposit_sig='bridgeAsset(uint32,address,uint256,address,bool,bytes)' + + if [[ $token_addr == "0x0000000000000000000000000000000000000000" ]]; then + echo "Checking the current ETH balance: " >&3 + cast balance -e --rpc-url $l1_rpc_url $current_addr >&3 + else + echo "Checking the current token balance for token at $token_addr: " >&3 + cast call --rpc-url $l1_rpc_url $token_addr 'balanceOf(address)(uint256)' $current_addr >&3 + fi + + echo "Attempting to deposit $amount wei to net $destination_net for token $token_addr" >&3 + + if [[ $dry_run == "true" ]]; then + cast calldata $deposit_sig $destination_net $destination_addr $amount $token_addr $is_forced $meta_bytes + else + if [[ $token_addr == "0x0000000000000000000000000000000000000000" ]]; then + cast send --legacy --private-key $skey --value $amount --rpc-url $l1_rpc_url $bridge_addr $deposit_sig $destination_net $destination_addr $amount $token_addr $is_forced $meta_bytes + else + cast send --legacy --private-key $skey --rpc-url $l1_rpc_url $bridge_addr $deposit_sig $destination_net $destination_addr $amount $token_addr $is_forced $meta_bytes + fi + fi +} + +function claim() { + readonly claim_sig="claimAsset(bytes32[32],bytes32[32],uint256,bytes32,bytes32,uint32,address,uint32,address,uint256,bytes)" + readonly bridge_deposit_file=$(mktemp) + readonly claimable_deposit_file=$(mktemp) + echo "Getting full list of deposits" >&3 + curl -s "$bridge_api_url/bridges/$destination_addr?limit=100&offset=0" | jq '.' | tee $bridge_deposit_file + + echo "Looking for claimable deposits" >&3 + jq '[.deposits[] | select(.ready_for_claim == true and .claim_tx_hash == "" and .dest_net == '$destination_net')]' $bridge_deposit_file | tee $claimable_deposit_file + readonly claimable_count=$(jq '. | length' $claimable_deposit_file) + echo "Found $claimable_count claimable deposits" >&3 + + if [[ $claimable_count == 0 ]]; then + echo "We have no claimable deposits at this time" >&3 + exit 1 + fi + + echo "We have $claimable_count claimable deposits on network $destination_net. Let's get this party started." >&3 + readonly current_deposit=$(mktemp) + readonly current_proof=$(mktemp) + while read deposit_idx; do + echo "Starting claim for tx index: "$deposit_idx >&3 + echo "Deposit info:" >&3 + jq --arg idx $deposit_idx '.[($idx | tonumber)]' $claimable_deposit_file | tee $current_deposit >&3 + + curr_deposit_cnt=$(jq -r '.deposit_cnt' $current_deposit) + curr_network_id=$(jq -r '.network_id' $current_deposit) + curl -s "$bridge_api_url/merkle-proof?deposit_cnt=$curr_deposit_cnt&net_id=$curr_network_id" | jq '.' | tee $current_proof + + in_merkle_proof="$(jq -r -c '.proof.merkle_proof' $current_proof | tr -d '"')" + in_rollup_merkle_proof="$(jq -r -c '.proof.rollup_merkle_proof' $current_proof | tr -d '"')" + in_global_index=$(jq -r '.global_index' $current_deposit) + in_main_exit_root=$(jq -r '.proof.main_exit_root' $current_proof) + in_rollup_exit_root=$(jq -r '.proof.rollup_exit_root' $current_proof) + in_orig_net=$(jq -r '.orig_net' $current_deposit) + in_orig_addr=$(jq -r '.orig_addr' $current_deposit) + in_dest_net=$(jq -r '.dest_net' $current_deposit) + in_dest_addr=$(jq -r '.dest_addr' $current_deposit) + in_amount=$(jq -r '.amount' $current_deposit) + in_metadata=$(jq -r '.metadata' $current_deposit) + + if [[ $dry_run == "true" ]]; then + cast calldata $claim_sig "$in_merkle_proof" "$in_rollup_merkle_proof" $in_global_index $in_main_exit_root $in_rollup_exit_root $in_orig_net $in_orig_addr $in_dest_net $in_dest_addr $in_amount $in_metadata + cast call --rpc-url $l2_rpc_url $bridge_addr $claim_sig "$in_merkle_proof" "$in_rollup_merkle_proof" $in_global_index $in_main_exit_root $in_rollup_exit_root $in_orig_net $in_orig_addr $in_dest_net $in_dest_addr $in_amount $in_metadata + else + cast send --legacy --rpc-url $l2_rpc_url --private-key $skey $bridge_addr $claim_sig "$in_merkle_proof" "$in_rollup_merkle_proof" $in_global_index $in_main_exit_root $in_rollup_exit_root $in_orig_net $in_orig_addr $in_dest_net $in_dest_addr $in_amount $in_metadata + fi + + + done < <(seq 0 $((claimable_count - 1)) ) +} diff --git a/test/run-e2e.sh b/test/run-e2e.sh index a0db5d56..6a29e416 100755 --- a/test/run-e2e.sh +++ b/test/run-e2e.sh @@ -18,11 +18,8 @@ else echo "docker cdk:latest already exists" fi -$BASE_FOLDER/scripts/kurtosis_prepare_params_yml.sh "$KURTOSIS_FOLDER" "elderberry" "cdk-validium" +$BASE_FOLDER/scripts/kurtosis_prepare_params_yml.sh "$KURTOSIS_FOLDER" $DATA_AVAILABILITY_MODE [ $? -ne 0 ] && echo "Error preparing params.yml" && exit 1 kurtosis clean --all kurtosis run --enclave cdk-v1 --args-file $DEST_KURTOSIS_PARAMS_YML --image-download always $KURTOSIS_FOLDER -#[ $? -ne 0 ] && echo "Error running kurtosis" && exit 1 -echo "Waiting 10 minutes to get some verified batch...." -scripts/batch_verification_monitor.sh 0 600 diff --git a/test/scripts/env.sh b/test/scripts/env.sh index 184a85d4..b81c18a4 100644 --- a/test/scripts/env.sh +++ b/test/scripts/env.sh @@ -1,6 +1,7 @@ #!/bin/bash ### Common variables ENCLAVE=cdk-v1 +CDK_ERIGON_NODE_NAME=cdk-erigon-node-001 TMP_CDK_FOLDER=tmp/cdk DEST_KURTOSIS_PARAMS_YML=../$TMP_CDK_FOLDER/e2e-params.yml KURTOSIS_VERSION=develop diff --git a/test/scripts/kurtosis_prepare_params_yml.sh b/test/scripts/kurtosis_prepare_params_yml.sh index 66353606..aa57e272 100755 --- a/test/scripts/kurtosis_prepare_params_yml.sh +++ b/test/scripts/kurtosis_prepare_params_yml.sh @@ -6,18 +6,19 @@ if [ -z $DEST_KURTOSIS_PARAMS_YML ]; then exit 1 fi +# Check if the destination params file exists and don't do nothing +if [ -f $DEST_KURTOSIS_PARAMS_YML ]; then + echo "Destination params file already exists" + exit 0 +fi + KURTOSIS_FOLDER=$1 if [ -z $KURTOSIS_FOLDER ]; then echo "Missing param Kurtosis Folder" exit 1 fi -FORK_NAME=$2 -if [ -z $FORK_NAME ]; then - echo "Missing param Fork Name" - exit 1 -fi -DATA_AVAILABILITY_MODE=$3 +DATA_AVAILABILITY_MODE=$2 if [ -z $DATA_AVAILABILITY_MODE ]; then echo "Missing param Data Availability Mode : [rollup, cdk-validium]" exit 1 @@ -25,5 +26,5 @@ fi mkdir -p $(dirname $DEST_KURTOSIS_PARAMS_YML) cp $KURTOSIS_FOLDER/params.yml $DEST_KURTOSIS_PARAMS_YML +yq -Y --in-place ".args.cdk_node_image = \"cdk\"" $DEST_KURTOSIS_PARAMS_YML yq -Y --in-place ".args.data_availability_mode = \"$DATA_AVAILABILITY_MODE\"" $DEST_KURTOSIS_PARAMS_YML -yq -Y --in-place ".args.zkevm_sequence_sender_image = \"cdk:latest\"" $DEST_KURTOSIS_PARAMS_YML diff --git a/tree/testvectors/types.go b/tree/testvectors/types.go index af3c7519..27bc1abb 100644 --- a/tree/testvectors/types.go +++ b/tree/testvectors/types.go @@ -21,9 +21,9 @@ type DepositVectorRaw struct { } func (d *DepositVectorRaw) Hash() common.Hash { - origNet := make([]byte, 4) //nolint:gomnd + origNet := make([]byte, 4) //nolint:mnd binary.BigEndian.PutUint32(origNet, d.OriginNetwork) - destNet := make([]byte, 4) //nolint:gomnd + destNet := make([]byte, 4) //nolint:mnd binary.BigEndian.PutUint32(destNet, d.DestinationNetwork) metaHash := keccak256.Hash(common.FromHex(d.Metadata))