From 25d9ba8e545e7f1c3a44f8030ce8d898b5778437 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Wed, 7 Jul 2021 15:22:21 +0200 Subject: [PATCH] Add GHA for tests, lints, analysis --- .github/workflows/main.yml | 36 +++++++++++++++++ .golangci.yml | 22 +++++++++++ cmd/ethproof/ethproof.go | 4 +- ethstorageproof/ethstorageproof.go | 40 +++---------------- ethstorageproof/ethstorageproof_test.go | 10 +++-- ethstorageproof/types.go | 6 +-- examples/generate-proofs/generateProofs.go | 4 +- ierc20/erc20.go | 16 -------- token/erc20/erc20token.go | 1 + token/erc20/token.go | 3 +- token/mapbased/mapbased.go | 5 ++- token/minime/helpers.go | 16 +++++--- token/minime/minime.go | 5 ++- token/minime/minime_test.go | 46 +++++++++++++++------- token/token.go | 8 ++-- 15 files changed, 134 insertions(+), 88 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 .golangci.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..2124ee0 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,36 @@ +--- + +name: Main + +on: [push, pull_request] + +jobs: + go-tests: + runs-on: self-hosted + container: + image: golang:1.16.5 + defaults: + run: + shell: bash + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Lint + run: | + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0 + $(go env GOPATH)/bin/golangci-lint run --timeout=5m -c .golangci.yml + + - name: Go test + run: | + # we run vet in another step + go test -vet=off -timeout=1m ./... + # -race can easily make the crypto stuff 10x slower + go test -vet=off -timeout=15m -race -covermode atomic -coverprofile=covprofile ./... + + - name: Go analyze + run: | + diff -u <(echo -n) <(gofmt -s -d $(git ls-files '*.go')) + go vet ./... + curl -L https://github.com/dominikh/go-tools/releases/download/2021.1/staticcheck_linux_amd64.tar.gz | tar -xzf - + ./staticcheck/staticcheck ./... diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..305d63f --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,22 @@ +issues: + max-same-issues: 0 + exclude-use-default: false +linters: + enable: + - gosec + - misspell + - gofumpt + - lll + - staticcheck + - structcheck + - varcheck + - unused + - typecheck + - ineffassign + - errcheck + - gosimple + - goconst + +linters-settings: + lll: + line-length: 100 diff --git a/cmd/ethproof/ethproof.go b/cmd/ethproof/ethproof.go index 0327084..1812ab8 100644 --- a/cmd/ethproof/ethproof.go +++ b/cmd/ethproof/ethproof.go @@ -24,7 +24,9 @@ func main() { flag.Parse() ts := erc20.ERC20Token{} - ts.Init(context.Background(), *web3, *contract) + if err := ts.Init(context.Background(), *web3, *contract); err != nil { + log.Fatal(err) + } tokenData, err := ts.GetTokenData() if err != nil { log.Fatal(err) diff --git a/ethstorageproof/ethstorageproof.go b/ethstorageproof/ethstorageproof.go index cb212ba..462c9df 100644 --- a/ethstorageproof/ethstorageproof.go +++ b/ethstorageproof/ethstorageproof.go @@ -4,7 +4,6 @@ package ethstorageproof import ( "bytes" - "errors" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -12,29 +11,12 @@ import ( "github.com/ethereum/go-ethereum/trie" ) -const ( - shortNode = 2 - branchNode = 17 - hexChar = "0123456789abcdef" -) - -type ( - rlpNode [][]byte - keyStream struct { - *bytes.Buffer - } -) - -var ( - errDecode = errors.New("storage proof decode error") - lenBuf = make([]byte, 8) - nilBuf = make([]byte, 8) -) - -// VerifyEIP1186 verifies the whole Ethereum proof obtained with eth_getProof method against a StateRoot. -// It verifies Account proof against StateRoot and all Storage proofs against StorageHash. +// VerifyEIP1186 verifies the whole Ethereum proof obtained with eth_getProof +// method against a StateRoot. It verifies Account proof against StateRoot and +// all Storage proofs against StorageHash. func VerifyEIP1186(proof *StorageProof) (bool, error) { for _, sp := range proof.StorageProof { + sp := sp if ok, err := VerifyEthStorageProof(&sp, proof.StorageHash); !ok { return false, err } @@ -46,7 +28,8 @@ func VerifyEIP1186(proof *StorageProof) (bool, error) { // It does not verify the storage proof(s). func VerifyEthAccountProof(proof *StorageProof) (bool, error) { value, err := rlp.EncodeToBytes([]interface{}{ - proof.Nonce, proof.Balance.ToInt(), proof.StorageHash, proof.CodeHash}) + proof.Nonce, proof.Balance.ToInt(), proof.StorageHash, proof.CodeHash, + }) if err != nil { return false, err } @@ -54,17 +37,6 @@ func VerifyEthAccountProof(proof *StorageProof) (bool, error) { return VerifyProof(proof.StateRoot, proof.Address.Bytes(), value, proof.AccountProof) } -type proofList [][]byte - -func (n *proofList) Put(key []byte, value []byte) error { - *n = append(*n, value) - return nil -} - -func (n *proofList) Get(key []byte) ([]byte, error) { - return nil, nil -} - // VerifyEthStorageProof verifies an Ethereum storage proof against the StateRoot. // It does not verify the account proof against the Ethereum StateHash. func VerifyEthStorageProof(proof *StorageResult, storageHash common.Hash) (bool, error) { diff --git a/ethstorageproof/ethstorageproof_test.go b/ethstorageproof/ethstorageproof_test.go index 1d4ba89..516d8d8 100644 --- a/ethstorageproof/ethstorageproof_test.go +++ b/ethstorageproof/ethstorageproof_test.go @@ -12,6 +12,7 @@ import ( ) func TestVerify(t *testing.T) { + //nolint:lll tests := []struct { key []byte value []byte @@ -93,7 +94,8 @@ func TestVerify(t *testing.T) { { toBytes(t, "25a7599f71cc507621bc7f672ca927b1800f73b2a3e7c8d22648bda4ccb055b5"), nil, - proofToBytes([]string{"0xf90211a0dcc1e39d0a69b99e6ec5ec20c140cfe39a966d665c5eab729af9e5fa4c3778bca01469877a7a775ef8cfefd47ede98bb4fc04e2b63b5384f3528a34d918c335259a05a71a831adbc7ac9df83e4bcfff8b835f4e8ac584bb3b0d36c9f1421c368641ea0a28c6487a3018b15941fd7a89d6b4e909cf8ab50f669ee811c56141894539f07a0a1fffbe9ea9bde9f8b3a9c20d3275c54a0d9da8b6f053d47a12f1ed5f1aadbe9a0ec098bcc6e1a1e291e510db5c2f0df76e18e5a8e03cf476dfe251bda5605e810a08692406bc6f582c72572b92526747b2f6297af87dda1844a8932c2b4864842f5a03700357d763fd3935dd7c585d621da5b4a82e7d237169acf9d18618ca3aee2f6a02435caf55e43ddb879b3962e833ae560c906bf978ad6a0efd50adcf97f2e7111a092895b092500fa7f2068a04cda020cdd3e2d5e4793035ce5bca7e7c25fd1c067a084c852e8b21b0e1e1bc59067436152b717f355381d668025ba4e6bf6c6365270a0eca3831f7ad609a22ba6f4c52b3c1e9c571ff2649714449cfcf8e62d87e847b6a06c8ac45455a0bf559abf377c95e639e38c0d9b881fb5e1483c5736c130760d66a08218bdc141d4b3edca01320b16407f0da401de8d8186ea720baf9994c835796fa0ef5f7eccd4a593b267c717addbda2958817cf19be3a925284bd861470a1597aaa09b9e28a91bf0929f2bfc25ef5a59183d01f7122947c044a4fcd636427853fc0980", + proofToBytes([]string{ + "0xf90211a0dcc1e39d0a69b99e6ec5ec20c140cfe39a966d665c5eab729af9e5fa4c3778bca01469877a7a775ef8cfefd47ede98bb4fc04e2b63b5384f3528a34d918c335259a05a71a831adbc7ac9df83e4bcfff8b835f4e8ac584bb3b0d36c9f1421c368641ea0a28c6487a3018b15941fd7a89d6b4e909cf8ab50f669ee811c56141894539f07a0a1fffbe9ea9bde9f8b3a9c20d3275c54a0d9da8b6f053d47a12f1ed5f1aadbe9a0ec098bcc6e1a1e291e510db5c2f0df76e18e5a8e03cf476dfe251bda5605e810a08692406bc6f582c72572b92526747b2f6297af87dda1844a8932c2b4864842f5a03700357d763fd3935dd7c585d621da5b4a82e7d237169acf9d18618ca3aee2f6a02435caf55e43ddb879b3962e833ae560c906bf978ad6a0efd50adcf97f2e7111a092895b092500fa7f2068a04cda020cdd3e2d5e4793035ce5bca7e7c25fd1c067a084c852e8b21b0e1e1bc59067436152b717f355381d668025ba4e6bf6c6365270a0eca3831f7ad609a22ba6f4c52b3c1e9c571ff2649714449cfcf8e62d87e847b6a06c8ac45455a0bf559abf377c95e639e38c0d9b881fb5e1483c5736c130760d66a08218bdc141d4b3edca01320b16407f0da401de8d8186ea720baf9994c835796fa0ef5f7eccd4a593b267c717addbda2958817cf19be3a925284bd861470a1597aaa09b9e28a91bf0929f2bfc25ef5a59183d01f7122947c044a4fcd636427853fc0980", "0xf90211a09b71ba939391f11873619f1485b28ccff4f82c307ada11ebc55c89c399cb03ada08707d4ee35e0cddf0b1c5e0e741b9e5a06a845492e69335015d3e15ac071e93fa02b259d0a74389c95163ac48b7d7cc21fa6c4b88fd0e1a7cc11ec2705f298f143a0a8e47fb85490b054a6e5a41c3b6c4223c48f96b6e9a65a35c42d1f1c642af57aa0ed282db93aa4f7c1bd51c5c53319113d7af33d8638001159aa03f6f8e49faa7fa0442736a22acdabc8a748d4f9509ee60c31380a557b1b379f8bf218d34fc35c50a025dbee8981097d50c7d9b63bd517687c1437d87b9412afb1622b1f2ec2567b81a00b5890040ce417e090b1f4db3bf5b821a64b00fe5030076ba0057cb984656bc6a0b984e8c8307d9f125e2a512a6df13ca5c726e02f2cbdd08c1ff28791a42471b8a0033cfe45191e18d6c24754d719acc27004be45e7c00d77d453cf0300f622ec86a03febfa8e3a9af3ad3ed4b1bbcc000e8f375c198955347960a060c4df7e8d6262a01314a87f953887b83e268a036fea7a21cb23b6e9bc5a5a1342b638b359b93f34a060422f3c85e7493f3413afc6e73ef447372fcc22271e0f9fd25c742da26aa217a042f0be13d42d5001c8674b6df4ff5fda166b55276051ce00339d289c551f754aa00b1d9f4dd46cc489627374138ec313d38aeeb50baa7f6556f4bca64661ea80c8a039451466ed1b5d02a52cb962de7c52933cd4eb4f08f2ddd0ceff96c512f853d880", "0xf90211a01f4e7d1627bc65a09d8aac9b777bb62ad92a7d742ce00b8e39ca03a6f1bdd4bfa0aeaaa067fa3ad8b8c1352a2eb086a7d80b619a9e954898302bb54aac2a580888a0bd13681290fb0cb03848e2c2ae4fc48267ed708d0ea453d47310e7b8c676850ca03be0d8737a368f1f2cbf4a5665e28e7965a493e7d521022ab8ecfb5a42759e60a0fecd6db0a06292d872d96521404dba9d176823450066f641230b124e303b79f6a01ebcd9035bac2bb87c96c389b9f6b7307ef0db10ecf5ecc1abddac5d91506cb2a0256e31d30797fbe76fc194a219a2784f72c0b2850010fcd13d9ab8bd781ecb68a0ca5f9467b58bcf543f1d9f796b93b03622a54317408dcfe500ea9ce7de54220ea03d887644ef21ae2046f1e9035d3aeed524cd2ca3e0c2dcdae2642ca6796d7ebba084d4225ea797f5ca498adf6b30a83b4cad1853210025880eba9f0f2f6f2e8be5a02aa767777d307e000e5901422272b37c4134a24f154b59ca85790e857727a247a0fff31eb7ae28c63dabb8eecf64724e066e203c96dd65b3c8164974730819aa9ba07ff418c514cd85966992f998280cb90a92d7d063cb0d41c904361ff4494db0c6a01dee75007d41fb92e6c6e1c49ac45c241de4699134398643e598132a9d3224ada0e3b6eaee5e3a720e8cdac26a2d0dd056e17d7d9cd268778c5fcc73834ad015f4a05b2be630ed55951a54fe0c59ab12c22f4bd0b947186366235c096ecbb53b3eec80", "0xf90211a0703dc4b34f82f8da0d88be3466b492030943390743eec24dd212f70461114470a0376156a921eff3646f8fde5dcd09a43142bbe17206bb704eeaf0ebe86532e109a0482f8dedfcf8594a6176a6037b9af61f2296699224636f5874346c029194711aa0cea35f64980e677c64513a6dc4ac3dc7aa0b3f790e0c2005142fdfa5d49269e0a04b36d236a15144a1538c6219d4860857fb2a61d606ad79a3c579317ec8c43734a0db9d56dbc845090b95c5902c5a937860074d005276e91ce75b18be3bf5d6a651a01e9931923eb1b292a59c5af11259b39b202bf6a5eaf267e91da711447f609dc8a0debb8201ffc93286825511aa312a2ce6ea49ce9cc70bc912500d241d0e77eff1a0aaa743a24960ae73c4e2094cf2fa9fbeaa659f12fe402728a0b045ccad360138a0bfc485bacc720267fa859d1b6ce2b94a994b697a94cca5928b9af5f9bec62688a061d253de7f94a85004211f61806d1ed29ca818ed31e56d3dec6cb49d86c515f1a07e32f826a6b32892e8da6b4a858ee28914d441b5537817f492b74a01711f625ba0f6872ce36ec20967e568dceb585d6c6e3030d37c11dd671aee5a8144c4a8ee0aa04fd974620101b1584bba4229dd838a0bd2fce2748b582cd5c560618aa2603856a07352742e4e2d84d18d940882876b0a8191250a788b5d175e712adc146d72293ca0c20e98c5f04597d5ca6fba997fd2b0b68514784b858137c54f00f29f036e656780", @@ -203,6 +205,7 @@ func proofToBytes(proof []string) [][]byte { return r } +//nolint:lll var EIP1186Proof = ` { "stateRoot": "0xfd725b0325c2bda54cf7e33e3b9f6bc9b7927beb7ba6a2ef5feef7d20b394168", @@ -217,7 +220,7 @@ var EIP1186Proof = ` "0xf90211a09de6b0101efd7a910d3f5c818dda4ae5f683face6cc2adef0241ce09607ac7e2a02854271440ed7710c813922ec25972029fceeb9a71c619ae05a385be54a46a2ba0dbf4471186119f65130ec4de24f5a4549c288085f3bbeec2fce96e85ce79a542a028bed7905f83437274bcf048a7cc08e8873dc8b761e98f387d39e83c2b4a20b1a0718a55da0e5f5f51102838b8f5aa8d8bc7ccbd448eac86e9903edaed23807089a0788a858cb1f272f8c8c2cbc5514d1782a637780e15ecb0f9e5bba5cab44cb44da00575ce84f14cba25cab3aabe9cac7901e6402b84f985f64bc82e4cff625216a5a0b6429f01756315b7fb9de64ac831c3dcc706663d26e71ca8034951c394ec0a5ca0cfea6a7f844bae7ada294525a8e10aa81fac634924ec47ef303eb36d752cac76a043890cca104e25bf95636b875fea6214ffb680cfc37fba9962c642b161cae2afa00926c77779136644c659b65c48532a57be7923a70ac7ff0872f93f9b27f2597aa010c67946f8fdbf8fbbcb9320e6bafccb1d8ab34eacc242dd7f8a8d0d6306e32ba0b1a825bf9182504c086d64ac2a4fdd072136a86984e895df7fd6499a048b452aa0db152acded3fb8df9f4d1005cf7f4d38fc1c0d6d1c55b81385d2d92c7397825da04ca471ce492cdf4692406b2b2787b1c78258350225c40814af8687d89c78e460a0568b92c18e85758988981c993b44794164d5291f164d3d38910c2e4ebf0c9cf680", "0xf8f1a075aecc05e77688cfcf7b2be6918d317d40f84ac70ae82fa00e363eb6d54e9d6f80a0c66b311f312e309f3cb80cce2ea55e7fabd55bfd222297868b8cda2186c5e0dd80808080a0d3bee690d48173444d679a7ab969cd9199b83ac3de64db3d987dc6aa2ddb06e780a07b3eb22f76a4e16a632f1732fe234e87fd2bea81ffe1dbba8ff04495319b0257a0903e3cd41d04b4693e0eae1549f7fe024eb06b98fa1c137cacc66d57a7a0e223a05d07ec85b94b44ef509a9cff840b0ce44facf7e79411967c7e9fabcaa354629b8080a015234d9ef39b97af083fb5715dd5cc2f4454a23ca3a4d72419cfde3ea918036c8080", "0xf87180a0568a3548f0c468bec66c6d91b1d72f84e44373c03c6e118d7edc6ba8fe9b4d0c80808080808080a0ec26e129a6fc11a5dcc748bd22ca4e41a0ace63cbf1cb2de018e2b9585a06fc680a0de28cbec81a40883ee13ca2ca4a047f79f9b7b411898941314270334f0c86ec38080808080", - "0xf8669d2092cd7f3f78137497df02f6ccb9badda93d9782e0f230c807ba728be0b846f8440180a0a9302463fd528ce8aca2d5ad58de0622f07e2107c12a780f67c624592bbcc13da0d80d4b7c890cb9d6a4893e6b52bc34b56b25335cb13716e0d1d31383e6b41505" + "0xf8669d2092cd7f3f78137497df02f6ccb9badda93d9782e0f230c807ba728be0b846f8440180a0a9302463fd528ce8aca2d5ad58de0622f07e2107c12a780f67c624592bbcc13da0d80d4b7c890cb9d6a4893e6b52bc34b56b25335cb13716e0d1d31383e6b41505" ], "balance": "0x0", "codeHash": "0xd80d4b7c890cb9d6a4893e6b52bc34b56b25335cb13716e0d1d31383e6b41505", @@ -254,7 +257,8 @@ func Test_eipProof(t *testing.T) { if ok, err := VerifyEthStorageProof(&sp.StorageProof[0], sp.StorageHash); !ok { t.Errorf("proof must be valid but it is invalid: (%v)", err) } - sp.StorageProof[0].Key = toBytes(t, "0x49c4c8b2db715e9f7e1d3306b9f6860a389635dfb3943db23f1005544a50fbb2") + sp.StorageProof[0].Key = toBytes(t, + "0x49c4c8b2db715e9f7e1d3306b9f6860a389635dfb3943db23f1005544a50fbb2") if ok, _ := VerifyEIP1186(&sp); ok { t.Errorf("proof must be invalid but it is valid") } diff --git a/ethstorageproof/types.go b/ethstorageproof/types.go index bd30a69..1a5c2ef 100644 --- a/ethstorageproof/types.go +++ b/ethstorageproof/types.go @@ -83,7 +83,8 @@ func (s *SliceData) UnmarshalJSON(data []byte) error { // with the stateRoot-Node, following the path of the SHA3 (address) as // key. // -// storageProof: ARRAY - Array of storage-entries as requested. Each entry is a object with these properties: +// storageProof: ARRAY - Array of storage-entries as requested. Each entry +// is a object with these properties: // key: QUANTITY - the requested storage key // value: QUANTITY - the storage value // proof: ARRAY - Array of rlp-serialized MerkleTree-Nodes, starting @@ -144,8 +145,7 @@ func (m *MemDB) Get(key []byte) ([]byte, error) { } // Put sets or updates the value at key -func (m *MemDB) Put(key []byte, value []byte) error { +func (m *MemDB) Put(key []byte, value []byte) { h := common.BytesToHash(key) m.kvs[h] = value - return nil } diff --git a/examples/generate-proofs/generateProofs.go b/examples/generate-proofs/generateProofs.go index 68e6c0e..147f295 100644 --- a/examples/generate-proofs/generateProofs.go +++ b/examples/generate-proofs/generateProofs.go @@ -68,8 +68,8 @@ func getProofs(web3, contract string, holders []string) { if len(h) < 20 { continue } + wg.Add(1) go func() { - wg.Add(1) holderAddr := common.HexToAddress(h) sproof, err := t.GetProof(holderAddr, blk.Number(), slot) if err != nil { @@ -93,5 +93,5 @@ func getProofs(web3, contract string, holders []string) { if err != nil { log.Fatal(err) } - ioutil.WriteFile("proofs.json", p, os.FileMode(0644)) + ioutil.WriteFile("proofs.json", p, os.FileMode(0o644)) } diff --git a/ierc20/erc20.go b/ierc20/erc20.go index 4f0f3e4..6a80f98 100644 --- a/ierc20/erc20.go +++ b/ierc20/erc20.go @@ -177,7 +177,6 @@ func (_Token *TokenTransactorRaw) Transact(opts *bind.TransactOpts, method strin func (_Token *TokenCaller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { var out []interface{} err := _Token.contract.Call(opts, &out, "allowance", owner, spender) - if err != nil { return *new(*big.Int), err } @@ -185,7 +184,6 @@ func (_Token *TokenCaller) Allowance(opts *bind.CallOpts, owner common.Address, out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err - } // Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. @@ -208,7 +206,6 @@ func (_Token *TokenCallerSession) Allowance(owner common.Address, spender common func (_Token *TokenCaller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { var out []interface{} err := _Token.contract.Call(opts, &out, "balanceOf", account) - if err != nil { return *new(*big.Int), err } @@ -216,7 +213,6 @@ func (_Token *TokenCaller) BalanceOf(opts *bind.CallOpts, account common.Address out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err - } // BalanceOf is a free data retrieval call binding the contract method 0x70a08231. @@ -239,7 +235,6 @@ func (_Token *TokenCallerSession) BalanceOf(account common.Address) (*big.Int, e func (_Token *TokenCaller) Decimals(opts *bind.CallOpts) (uint8, error) { var out []interface{} err := _Token.contract.Call(opts, &out, "decimals") - if err != nil { return *new(uint8), err } @@ -247,7 +242,6 @@ func (_Token *TokenCaller) Decimals(opts *bind.CallOpts) (uint8, error) { out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) return out0, err - } // Decimals is a free data retrieval call binding the contract method 0x313ce567. @@ -270,7 +264,6 @@ func (_Token *TokenCallerSession) Decimals() (uint8, error) { func (_Token *TokenCaller) Name(opts *bind.CallOpts) (string, error) { var out []interface{} err := _Token.contract.Call(opts, &out, "name") - if err != nil { return *new(string), err } @@ -278,7 +271,6 @@ func (_Token *TokenCaller) Name(opts *bind.CallOpts) (string, error) { out0 := *abi.ConvertType(out[0], new(string)).(*string) return out0, err - } // Name is a free data retrieval call binding the contract method 0x06fdde03. @@ -301,7 +293,6 @@ func (_Token *TokenCallerSession) Name() (string, error) { func (_Token *TokenCaller) Symbol(opts *bind.CallOpts) (string, error) { var out []interface{} err := _Token.contract.Call(opts, &out, "symbol") - if err != nil { return *new(string), err } @@ -309,7 +300,6 @@ func (_Token *TokenCaller) Symbol(opts *bind.CallOpts) (string, error) { out0 := *abi.ConvertType(out[0], new(string)).(*string) return out0, err - } // Symbol is a free data retrieval call binding the contract method 0x95d89b41. @@ -332,7 +322,6 @@ func (_Token *TokenCallerSession) Symbol() (string, error) { func (_Token *TokenCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} err := _Token.contract.Call(opts, &out, "totalSupply") - if err != nil { return *new(*big.Int), err } @@ -340,7 +329,6 @@ func (_Token *TokenCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err - } // TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. @@ -541,7 +529,6 @@ type TokenApproval struct { // // Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) func (_Token *TokenFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*TokenApprovalIterator, error) { - var ownerRule []interface{} for _, ownerItem := range owner { ownerRule = append(ownerRule, ownerItem) @@ -562,7 +549,6 @@ func (_Token *TokenFilterer) FilterApproval(opts *bind.FilterOpts, owner []commo // // Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) func (_Token *TokenFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *TokenApproval, owner []common.Address, spender []common.Address) (event.Subscription, error) { - var ownerRule []interface{} for _, ownerItem := range owner { ownerRule = append(ownerRule, ownerItem) @@ -694,7 +680,6 @@ type TokenTransfer struct { // // Solidity: event Transfer(address indexed from, address indexed to, uint256 value) func (_Token *TokenFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*TokenTransferIterator, error) { - var fromRule []interface{} for _, fromItem := range from { fromRule = append(fromRule, fromItem) @@ -715,7 +700,6 @@ func (_Token *TokenFilterer) FilterTransfer(opts *bind.FilterOpts, from []common // // Solidity: event Transfer(address indexed from, address indexed to, uint256 value) func (_Token *TokenFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *TokenTransfer, from []common.Address, to []common.Address) (event.Subscription, error) { - var fromRule []interface{} for _, fromItem := range from { fromRule = append(fromRule, fromItem) diff --git a/token/erc20/erc20token.go b/token/erc20/erc20token.go index 7cbd49e..24d8f6c 100644 --- a/token/erc20/erc20token.go +++ b/token/erc20/erc20token.go @@ -47,6 +47,7 @@ func (w *ERC20Token) Init(ctx context.Context, web3Endpoint, contractAddress str return fmt.Errorf("RPC node client is not set") } if w.Ethcli == nil { + //lint:ignore ST1005 "Ethereum" is a proper noun, so it's capitalized return fmt.Errorf("Ethereum client is not set") } } diff --git a/token/erc20/token.go b/token/erc20/token.go index 8b8207e..ae8ae08 100644 --- a/token/erc20/token.go +++ b/token/erc20/token.go @@ -14,5 +14,6 @@ type TokenData struct { } func (t *TokenData) String() string { - return fmt.Sprintf(`{"name":%s,"symbol":%s,"decimals":%s,"totalSupply":%s}`, t.Name, t.Symbol, string(t.Decimals), t.TotalSupply.String()) + return fmt.Sprintf(`{"name":%s,"symbol":%s,"decimals":%s,"totalSupply":%s}`, + t.Name, t.Symbol, string(t.Decimals), t.TotalSupply.String()) } diff --git a/token/mapbased/mapbased.go b/token/mapbased/mapbased.go index b7b12aa..b311cb3 100644 --- a/token/mapbased/mapbased.go +++ b/token/mapbased/mapbased.go @@ -85,7 +85,7 @@ func (m *Mapbased) DiscoverSlot(holder common.Address) (int, *big.Float, error) } balance, err := m.erc20.Balance(holder) if err != nil { - return -1, nil, fmt.Errorf("Balance: %w", err) + return -1, nil, fmt.Errorf("balance: %w", err) } addr := common.Address{} @@ -127,7 +127,8 @@ func (m *Mapbased) DiscoverSlot(holder common.Address) (int, *big.Float, error) // VerifyProof verifies a map based storage proof. func (m *Mapbased) VerifyProof(holder common.Address, storageRoot common.Hash, - proofs []ethstorageproof.StorageResult, mapIndexSlot int, targetBalance, targetBlock *big.Int) error { + proofs []ethstorageproof.StorageResult, mapIndexSlot int, targetBalance, + targetBlock *big.Int) error { if len(proofs) != 1 { return fmt.Errorf("invalid length of proofs %d", len(proofs)) } diff --git a/token/minime/helpers.go b/token/minime/helpers.go index 1bf07fa..f1bc694 100644 --- a/token/minime/helpers.go +++ b/token/minime/helpers.go @@ -13,7 +13,8 @@ import ( // VerifyProof verifies a Minime storage proof. // The targetBalance parameter is the full balance value, without decimals. func VerifyProof(holder common.Address, storageRoot common.Hash, - proofs []ethstorageproof.StorageResult, mapIndexSlot int, targetBalance, targetBlock *big.Int) error { + proofs []ethstorageproof.StorageResult, mapIndexSlot int, targetBalance, + targetBlock *big.Int) error { // Sanity checks if len(proofs) != 2 { return fmt.Errorf("wrong length of storage proofs") @@ -51,7 +52,8 @@ func VerifyProof(holder common.Address, storageRoot common.Hash, } // Check balance matches with the provided balance if proof0Balance.Cmp(targetBalance) != 0 { - return fmt.Errorf("proof balance and provided balance mismatch (%s != %s)", proof0Balance.String(), targetBalance.String()) + return fmt.Errorf("proof balance and provided balance mismatch (%s != %s)", + proof0Balance.String(), targetBalance.String()) } // Proof 0 checkpoint block should be smaller or equal than target block @@ -93,11 +95,13 @@ func VerifyProof(holder common.Address, storageRoot common.Hash, return nil } -// ParseMinimeValue takes the RLP encoded (hexadecimal string) value from EIP1186 and splits into -// balance and block number (checkpoint). If decimals are unkown use 1. +// ParseMinimeValue takes the RLP encoded (hexadecimal string) value from +// EIP1186 and splits into balance and block number (checkpoint). If decimals +// are unknown use 1. // -// Returns the float balance (taking into account the decimals), the full integer without taking into -// account the decimals and the Ethereum block number for the checkpoint. +// Returns the float balance (taking into account the decimals), the full +// integer without taking into account the decimals and the Ethereum block +// number for the checkpoint. func ParseMinimeValue(value []byte, decimals int) (*big.Float, *big.Int, *big.Int, error) { // hexValue could be left zeroes trimed, so we need to expand it to 32 bytes value = common.LeftPadBytes(value, 32) diff --git a/token/minime/minime.go b/token/minime/minime.go index 794718f..687a321 100644 --- a/token/minime/minime.go +++ b/token/minime/minime.go @@ -48,7 +48,7 @@ func (m *Minime) DiscoverSlot(holder common.Address) (int, *big.Float, error) { addr := common.Address{} copy(addr[:], m.erc20.TokenAddr[:20]) amount := big.NewFloat(0) - block := new(big.Int) + var block *big.Int index := -1 for i := 0; i < maxIterationsForDiscover; i++ { @@ -157,7 +157,8 @@ func (m *Minime) GetProof(holder common.Address, block *big.Int, // VerifyProof verifies a minime storage proof func (m *Minime) VerifyProof(holder common.Address, storageRoot common.Hash, - proofs []ethstorageproof.StorageResult, mapIndexSlot int, targetBalance, targetBlock *big.Int) error { + proofs []ethstorageproof.StorageResult, mapIndexSlot int, targetBalance, + targetBlock *big.Int) error { return VerifyProof(holder, storageRoot, proofs, mapIndexSlot, targetBalance, targetBlock) } diff --git a/token/minime/minime_test.go b/token/minime/minime_test.go index e278128..645b035 100644 --- a/token/minime/minime_test.go +++ b/token/minime/minime_test.go @@ -11,22 +11,36 @@ import ( ) func TestEthProof(t *testing.T) { - sp := testStorageProof{} - if err := json.Unmarshal([]byte(proof1), &sp); err != nil { - t.Fatal(err) + tests := []struct { + proof string + verify bool + }{ + {proof1, true}, + {proof2, true}, } + for i, tt := range tests { + sp := testStorageProof{} + if err := json.Unmarshal([]byte(tt.proof), &sp); err != nil { + t.Fatal(err) + } - balance, err := hex.DecodeString(sp.Balance) - if err != nil { - t.Fatal(err) + balance, err := hex.DecodeString(sp.Balance) + if err != nil { + t.Fatal(err) + } + err = VerifyProof(sp.Address, + sp.Root, + sp.StorageProofs, + sp.Slot, + new(big.Int).SetBytes(balance), + new(big.Int).SetUint64(sp.Block), + ) + if tt.verify && err != nil { + t.Errorf("can't verify proof %v: %v", i, err) + } else if !tt.verify && err == nil { + t.Errorf("shouldn't verify proof %v", i) + } } - VerifyProof(sp.Address, - sp.Root, - sp.StorageProofs, - sp.Slot, - new(big.Int).SetBytes(balance), - new(big.Int).SetUint64(sp.Block), - ) } type testStorageProof struct { @@ -38,6 +52,7 @@ type testStorageProof struct { StorageProofs []ethstorageproof.StorageResult `json:"storageProofs"` } +//nolint:lll var proof1 = string(`{ "address": "0x75ebce762600f8d2171c42e1f1af07c1fbf39832", "root": "0x9e38fc8a3d67075aed963f0be7fea6d0a145eacefe9c1e4deccfd927e3ea5c36", @@ -72,11 +87,12 @@ var proof1 = string(`{ ] }`) -var proof2Wrong = string(`{ +//nolint:lll +var proof2 = string(`{ "address": "0xbd9c69654b8f3e5978dfd138b00cb0be29f28ccf", "root": "0x1778ec12b19b5c6036edbe69e9a54dddc397813f292ce276aabb3fc4184abe4c", "balance": "0293ca8fbc70ffaffde577", -"block":"12743076", +"block":12743076, "slot": 8, "storageProofs":[ { diff --git a/token/token.go b/token/token.go index 60420eb..d83cb41 100644 --- a/token/token.go +++ b/token/token.go @@ -19,10 +19,12 @@ const ( type Token interface { Init(tokenAddress, web3endpoint string) error DiscoverSlot(holder common.Address) (int, *big.Float, error) - GetProof(holder common.Address, block *big.Int, indexSlot int) (*ethstorageproof.StorageProof, error) + GetProof(holder common.Address, block *big.Int, + indexSlot int) (*ethstorageproof.StorageProof, error) GetBlock(block *big.Int) (*types.Block, error) - VerifyProof(holder common.Address, storageRoot common.Hash, proofs []ethstorageproof.StorageResult, - indexSlot int, targetBalance, targetBlock *big.Int) error + VerifyProof(holder common.Address, storageRoot common.Hash, + proofs []ethstorageproof.StorageResult, indexSlot int, targetBalance, + targetBlock *big.Int) error } func NewToken(tokenType int, address, web3endpoint string) (Token, error) {