From c6474133b52af8d32c08f9e91704fa39f80f7657 Mon Sep 17 00:00:00 2001
From: Victor Castell <victor@polygon.technology>
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 e644f97b4..bdad36b2f 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 670ce8b37..b20bb982a 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 5dd6e0ecd..98197d744 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 7f8ff33b4..c653ec1e0 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 edbddd778..1ba94d7a8 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 6c033f9f3..a97d72f9a 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 225cedb9c..f05799eb0 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 cd6df050b..8cb13b1d5 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 30eb91233..fbcdca732 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 1eb86839a..773c5e245 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 71e06a04b..c11bd083f 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 bb74984c7..01b96a13f 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 c4fd93876..a2d748e7b 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 7e5b1d016..c7e1f860c 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 120ba6c63..5a33f5a32 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 38d663812..f3ad6d36e 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 781d44787..c76d7aac7 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 049b2847e..628ea04ab 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 201c87908..b6d9d1cc4 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 9d33bcd01..9a596608d 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 1fd6feecc..7926df60a 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 77189b208..e264807a5 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 22c4693ef..7a995bac0 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 cd0d6855a..23c674098 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 21b5834e8..5d903dc5d 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 263e729b7..3431d3fe5 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 a48efd234..7b451ed82 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 5386e2876..af4b05c04 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 905aa8551..f9a6275db 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 14a0bddfe..35173d8e6 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 dff4636e7..66eb94461 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 30b16d233..d263b5c79 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 aeedb8fe3..7f2b64be5 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 a5ae6331d..fa32fc99c 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 1e70d12f4..c9c4e6610 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 86bd147ef..0c50ec358 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 000000000..cbd845f56
--- /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 000000000..98443b3b1
--- /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 62bffeb85..66471c6ac 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 000000000..e27ddd001
--- /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 000000000..c85e33ce2
--- /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 b7bb504c6..8b5073fb9 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 000000000..b76913660
--- /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 000000000..709bf8435
--- /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 <private_key> <receiver> <value_or_function_signature> [<param1> <param2> ...]"
+        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 000000000..bbaf45e10
--- /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 a0db5d56e..6a29e4162 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 184a85d45..b81c18a4b 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 663536063..aa57e2720 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 af3c75195..27bc1abbc 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))