[
  {
    "path": ".github/workflows/pr.yaml",
    "content": "name: Unit tests\non: [pull_request]\njobs:\n  build:\n    runs-on: ubuntu-latest\n    name: Go test\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          node-version: \"14\"\n      - name: Install ethers testcases\n        run: cd ./testcases && npm install\n      - name: Setup go\n        uses: actions/setup-go@v1\n        with:\n          go-version: \"1.18.1\"\n      - name: \"Setup\"\n        run: ./scripts/setup-ci.sh\n      - name: \"Setup geth\"\n        run: ./scripts/setup-geth.sh\n      - name: Go test\n        run: go test -v ./...\n"
  },
  {
    "path": ".github/workflows/release.yaml",
    "content": "name: Release\n\non:\n  workflow_dispatch:\n  push:\n    branches-ignore:\n      - '**'\n    tags:\n      - 'v*.*.*'\n      # to be used by fork patch-releases ^^\n      - 'v*.*.*-*'\n\njobs:\n  goreleaser:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Fetch all tags\n        run: git fetch --force --tags\n      - name: Setup go\n        uses: actions/setup-go@v1\n        with:\n          go-version: '1.18.1'\n      - name: Run GoReleaser\n        uses: goreleaser/goreleaser-action@v2\n        with:\n          distribution: goreleaser\n          version: latest\n          args: release --rm-dist\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}"
  },
  {
    "path": ".gitignore",
    "content": "bin/\npkg/\n\n.idea\n\n# website\nnode_modules\n.next\n\ndist/\n"
  },
  {
    "path": ".goreleaser.yaml",
    "content": "before:\n  hooks:\n    - go mod tidy\nbuilds:\n  - dir: cmd\n    env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - windows\n      - darwin\narchives:\n  - replacements:\n      darwin: Darwin\n      linux: Linux\n      windows: Windows\n      386: i386\n      amd64: x86_64\nchecksum:\n  name_template: 'checksums.txt'\nsnapshot:\n  name_template: \"{{ incpatch .Version }}-next\"\nchangelog:\n  sort: asc\n  filters:\n    exclude:\n      - '^docs:'\n      - '^test:'\n"
  },
  {
    "path": "4byte/4byte.go",
    "content": "package fourbyte\n\nimport (\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n)\n\nconst (\n\tfourByteURL = \"https://www.4byte.directory\"\n)\n\n// Resolve resolves a method/event signature\nfunc Resolve(str string) (string, error) {\n\treturn get(\"/api/v1/signatures/?hex_signature=\" + str)\n}\n\n// ResolveBytes resolves a method/event signature in bytes\nfunc ResolveBytes(b []byte) (string, error) {\n\treturn Resolve(hex.EncodeToString(b))\n}\n\nfunc get(path string) (string, error) {\n\treq, err := http.Get(fourByteURL + path)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer req.Body.Close()\n\n\tdata, err := ioutil.ReadAll(req.Body)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar result struct {\n\t\tResults []signatureResult\n\t}\n\tif err := json.Unmarshal(data, &result); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif len(result.Results) == 0 {\n\t\treturn \"\", nil\n\t}\n\treturn result.Results[0].TextSignature, nil\n}\n\ntype signatureResult struct {\n\tTextSignature string `json:\"text_signature\"`\n}\n"
  },
  {
    "path": "4byte/4byte_test.go",
    "content": "package fourbyte\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc Test4Byte(t *testing.T) {\n\tt.Skip(\"http api not stable, skip for now\")\n\n\tvar cases = []struct {\n\t\tin, out string\n\t}{\n\t\t{\n\t\t\t\"0xddf252ad\",\n\t\t\t\"Transfer(address,address,uint256)\",\n\t\t},\n\t\t{\n\t\t\t\"0x42842e0e\",\n\t\t\t\"safeTransferFrom(address,address,uint256)\",\n\t\t},\n\t}\n\tfor _, i := range cases {\n\t\tfound, err := Resolve(i.in)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, i.out, found)\n\t}\n\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# 0.1.4 (Unreleased)\n\n- feat: Add override to `eth_call` request [[GH-240](https://github.com/umbracle/ethgo/issues/240)]\n- fix: Recovery of typed transactions [[GH-238](https://github.com/umbracle/ethgo/issues/238)]\n- fix: Parse `nonce` and `mixHash` on `Block` [[GH-228](https://github.com/umbracle/ethgo/issues/228)]\n- feat: `abi` decodes function string in multilines [[GH-212](https://github.com/umbracle/ethgo/issues/212)]\n- feat: `abi` DecodeStruct uses the `abi` tag instead of the default `mapstructure` [[GH-211](https://github.com/umbracle/ethgo/issues/211)]\n- feat: Implement `ens` reverse resolver [[GH-210](https://github.com/umbracle/ethgo/issues/210)]\n- fix: Jsonrpc eth_getLogs request cannot return string [[GH-209](https://github.com/umbracle/ethgo/issues/209)]\n\n# 0.1.3 (13 June, 2022)\n\n- Fix out-of-bounds reading of bytes during ABI decoding [[GH-205](https://github.com/umbracle/ethgo/issues/205)]\n- Update `fastrlp` to `59d5dd3` commit to fix a bug on bytes length check [[GH-204](https://github.com/umbracle/ethgo/issues/204)]\n- Fix out-of-bounds RLP unmarshal of transactions [[GH-203](https://github.com/umbracle/ethgo/issues/203)]\n\n# 0.1.2 (5 May, 2022)\n\n- Update `btcd` library to new `v0.22.1`\n- Add option in `contract` to send transactions with EIP-1559 [[GH-198](https://github.com/umbracle/ethgo/issues/198)]\n- Add custom `TxnOpts` to send a transaction in `contract` [[GH-195](https://github.com/umbracle/ethgo/issues/195)]\n- Add `ens resolve` command to resolve an ENS name [[GH-196](https://github.com/umbracle/ethgo/issues/196)]\n- Fix signing of typed transactions [[GH-197](https://github.com/umbracle/ethgo/issues/197)]\n- Fix. Use `ethgo.BlockNumber` input to make `Call` in contract [[GH-194](https://github.com/umbracle/ethgo/issues/194)]\n- Add `testcases` for contract signature and transaction signing [[GH-193](https://github.com/umbracle/ethgo/issues/193)]\n- Add `eth_feeHistory` rpc endpoint [[GH-192](https://github.com/umbracle/ethgo/issues/192)]\n- Update `testserver` to `go-ethereum:v1.10.15` [[GH-191](https://github.com/umbracle/ethgo/issues/191)]\n- Do not decode `to` in `Transaction` if not exists [[GH-190](https://github.com/umbracle/ethgo/issues/190)]\n\n# 0.1.1 (25 April, 2022)\n\n- Retrieve latest nonce when sending a transaction on `contract` [[GH-185](https://github.com/umbracle/ethgo/issues/185)]\n- Add `etherscan.GasPrice` function to return last block gas price [[GH-182](https://github.com/umbracle/ethgo/issues/182)]\n- Add `4byte` package and cli [[GH-178](https://github.com/umbracle/ethgo/issues/178)]\n- Install and use `ethers.js` spec tests for wallet private key decoding [[GH-177](https://github.com/umbracle/ethgo/issues/177)]\n- Add `GetLogs` function Etherscan to return logs by filter [[GH-170](https://github.com/umbracle/ethgo/issues/170)]\n- Add `Copy` function to major data types [[GH-169](https://github.com/umbracle/ethgo/issues/169)]\n- Parse `fixed bytes` type in event topic [[GH-168](https://github.com/umbracle/ethgo/issues/168)]\n- Introduce `NodeProvider` and update `Contract` and `abigen` format. [[GH-167](https://github.com/umbracle/ethgo/issues/167)]\n\n# 0.1.0 (5 March, 2022)\n\n- Initial public release.\n"
  },
  {
    "path": "LICENSE",
    "content": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"\n    means each individual or legal entity that creates, contributes to\n    the creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n    means the combination of the Contributions of others (if any) used\n    by a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n    means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n    means Source Code Form to which the initial Contributor has attached\n    the notice in Exhibit A, the Executable Form of such Source Code\n    Form, and Modifications of such Source Code Form, in each case\n    including portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n    means\n\n    (a) that the initial Contributor has attached the notice described\n        in Exhibit B to the Covered Software; or\n\n    (b) that the Covered Software was made available under the terms of\n        version 1.1 or earlier of the License, but not also under the\n        terms of a Secondary License.\n\n1.6. \"Executable Form\"\n    means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n    means a work that combines Covered Software with other material, in\n    a separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n    means this document.\n\n1.9. \"Licensable\"\n    means having the right to grant, to the maximum extent possible,\n    whether at the time of the initial grant or subsequently, any and\n    all of the rights conveyed by this License.\n\n1.10. \"Modifications\"\n    means any of the following:\n\n    (a) any file in Source Code Form that results from an addition to,\n        deletion from, or modification of the contents of Covered\n        Software; or\n\n    (b) any new file in Source Code Form that contains any Covered\n        Software.\n\n1.11. \"Patent Claims\" of a Contributor\n    means any patent claim(s), including without limitation, method,\n    process, and apparatus claims, in any patent Licensable by such\n    Contributor that would be infringed, but for the grant of the\n    License, by the making, using, selling, offering for sale, having\n    made, import, or transfer of either its Contributions or its\n    Contributor Version.\n\n1.12. \"Secondary License\"\n    means either the GNU General Public License, Version 2.0, the GNU\n    Lesser General Public License, Version 2.1, the GNU Affero General\n    Public License, Version 3.0, or any later versions of those\n    licenses.\n\n1.13. \"Source Code Form\"\n    means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n    means an individual or a legal entity exercising rights under this\n    License. For legal entities, \"You\" includes any entity that\n    controls, is controlled by, or is under common control with You. For\n    purposes of this definition, \"control\" means (a) the power, direct\n    or indirect, to cause the direction or management of such entity,\n    whether by contract or otherwise, or (b) ownership of more than\n    fifty percent (50%) of the outstanding shares or beneficial\n    ownership of such entity.\n\n2. License Grants and Conditions\n--------------------------------\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-exclusive license:\n\n(a) under intellectual property rights (other than patent or trademark)\n    Licensable by such Contributor to use, reproduce, make available,\n    modify, display, perform, distribute, and otherwise exploit its\n    Contributions, either on an unmodified basis, with Modifications, or\n    as part of a Larger Work; and\n\n(b) under Patent Claims of such Contributor to make, use, sell, offer\n    for sale, have made, import, and otherwise transfer either its\n    Contributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\n    or\n\n(b) for infringements caused by: (i) Your and any other third party's\n    modifications of Covered Software, or (ii) the combination of its\n    Contributions with other software (except as part of its Contributor\n    Version); or\n\n(c) under Patent Claims infringed by Covered Software in the absence of\n    its Contributions.\n\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n-------------------\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\n    Form, as described in Section 3.1, and You must inform recipients of\n    the Executable Form how they can obtain a copy of such Source Code\n    Form by reasonable means in a timely manner, at a charge no more\n    than the cost of distribution to the recipient; and\n\n(b) You may distribute such Executable Form under the terms of this\n    License, or sublicense it under different terms, provided that the\n    license for the Executable Form does not attempt to limit or alter\n    the recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n---------------------------------------------------\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n--------------\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n************************************************************************\n*                                                                      *\n*  6. Disclaimer of Warranty                                           *\n*  -------------------------                                           *\n*                                                                      *\n*  Covered Software is provided under this License on an \"as is\"       *\n*  basis, without warranty of any kind, either expressed, implied, or  *\n*  statutory, including, without limitation, warranties that the       *\n*  Covered Software is free of defects, merchantable, fit for a        *\n*  particular purpose or non-infringing. The entire risk as to the     *\n*  quality and performance of the Covered Software is with You.        *\n*  Should any Covered Software prove defective in any respect, You     *\n*  (not any Contributor) assume the cost of any necessary servicing,   *\n*  repair, or correction. This disclaimer of warranty constitutes an   *\n*  essential part of this License. No use of any Covered Software is   *\n*  authorized under this License except under this disclaimer.         *\n*                                                                      *\n************************************************************************\n\n************************************************************************\n*                                                                      *\n*  7. Limitation of Liability                                          *\n*  --------------------------                                          *\n*                                                                      *\n*  Under no circumstances and under no legal theory, whether tort      *\n*  (including negligence), contract, or otherwise, shall any           *\n*  Contributor, or anyone who distributes Covered Software as          *\n*  permitted above, be liable to You for any direct, indirect,         *\n*  special, incidental, or consequential damages of any character      *\n*  including, without limitation, damages for lost profits, loss of    *\n*  goodwill, work stoppage, computer failure or malfunction, or any    *\n*  and all other commercial damages or losses, even if such party      *\n*  shall have been informed of the possibility of such damages. This   *\n*  limitation of liability shall not apply to liability for death or   *\n*  personal injury resulting from such party's negligence to the       *\n*  extent applicable law prohibits such limitation. Some               *\n*  jurisdictions do not allow the exclusion or limitation of           *\n*  incidental or consequential damages, so this exclusion and          *\n*  limitation may not apply to You.                                    *\n*                                                                      *\n************************************************************************\n\n8. Litigation\n-------------\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n----------------\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n---------------------------\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n-------------------------------------------\n\n  This Source Code Form is subject to the terms of the Mozilla Public\n  License, v. 2.0. If a copy of the MPL was not distributed with this\n  file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n---------------------------------------------------------\n\n  This Source Code Form is \"Incompatible With Secondary Licenses\", as\n  defined by the Mozilla Public License, v. 2.0.\n"
  },
  {
    "path": "Makefile",
    "content": "\n.PHONY: build-artifacts\nbuild-artifacts: \n\t@echo \"--> Build Artifacts\"\n\t@sh -c ./scripts/build-artifacts.sh\n"
  },
  {
    "path": "README.md",
    "content": "\n# Eth-Go\n\n[![Chat Badge]][chat link]\n\n[chat badge]: https://img.shields.io/badge/chat-discord-%237289da\n[chat link]: https://discord.gg/5A6Qm2u4yK\n\nEthgo is a lightweight SDK in Go to interact with Ethereum compatible blockchains.\n\n- Website: https://www.ethgoproject.io\n\nEthgo provides the next key features:\n\n- **Simple**: Light and with a small number of direct dependencies.\n\n- **Ethereum ecosystem**: Native integration with other tools from the ecosystem like `ens` and `etherscan`.\n\n- **Command-line-interface**: Ethgo is both a Golang SDK library and a CLI.\n"
  },
  {
    "path": "abi/abi.go",
    "content": "package abi\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"hash\"\n\t\"io\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\n// ABI represents the ethereum abi format\ntype ABI struct {\n\tConstructor        *Method\n\tMethods            map[string]*Method\n\tMethodsBySignature map[string]*Method\n\tEvents             map[string]*Event\n\tErrors             map[string]*Error\n}\n\nfunc (a *ABI) GetMethod(name string) *Method {\n\tm := a.Methods[name]\n\treturn m\n}\n\nfunc (a *ABI) GetMethodBySignature(methodSignature string) *Method {\n\tm := a.MethodsBySignature[methodSignature]\n\treturn m\n}\n\nfunc (a *ABI) addError(e *Error) {\n\tif len(a.Errors) == 0 {\n\t\ta.Errors = map[string]*Error{}\n\t}\n\ta.Errors[e.Name] = e\n}\n\nfunc (a *ABI) addEvent(e *Event) {\n\tif len(a.Events) == 0 {\n\t\ta.Events = map[string]*Event{}\n\t}\n\tname := overloadedName(e.Name, func(s string) bool {\n\t\t_, ok := a.Events[s]\n\t\treturn ok\n\t})\n\ta.Events[name] = e\n}\n\nfunc (a *ABI) addMethod(m *Method) {\n\tif len(a.Methods) == 0 {\n\t\ta.Methods = map[string]*Method{}\n\t}\n\tif len(a.MethodsBySignature) == 0 {\n\t\ta.MethodsBySignature = map[string]*Method{}\n\t}\n\tname := overloadedName(m.Name, func(s string) bool {\n\t\t_, ok := a.Methods[s]\n\t\treturn ok\n\t})\n\ta.Methods[name] = m\n\ta.MethodsBySignature[m.Sig()] = m\n}\n\nfunc overloadedName(rawName string, isAvail func(string) bool) string {\n\tname := rawName\n\tok := isAvail(name)\n\tfor idx := 0; ok; idx++ {\n\t\tname = fmt.Sprintf(\"%s%d\", rawName, idx)\n\t\tok = isAvail(name)\n\t}\n\treturn name\n}\n\n// NewABI returns a parsed ABI struct\nfunc NewABI(s string) (*ABI, error) {\n\treturn NewABIFromReader(bytes.NewReader([]byte(s)))\n}\n\n// MustNewABI returns a parsed ABI contract or panics if fails\nfunc MustNewABI(s string) *ABI {\n\ta, err := NewABI(s)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn a\n}\n\n// NewABIFromReader returns an ABI object from a reader\nfunc NewABIFromReader(r io.Reader) (*ABI, error) {\n\tvar abi *ABI\n\tdec := json.NewDecoder(r)\n\tif err := dec.Decode(&abi); err != nil {\n\t\treturn nil, err\n\t}\n\treturn abi, nil\n}\n\n// UnmarshalJSON implements json.Unmarshaler interface\nfunc (a *ABI) UnmarshalJSON(data []byte) error {\n\tvar fields []struct {\n\t\tType            string\n\t\tName            string\n\t\tConstant        bool\n\t\tAnonymous       bool\n\t\tStateMutability string\n\t\tInputs          []*ArgumentStr\n\t\tOutputs         []*ArgumentStr\n\t}\n\n\tif err := json.Unmarshal(data, &fields); err != nil {\n\t\treturn err\n\t}\n\n\tfor _, field := range fields {\n\t\tswitch field.Type {\n\t\tcase \"constructor\":\n\t\t\tif a.Constructor != nil {\n\t\t\t\treturn fmt.Errorf(\"multiple constructor declaration\")\n\t\t\t}\n\t\t\tinput, err := NewTupleTypeFromArgs(field.Inputs)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\ta.Constructor = &Method{\n\t\t\t\tInputs: input,\n\t\t\t}\n\n\t\tcase \"function\", \"\":\n\t\t\tc := field.Constant\n\t\t\tif field.StateMutability == \"view\" || field.StateMutability == \"pure\" {\n\t\t\t\tc = true\n\t\t\t}\n\n\t\t\tinputs, err := NewTupleTypeFromArgs(field.Inputs)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\toutputs, err := NewTupleTypeFromArgs(field.Outputs)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tmethod := &Method{\n\t\t\t\tName:    field.Name,\n\t\t\t\tConst:   c,\n\t\t\t\tInputs:  inputs,\n\t\t\t\tOutputs: outputs,\n\t\t\t}\n\t\t\ta.addMethod(method)\n\n\t\tcase \"event\":\n\t\t\tinput, err := NewTupleTypeFromArgs(field.Inputs)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tevent := &Event{\n\t\t\t\tName:      field.Name,\n\t\t\t\tAnonymous: field.Anonymous,\n\t\t\t\tInputs:    input,\n\t\t\t}\n\t\t\ta.addEvent(event)\n\n\t\tcase \"error\":\n\t\t\tinput, err := NewTupleTypeFromArgs(field.Inputs)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\terrObj := &Error{\n\t\t\t\tName:   field.Name,\n\t\t\t\tInputs: input,\n\t\t\t}\n\t\t\ta.addError(errObj)\n\n\t\tcase \"fallback\":\n\t\tcase \"receive\":\n\t\t\t// do nothing\n\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown field type '%s'\", field.Type)\n\t\t}\n\t}\n\treturn nil\n}\n\n// Method is a callable function in the contract\ntype Method struct {\n\tName    string\n\tConst   bool\n\tInputs  *Type\n\tOutputs *Type\n}\n\n// Sig returns the signature of the method\nfunc (m *Method) Sig() string {\n\treturn buildSignature(m.Name, m.Inputs)\n}\n\n// ID returns the id of the method\nfunc (m *Method) ID() []byte {\n\tk := acquireKeccak()\n\tk.Write([]byte(m.Sig()))\n\tdst := k.Sum(nil)[:4]\n\treleaseKeccak(k)\n\treturn dst\n}\n\n// Encode encodes the inputs with this function\nfunc (m *Method) Encode(args interface{}) ([]byte, error) {\n\tdata, err := Encode(args, m.Inputs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdata = append(m.ID(), data...)\n\treturn data, nil\n}\n\n// Decode decodes the output with this function\nfunc (m *Method) Decode(data []byte) (map[string]interface{}, error) {\n\tif len(data) == 0 {\n\t\treturn nil, fmt.Errorf(\"empty response\")\n\t}\n\trespInterface, err := Decode(m.Outputs, data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tresp := respInterface.(map[string]interface{})\n\treturn resp, nil\n}\n\n// MustNewMethod creates a new solidity method object or fails\nfunc MustNewMethod(name string) *Method {\n\tmethod, err := NewMethod(name)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn method\n}\n\nfunc NewMethod(name string) (*Method, error) {\n\tname, inputs, outputs, err := parseMethodSignature(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm := &Method{Name: name, Inputs: inputs, Outputs: outputs}\n\treturn m, nil\n}\n\nvar (\n\tfuncRegexpWithReturn    = regexp.MustCompile(`(\\w*)\\s*\\((.*)\\)(.*)\\s*returns\\s*\\((.*)\\)`)\n\tfuncRegexpWithoutReturn = regexp.MustCompile(`(\\w*)\\s*\\((.*)\\)(.*)`)\n)\n\nfunc parseMethodSignature(name string) (string, *Type, *Type, error) {\n\tname = strings.Replace(name, \"\\n\", \" \", -1)\n\tname = strings.Replace(name, \"\\t\", \" \", -1)\n\n\tname = strings.TrimPrefix(name, \"function \")\n\tname = strings.TrimSpace(name)\n\n\tvar funcName, inputArgs, outputArgs string\n\n\tif strings.Contains(name, \"returns\") {\n\t\tmatches := funcRegexpWithReturn.FindAllStringSubmatch(name, -1)\n\t\tif len(matches) == 0 {\n\t\t\treturn \"\", nil, nil, fmt.Errorf(\"no matches found\")\n\t\t}\n\t\tfuncName = strings.TrimSpace(matches[0][1])\n\t\tinputArgs = strings.TrimSpace(matches[0][2])\n\t\toutputArgs = strings.TrimSpace(matches[0][4])\n\t} else {\n\t\tmatches := funcRegexpWithoutReturn.FindAllStringSubmatch(name, -1)\n\t\tif len(matches) == 0 {\n\t\t\treturn \"\", nil, nil, fmt.Errorf(\"no matches found\")\n\t\t}\n\t\tfuncName = strings.TrimSpace(matches[0][1])\n\t\tinputArgs = strings.TrimSpace(matches[0][2])\n\t}\n\n\tinput, err := NewType(\"tuple(\" + inputArgs + \")\")\n\tif err != nil {\n\t\treturn \"\", nil, nil, err\n\t}\n\toutput, err := NewType(\"tuple(\" + outputArgs + \")\")\n\tif err != nil {\n\t\treturn \"\", nil, nil, err\n\t}\n\treturn funcName, input, output, nil\n}\n\n// Event is a triggered log mechanism\ntype Event struct {\n\tName      string\n\tAnonymous bool\n\tInputs    *Type\n}\n\n// Sig returns the signature of the event\nfunc (e *Event) Sig() string {\n\treturn buildSignature(e.Name, e.Inputs)\n}\n\n// ID returns the id of the event used during logs\nfunc (e *Event) ID() (res ethgo.Hash) {\n\tk := acquireKeccak()\n\tk.Write([]byte(e.Sig()))\n\tdst := k.Sum(nil)\n\treleaseKeccak(k)\n\tcopy(res[:], dst)\n\treturn\n}\n\n// MustNewEvent creates a new solidity event object or fails\nfunc MustNewEvent(name string) *Event {\n\tevnt, err := NewEvent(name)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn evnt\n}\n\n// NewEvent creates a new solidity event object using the signature\nfunc NewEvent(name string) (*Event, error) {\n\tname, typ, err := parseEventOrErrorSignature(\"event \", name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewEventFromType(name, typ), nil\n}\n\n// Error is a solidity error object\ntype Error struct {\n\tName   string\n\tInputs *Type\n}\n\n// NewError creates a new solidity error object\nfunc NewError(name string) (*Error, error) {\n\tname, typ, err := parseEventOrErrorSignature(\"error \", name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Error{Name: name, Inputs: typ}, nil\n}\n\nfunc parseEventOrErrorSignature(prefix string, name string) (string, *Type, error) {\n\tif !strings.HasPrefix(name, prefix) {\n\t\treturn \"\", nil, fmt.Errorf(\"prefix '%s' not found\", prefix)\n\t}\n\tname = strings.TrimPrefix(name, prefix)\n\n\tif !strings.HasSuffix(name, \")\") {\n\t\treturn \"\", nil, fmt.Errorf(\"failed to parse input, expected 'name(types)'\")\n\t}\n\tindx := strings.Index(name, \"(\")\n\tif indx == -1 {\n\t\treturn \"\", nil, fmt.Errorf(\"failed to parse input, expected 'name(types)'\")\n\t}\n\n\tfuncName, signature := name[:indx], name[indx:]\n\tsignature = \"tuple\" + signature\n\n\ttyp, err := NewType(signature)\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\treturn funcName, typ, nil\n}\n\n// NewEventFromType creates a new solidity event object using the name and type\nfunc NewEventFromType(name string, typ *Type) *Event {\n\treturn &Event{Name: name, Inputs: typ}\n}\n\n// Match checks wheter the log is from this event\nfunc (e *Event) Match(log *ethgo.Log) bool {\n\tif len(log.Topics) == 0 {\n\t\treturn false\n\t}\n\tif log.Topics[0] != e.ID() {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// ParseLog parses a log with this event\nfunc (e *Event) ParseLog(log *ethgo.Log) (map[string]interface{}, error) {\n\tif !e.Match(log) {\n\t\treturn nil, fmt.Errorf(\"log does not match this event\")\n\t}\n\treturn e.Inputs.ParseLog(log)\n}\n\nfunc buildSignature(name string, typ *Type) string {\n\ttypes := make([]string, len(typ.tuple))\n\tfor i, input := range typ.tuple {\n\t\ttypes[i] = strings.Replace(input.Elem.String(), \"tuple\", \"\", -1)\n\t}\n\treturn fmt.Sprintf(\"%v(%v)\", name, strings.Join(types, \",\"))\n}\n\n// ArgumentStr encodes a type object\ntype ArgumentStr struct {\n\tName         string\n\tType         string\n\tIndexed      bool\n\tComponents   []*ArgumentStr\n\tInternalType string\n}\n\nvar keccakPool = sync.Pool{\n\tNew: func() interface{} {\n\t\treturn sha3.NewLegacyKeccak256()\n\t},\n}\n\nfunc acquireKeccak() hash.Hash {\n\treturn keccakPool.Get().(hash.Hash)\n}\n\nfunc releaseKeccak(k hash.Hash) {\n\tk.Reset()\n\tkeccakPool.Put(k)\n}\n\nfunc NewABIFromList(humanReadableAbi []string) (*ABI, error) {\n\tres := &ABI{}\n\tfor _, c := range humanReadableAbi {\n\t\tif strings.HasPrefix(c, \"constructor\") {\n\t\t\ttyp, err := NewType(\"tuple\" + strings.TrimPrefix(c, \"constructor\"))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tres.Constructor = &Method{\n\t\t\t\tInputs: typ,\n\t\t\t}\n\n\t\t} else if strings.HasPrefix(c, \"function \") {\n\t\t\tmethod, err := NewMethod(c)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tres.addMethod(method)\n\n\t\t} else if strings.HasPrefix(c, \"event \") {\n\t\t\tevnt, err := NewEvent(c)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tres.addEvent(evnt)\n\n\t\t} else if strings.HasPrefix(c, \"error \") {\n\t\t\terrTyp, err := NewError(c)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tres.addError(errTyp)\n\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"either event or function expected\")\n\t\t}\n\t}\n\treturn res, nil\n}\n"
  },
  {
    "path": "abi/abi_test.go",
    "content": "package abi\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestAbi(t *testing.T) {\n\tmethodOutput := &Method{\n\t\tName:    \"abc\",\n\t\tInputs:  MustNewType(\"tuple()\"),\n\t\tOutputs: MustNewType(\"tuple()\"),\n\t}\n\tbalanceFunc := &Method{\n\t\tName:    \"balanceOf\",\n\t\tConst:   true,\n\t\tInputs:  MustNewType(\"tuple(address owner)\"),\n\t\tOutputs: MustNewType(\"tuple(uint256 balance)\"),\n\t}\n\n\tcases := []struct {\n\t\tInput  string\n\t\tOutput *ABI\n\t}{\n\t\t{\n\t\t\tInput: `[\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"abc\",\n\t\t\t\t\t\"type\": \"function\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"cde\",\n\t\t\t\t\t\"type\": \"event\",\n\t\t\t\t\t\"inputs\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"indexed\": true,\n\t\t\t\t\t\t\t\"name\": \"a\",\n\t\t\t\t\t\t\t\"type\": \"address\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"def\",\n\t\t\t\t\t\"type\": \"error\",\n\t\t\t\t\t\"inputs\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"indexed\": true,\n\t\t\t\t\t\t\t\"name\": \"a\",\n\t\t\t\t\t\t\t\"type\": \"address\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"function\",\n\t\t\t\t\t\"name\": \"balanceOf\",\n\t\t\t\t\t\"constant\": true,\n\t\t\t\t\t\"stateMutability\": \"view\",\n\t\t\t\t \t\"payable\": false,\n\t\t\t\t\t\"inputs\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t    \t\"type\": \"address\",\n\t\t\t\t\t    \t\"name\": \"owner\"\n\t\t\t\t\t   \t}\n\t\t\t\t\t],\n\t\t\t\t\t\"outputs\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t    \t\"type\": \"uint256\",\n\t\t\t\t\t    \t\"name\": \"balance\"\n\t\t\t\t\t   \t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]`,\n\t\t\tOutput: &ABI{\n\t\t\t\tEvents: map[string]*Event{\n\t\t\t\t\t\"cde\": {\n\t\t\t\t\t\tName:   \"cde\",\n\t\t\t\t\t\tInputs: MustNewType(\"tuple(address indexed a)\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tMethods: map[string]*Method{\n\t\t\t\t\t\"abc\":       methodOutput,\n\t\t\t\t\t\"balanceOf\": balanceFunc,\n\t\t\t\t},\n\t\t\t\tMethodsBySignature: map[string]*Method{\n\t\t\t\t\t\"abc()\":              methodOutput,\n\t\t\t\t\t\"balanceOf(address)\": balanceFunc,\n\t\t\t\t},\n\t\t\t\tErrors: map[string]*Error{\n\t\t\t\t\t\"def\": {\n\t\t\t\t\t\tName:   \"def\",\n\t\t\t\t\t\tInputs: MustNewType(\"tuple(address indexed a)\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tabi, err := NewABI(c.Input)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif !reflect.DeepEqual(abi, c.Output) {\n\t\t\t\tt.Fatal(\"bad\")\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAbi_InternalType(t *testing.T) {\n\tconst abiStr = `[\n        {\n            \"inputs\": [\n\t\t\t\t{\n\t\t\t\t\t\"components\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"internalType\": \"address\",\n\t\t\t\t\t\t\t\"type\": \"address\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"internalType\": \"uint256[4]\",\n\t\t\t\t\t\t\t\"type\": \"uint256[4]\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"internalType\": \"struct X\",\n\t\t\t\t\t\"name\": \"newSet\",\n\t\t\t\t\t\"type\": \"tuple[]\"\n\t\t\t\t},\n                {\n                    \"internalType\": \"custom_address\",\n                    \"name\": \"_to\",\n                    \"type\": \"address\"\n                }\n\t\t\t],\n\t\t\t\"outputs\": [],\n\t\t\t\"name\": \"transfer\",\n\t\t\t\"type\": \"function\"\n\t\t}\n\t]`\n\n\tabi, err := NewABI(abiStr)\n\trequire.NoError(t, err)\n\n\ttyp := abi.GetMethod(\"transfer\").Inputs\n\trequire.Equal(t, typ.tuple[0].Elem.InternalType(), \"struct X\")\n\trequire.Equal(t, typ.tuple[0].Elem.elem.tuple[0].Elem.InternalType(), \"address\")\n\trequire.Equal(t, typ.tuple[0].Elem.elem.tuple[1].Elem.InternalType(), \"uint256[4]\")\n\trequire.Equal(t, typ.tuple[1].Elem.InternalType(), \"custom_address\")\n}\n\nfunc TestAbi_Polymorphism(t *testing.T) {\n\t// This ABI contains 2 \"transfer\" functions (polymorphism)\n\tconst polymorphicABI = `[\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_token\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transfer\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n\t\t{\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transfer\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        }\n    ]`\n\n\tabi, err := NewABI(polymorphicABI)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tassert.Len(t, abi.Methods, 2)\n\tassert.Equal(t, abi.GetMethod(\"transfer\").Sig(), \"transfer(address,address,uint256)\")\n\tassert.Equal(t, abi.GetMethod(\"transfer0\").Sig(), \"transfer(address,uint256)\")\n\tassert.NotEmpty(t, abi.GetMethodBySignature(\"transfer(address,address,uint256)\"))\n\tassert.NotEmpty(t, abi.GetMethodBySignature(\"transfer(address,uint256)\"))\n}\n\nfunc TestAbi_HumanReadable(t *testing.T) {\n\tcases := []string{\n\t\t\"constructor(string symbol, string name)\",\n\t\t\"function transferFrom(address from, address to, uint256 value)\",\n\t\t\"function balanceOf(address owner) view returns (uint256 balance)\",\n\t\t\"function balanceOf() view returns ()\",\n\t\t\"event Transfer(address indexed from, address indexed to, address value)\",\n\t\t\"error InsufficientBalance(address owner, uint256 balance)\",\n\t\t\"function addPerson(tuple(string name, uint16 age) person)\",\n\t\t\"function addPeople(tuple(string name, uint16 age)[] person)\",\n\t\t\"function getPerson(uint256 id) view returns (tuple(string name, uint16 age))\",\n\t\t\"event PersonAdded(uint256 indexed id, tuple(string name, uint16 age) person)\",\n\t}\n\tvv, err := NewABIFromList(cases)\n\tassert.NoError(t, err)\n\n\t// make it nil to not compare it and avoid writing each method twice for the test\n\tvv.MethodsBySignature = nil\n\n\texpect := &ABI{\n\t\tConstructor: &Method{\n\t\t\tInputs: MustNewType(\"tuple(string symbol, string name)\"),\n\t\t},\n\t\tMethods: map[string]*Method{\n\t\t\t\"transferFrom\": {\n\t\t\t\tName:    \"transferFrom\",\n\t\t\t\tInputs:  MustNewType(\"tuple(address from, address to, uint256 value)\"),\n\t\t\t\tOutputs: MustNewType(\"tuple()\"),\n\t\t\t},\n\t\t\t\"balanceOf\": {\n\t\t\t\tName:    \"balanceOf\",\n\t\t\t\tInputs:  MustNewType(\"tuple(address owner)\"),\n\t\t\t\tOutputs: MustNewType(\"tuple(uint256 balance)\"),\n\t\t\t},\n\t\t\t\"balanceOf0\": {\n\t\t\t\tName:    \"balanceOf\",\n\t\t\t\tInputs:  MustNewType(\"tuple()\"),\n\t\t\t\tOutputs: MustNewType(\"tuple()\"),\n\t\t\t},\n\t\t\t\"addPerson\": {\n\t\t\t\tName:    \"addPerson\",\n\t\t\t\tInputs:  MustNewType(\"tuple(tuple(string name, uint16 age) person)\"),\n\t\t\t\tOutputs: MustNewType(\"tuple()\"),\n\t\t\t},\n\t\t\t\"addPeople\": {\n\t\t\t\tName:    \"addPeople\",\n\t\t\t\tInputs:  MustNewType(\"tuple(tuple(string name, uint16 age)[] person)\"),\n\t\t\t\tOutputs: MustNewType(\"tuple()\"),\n\t\t\t},\n\t\t\t\"getPerson\": {\n\t\t\t\tName:    \"getPerson\",\n\t\t\t\tInputs:  MustNewType(\"tuple(uint256 id)\"),\n\t\t\t\tOutputs: MustNewType(\"tuple(tuple(string name, uint16 age))\"),\n\t\t\t},\n\t\t},\n\t\tEvents: map[string]*Event{\n\t\t\t\"Transfer\": {\n\t\t\t\tName:   \"Transfer\",\n\t\t\t\tInputs: MustNewType(\"tuple(address indexed from, address indexed to, address value)\"),\n\t\t\t},\n\t\t\t\"PersonAdded\": {\n\t\t\t\tName:   \"PersonAdded\",\n\t\t\t\tInputs: MustNewType(\"tuple(uint256 indexed id, tuple(string name, uint16 age) person)\"),\n\t\t\t},\n\t\t},\n\t\tErrors: map[string]*Error{\n\t\t\t\"InsufficientBalance\": {\n\t\t\t\tName:   \"InsufficientBalance\",\n\t\t\t\tInputs: MustNewType(\"tuple(address owner, uint256 balance)\"),\n\t\t\t},\n\t\t},\n\t}\n\tassert.Equal(t, expect, vv)\n}\n\nfunc TestAbi_ParseMethodSignature(t *testing.T) {\n\tcases := []struct {\n\t\tsignature string\n\t\tname      string\n\t\tinput     string\n\t\toutput    string\n\t}{\n\t\t{\n\t\t\t// both input and output\n\t\t\tsignature: \"function approve(address to) returns (address)\",\n\t\t\tname:      \"approve\",\n\t\t\tinput:     \"tuple(address)\",\n\t\t\toutput:    \"tuple(address)\",\n\t\t},\n\t\t{\n\t\t\t// no input\n\t\t\tsignature: \"function approve() returns (address)\",\n\t\t\tname:      \"approve\",\n\t\t\tinput:     \"tuple()\",\n\t\t\toutput:    \"tuple(address)\",\n\t\t},\n\t\t{\n\t\t\t// no output\n\t\t\tsignature: \"function approve(address)\",\n\t\t\tname:      \"approve\",\n\t\t\tinput:     \"tuple(address)\",\n\t\t\toutput:    \"tuple()\",\n\t\t},\n\t\t{\n\t\t\t// multiline\n\t\t\tsignature: `function a(\n\t\t\t\tuint256 b,\n\t\t\t\taddress[] c\n\t\t\t)\n\t\t\t\treturns\n\t\t\t\t(\n\t\t\t\tuint256[] d\n\t\t\t)`,\n\t\t\tname:   \"a\",\n\t\t\tinput:  \"tuple(uint256,address[])\",\n\t\t\toutput: \"tuple(uint256[])\",\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tname, input, output, err := parseMethodSignature(c.signature)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tassert.Equal(t, name, c.name)\n\n\t\tif input != nil {\n\t\t\tassert.Equal(t, c.input, input.String())\n\t\t} else {\n\t\t\tassert.Equal(t, c.input, \"\")\n\t\t}\n\n\t\tif input != nil {\n\t\t\tassert.Equal(t, c.output, output.String())\n\t\t} else {\n\t\t\tassert.Equal(t, c.output, \"\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "abi/decode.go",
    "content": "package abi\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"strconv\"\n\n\t\"github.com/mitchellh/mapstructure\"\n\t\"github.com/umbracle/ethgo\"\n)\n\n// Decode decodes the input with a given type\nfunc Decode(t *Type, input []byte) (interface{}, error) {\n\tif len(input) == 0 {\n\t\treturn nil, fmt.Errorf(\"empty input\")\n\t}\n\tval, _, err := decode(t, input)\n\treturn val, err\n}\n\n// DecodeStruct decodes the input with a type to a struct\nfunc DecodeStruct(t *Type, input []byte, out interface{}) error {\n\tval, err := Decode(t, input)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdc := &mapstructure.DecoderConfig{\n\t\tResult:           out,\n\t\tWeaklyTypedInput: true,\n\t\tTagName:          \"abi\",\n\t}\n\tms, err := mapstructure.NewDecoder(dc)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err = ms.Decode(val); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc decode(t *Type, input []byte) (interface{}, []byte, error) {\n\tvar data []byte\n\tvar length int\n\tvar err error\n\n\t// safe check, input should be at least 32 bytes\n\tif len(input) < 32 {\n\t\treturn nil, nil, fmt.Errorf(\"incorrect length\")\n\t}\n\n\tif t.isVariableInput() {\n\t\tlength, err = readLength(input)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t} else {\n\t\tdata = input[:32]\n\t}\n\n\tswitch t.kind {\n\tcase KindTuple:\n\t\treturn decodeTuple(t, input)\n\n\tcase KindSlice:\n\t\treturn decodeArraySlice(t, input[32:], length)\n\n\tcase KindArray:\n\t\treturn decodeArraySlice(t, input, t.size)\n\t}\n\n\tvar val interface{}\n\tswitch t.kind {\n\tcase KindBool:\n\t\tval, err = decodeBool(data)\n\n\tcase KindInt, KindUInt:\n\t\tval = readInteger(t, data)\n\n\tcase KindString:\n\t\tval = string(input[32 : 32+length])\n\n\tcase KindBytes:\n\t\tval = input[32 : 32+length]\n\n\tcase KindAddress:\n\t\tval, err = readAddr(data)\n\n\tcase KindFixedBytes:\n\t\tval, err = readFixedBytes(t, data)\n\n\tcase KindFunction:\n\t\tval, err = readFunctionType(t, data)\n\n\tdefault:\n\t\treturn nil, nil, fmt.Errorf(\"decoding not available for type '%s'\", t.kind)\n\t}\n\n\treturn val, input[32:], err\n}\n\nvar (\n\tmaxUint256 = big.NewInt(0).Add(\n\t\tbig.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil),\n\t\tbig.NewInt(-1))\n\tmaxInt256 = big.NewInt(0).Add(\n\t\tbig.NewInt(0).Exp(big.NewInt(2), big.NewInt(255), nil),\n\t\tbig.NewInt(-1))\n)\n\nfunc readAddr(b []byte) (ethgo.Address, error) {\n\tres := ethgo.Address{}\n\tif len(b) != 32 {\n\t\treturn res, fmt.Errorf(\"len is not correct\")\n\t}\n\tcopy(res[:], b[12:])\n\treturn res, nil\n}\n\nfunc readInteger(t *Type, b []byte) interface{} {\n\tswitch t.t.Kind() {\n\tcase reflect.Uint8:\n\t\treturn b[len(b)-1]\n\n\tcase reflect.Uint16:\n\t\treturn binary.BigEndian.Uint16(b[len(b)-2:])\n\n\tcase reflect.Uint32:\n\t\treturn binary.BigEndian.Uint32(b[len(b)-4:])\n\n\tcase reflect.Uint64:\n\t\treturn binary.BigEndian.Uint64(b[len(b)-8:])\n\n\tcase reflect.Int8:\n\t\treturn int8(b[len(b)-1])\n\n\tcase reflect.Int16:\n\t\treturn int16(binary.BigEndian.Uint16(b[len(b)-2:]))\n\n\tcase reflect.Int32:\n\t\treturn int32(binary.BigEndian.Uint32(b[len(b)-4:]))\n\n\tcase reflect.Int64:\n\t\treturn int64(binary.BigEndian.Uint64(b[len(b)-8:]))\n\n\tdefault:\n\t\tret := new(big.Int).SetBytes(b)\n\t\tif t.kind == KindUInt {\n\t\t\treturn ret\n\t\t}\n\n\t\tif ret.Cmp(maxInt256) > 0 {\n\t\t\tret.Add(maxUint256, big.NewInt(0).Neg(ret))\n\t\t\tret.Add(ret, big.NewInt(1))\n\t\t\tret.Neg(ret)\n\t\t}\n\t\treturn ret\n\t}\n}\n\nfunc readFunctionType(t *Type, word []byte) ([24]byte, error) {\n\tres := [24]byte{}\n\tif !allZeros(word[24:32]) {\n\t\treturn res, fmt.Errorf(\"function type expects the last 8 bytes to be empty but found: %b\", word[24:32])\n\t}\n\tcopy(res[:], word[0:24])\n\treturn res, nil\n}\n\nfunc readFixedBytes(t *Type, word []byte) (interface{}, error) {\n\tarray := reflect.New(t.t).Elem()\n\treflect.Copy(array, reflect.ValueOf(word[0:t.size]))\n\treturn array.Interface(), nil\n}\n\nfunc decodeTuple(t *Type, data []byte) (interface{}, []byte, error) {\n\tres := make(map[string]interface{})\n\n\torig := data\n\torigLen := len(orig)\n\tfor indx, arg := range t.tuple {\n\t\tif len(data) < 32 {\n\t\t\treturn nil, nil, fmt.Errorf(\"incorrect length\")\n\t\t}\n\n\t\tentry := data\n\t\tif arg.Elem.isDynamicType() {\n\t\t\toffset, err := readOffset(data, origLen)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tentry = orig[offset:]\n\t\t}\n\n\t\tval, tail, err := decode(arg.Elem, entry)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tif !arg.Elem.isDynamicType() {\n\t\t\tdata = tail\n\t\t} else {\n\t\t\tdata = data[32:]\n\t\t}\n\n\t\tname := arg.Name\n\t\tif name == \"\" {\n\t\t\tname = strconv.Itoa(indx)\n\t\t}\n\t\tif _, ok := res[name]; !ok {\n\t\t\tres[name] = val\n\t\t} else {\n\t\t\treturn nil, nil, fmt.Errorf(\"tuple with repeated values\")\n\t\t}\n\t}\n\treturn res, data, nil\n}\n\nfunc decodeArraySlice(t *Type, data []byte, size int) (interface{}, []byte, error) {\n\tif size < 0 {\n\t\treturn nil, nil, fmt.Errorf(\"size is lower than zero\")\n\t}\n\tif 32*size > len(data) {\n\t\treturn nil, nil, fmt.Errorf(\"size is too big\")\n\t}\n\n\tvar res reflect.Value\n\tif t.kind == KindSlice {\n\t\tres = reflect.MakeSlice(t.t, size, size)\n\t} else if t.kind == KindArray {\n\t\tres = reflect.New(t.t).Elem()\n\t}\n\n\torig := data\n\torigLen := len(orig)\n\tfor indx := 0; indx < size; indx++ {\n\t\tisDynamic := t.elem.isDynamicType()\n\n\t\tif len(data) < 32 {\n\t\t\treturn nil, nil, fmt.Errorf(\"incorrect length\")\n\t\t}\n\n\t\tentry := data\n\t\tif isDynamic {\n\t\t\toffset, err := readOffset(data, origLen)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tentry = orig[offset:]\n\t\t}\n\n\t\tval, tail, err := decode(t.elem, entry)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tif !isDynamic {\n\t\t\tdata = tail\n\t\t} else {\n\t\t\tdata = data[32:]\n\t\t}\n\t\tres.Index(indx).Set(reflect.ValueOf(val))\n\t}\n\treturn res.Interface(), data, nil\n}\n\nfunc decodeBool(data []byte) (interface{}, error) {\n\tswitch data[31] {\n\tcase 0:\n\t\treturn false, nil\n\tcase 1:\n\t\treturn true, nil\n\tdefault:\n\t\treturn false, fmt.Errorf(\"bad boolean\")\n\t}\n}\n\nfunc readOffset(data []byte, len int) (int, error) {\n\toffsetBig := big.NewInt(0).SetBytes(data[0:32])\n\tif offsetBig.BitLen() > 63 {\n\t\treturn 0, fmt.Errorf(\"offset larger than int64: %v\", offsetBig.Int64())\n\t}\n\toffset := int(offsetBig.Int64())\n\tif offset > len {\n\t\treturn 0, fmt.Errorf(\"offset insufficient %v require %v\", len, offset)\n\t}\n\treturn offset, nil\n}\n\nfunc readLength(data []byte) (int, error) {\n\tlengthBig := big.NewInt(0).SetBytes(data[0:32])\n\tif lengthBig.BitLen() > 63 {\n\t\treturn 0, fmt.Errorf(\"length larger than int64: %v\", lengthBig.Int64())\n\t}\n\tlength := int(lengthBig.Uint64())\n\n\t// if we trim the length in the data there should be enough\n\t// bytes to cover the length\n\tif length > len(data)-32 {\n\t\treturn 0, fmt.Errorf(\"length insufficient %v require %v\", len(data), length)\n\t}\n\treturn length, nil\n}\n\nfunc allZeros(b []byte) bool {\n\tfor _, i := range b {\n\t\tif i != 0 {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "abi/decode_test.go",
    "content": "package abi\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestDecode_BytesBound(t *testing.T) {\n\ttyp := MustNewType(\"tuple(string)\")\n\tdecodeTuple(typ, nil) // it should not panic\n}\n\nfunc TestDecode_DynamicLengthOutOfBounds(t *testing.T) {\n\tinput := []byte(\"00000000000000000000000000000000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 00000000000000000000000000\")\n\ttyp := MustNewType(\"tuple(bytes32, bytes, bytes)\")\n\n\t_, err := Decode(typ, input)\n\trequire.Error(t, err)\n}\n"
  },
  {
    "path": "abi/encode.go",
    "content": "package abi\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\nvar (\n\tzero = big.NewInt(0)\n\tone  = big.NewInt(1)\n)\n\n// Encode encodes a value\nfunc Encode(v interface{}, t *Type) ([]byte, error) {\n\treturn encode(reflect.ValueOf(v), t)\n}\n\nfunc encode(v reflect.Value, t *Type) ([]byte, error) {\n\tif v.Kind() == reflect.Interface {\n\t\tv = v.Elem()\n\t}\n\n\tswitch t.kind {\n\tcase KindSlice, KindArray:\n\t\treturn encodeSliceAndArray(v, t)\n\n\tcase KindTuple:\n\t\treturn encodeTuple(v, t)\n\n\tcase KindString:\n\t\treturn encodeString(v)\n\n\tcase KindBool:\n\t\treturn encodeBool(v)\n\n\tcase KindAddress:\n\t\treturn encodeAddress(v)\n\n\tcase KindInt, KindUInt:\n\t\treturn encodeNum(v)\n\n\tcase KindBytes:\n\t\treturn encodeBytes(v)\n\n\tcase KindFixedBytes, KindFunction:\n\t\treturn encodeFixedBytes(v)\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"encoding not available for type '%s'\", t.kind)\n\t}\n}\n\nfunc encodeSliceAndArray(v reflect.Value, t *Type) ([]byte, error) {\n\tif v.Kind() != reflect.Array && v.Kind() != reflect.Slice {\n\t\treturn nil, encodeErr(v, t.kind.String())\n\t}\n\n\tif v.Kind() == reflect.Array && t.kind != KindArray {\n\t\treturn nil, fmt.Errorf(\"expected array\")\n\t} else if v.Kind() == reflect.Slice && t.kind != KindSlice {\n\t\treturn nil, fmt.Errorf(\"expected slice\")\n\t}\n\n\tif t.kind == KindArray && t.size != v.Len() {\n\t\treturn nil, fmt.Errorf(\"array len incompatible\")\n\t}\n\n\tvar ret, tail []byte\n\tif t.isVariableInput() {\n\t\tret = append(ret, packNum(v.Len())...)\n\t}\n\n\toffset := 0\n\tisDynamic := t.elem.isDynamicType()\n\tif isDynamic {\n\t\toffset = getTypeSize(t.elem) * v.Len()\n\t}\n\n\tfor i := 0; i < v.Len(); i++ {\n\t\tval, err := encode(v.Index(i), t.elem)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !isDynamic {\n\t\t\tret = append(ret, val...)\n\t\t} else {\n\t\t\tret = append(ret, packNum(offset)...)\n\t\t\toffset += len(val)\n\t\t\ttail = append(tail, val...)\n\t\t}\n\t}\n\treturn append(ret, tail...), nil\n}\n\nfunc encodeTuple(v reflect.Value, t *Type) ([]byte, error) {\n\tif v.Kind() == reflect.Ptr {\n\t\tv = v.Elem()\n\t}\n\n\tvar err error\n\tisList := true\n\n\tswitch v.Kind() {\n\tcase reflect.Slice, reflect.Array:\n\tcase reflect.Map:\n\t\tisList = false\n\n\tcase reflect.Struct:\n\t\tisList = false\n\t\tv, err = mapFromStruct(v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\tdefault:\n\t\treturn nil, encodeErr(v, \"tuple\")\n\t}\n\n\tif v.Len() < len(t.tuple) {\n\t\treturn nil, fmt.Errorf(\"expected at least the same length\")\n\t}\n\n\toffset := 0\n\tfor _, elem := range t.tuple {\n\t\toffset += getTypeSize(elem.Elem)\n\t}\n\n\tvar ret, tail []byte\n\tvar aux reflect.Value\n\n\tfor i, elem := range t.tuple {\n\t\tif isList {\n\t\t\taux = v.Index(i)\n\t\t} else {\n\t\t\tname := elem.Name\n\t\t\tif name == \"\" {\n\t\t\t\tname = strconv.Itoa(i)\n\t\t\t}\n\t\t\taux = v.MapIndex(reflect.ValueOf(name))\n\t\t}\n\t\tif aux.Kind() == reflect.Invalid {\n\t\t\treturn nil, fmt.Errorf(\"cannot get key %s\", elem.Name)\n\t\t}\n\n\t\tval, err := encode(aux, elem.Elem)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif elem.Elem.isDynamicType() {\n\t\t\tret = append(ret, packNum(offset)...)\n\t\t\ttail = append(tail, val...)\n\t\t\toffset += len(val)\n\t\t} else {\n\t\t\tret = append(ret, val...)\n\t\t}\n\t}\n\n\treturn append(ret, tail...), nil\n}\n\nfunc convertArrayToBytes(value reflect.Value) reflect.Value {\n\tslice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())\n\treflect.Copy(slice, value)\n\treturn slice\n}\n\nfunc encodeFixedBytes(v reflect.Value) ([]byte, error) {\n\tif v.Kind() == reflect.Array {\n\t\tv = convertArrayToBytes(v)\n\t}\n\tif v.Kind() == reflect.String {\n\t\tvalue, err := decodeHex(v.String())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tv = reflect.ValueOf(value)\n\t}\n\treturn rightPad(v.Bytes(), 32), nil\n}\n\nfunc encodeAddress(v reflect.Value) ([]byte, error) {\n\tif v.Kind() == reflect.Array {\n\t\tv = convertArrayToBytes(v)\n\t}\n\tif v.Kind() == reflect.String {\n\t\tvar addr ethgo.Address\n\t\tif err := addr.UnmarshalText([]byte(v.String())); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv = reflect.ValueOf(addr.Bytes())\n\t}\n\treturn leftPad(v.Bytes(), 32), nil\n}\n\nfunc encodeBytes(v reflect.Value) ([]byte, error) {\n\tif v.Kind() == reflect.Array {\n\t\tv = convertArrayToBytes(v)\n\t}\n\tif v.Kind() == reflect.String {\n\t\tvalue, err := decodeHex(v.String())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tv = reflect.ValueOf(value)\n\t}\n\treturn packBytesSlice(v.Bytes(), v.Len())\n}\n\nfunc encodeString(v reflect.Value) ([]byte, error) {\n\tif v.Kind() != reflect.String {\n\t\treturn nil, encodeErr(v, \"string\")\n\t}\n\treturn packBytesSlice([]byte(v.String()), v.Len())\n}\n\nfunc packBytesSlice(buf []byte, l int) ([]byte, error) {\n\tlen, err := encodeNum(reflect.ValueOf(l))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn append(len, rightPad(buf, (l+31)/32*32)...), nil\n}\n\nfunc packNum(offset int) []byte {\n\tn, _ := encodeNum(reflect.ValueOf(offset))\n\treturn n\n}\n\nfunc encodeNum(v reflect.Value) ([]byte, error) {\n\tswitch v.Kind() {\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\treturn toU256(new(big.Int).SetUint64(v.Uint())), nil\n\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\treturn toU256(big.NewInt(v.Int())), nil\n\n\tcase reflect.Ptr:\n\t\tif v.Type() != bigIntT {\n\t\t\treturn nil, encodeErr(v.Elem(), \"number\")\n\t\t}\n\t\treturn toU256(v.Interface().(*big.Int)), nil\n\n\tcase reflect.Float64:\n\t\treturn encodeNum(reflect.ValueOf(int64(v.Float())))\n\n\tcase reflect.String:\n\t\tn, ok := new(big.Int).SetString(v.String(), 10)\n\t\tif !ok {\n\t\t\tn, ok = new(big.Int).SetString(v.String()[2:], 16)\n\t\t\tif !ok {\n\t\t\t\treturn nil, encodeErr(v, \"number\")\n\t\t\t}\n\t\t}\n\t\treturn encodeNum(reflect.ValueOf(n))\n\n\tdefault:\n\t\treturn nil, encodeErr(v, \"number\")\n\t}\n}\n\nfunc encodeBool(v reflect.Value) ([]byte, error) {\n\tif v.Kind() != reflect.Bool {\n\t\treturn nil, encodeErr(v, \"bool\")\n\t}\n\tif v.Bool() {\n\t\treturn leftPad(one.Bytes(), 32), nil\n\t}\n\treturn leftPad(zero.Bytes(), 32), nil\n}\n\nfunc encodeErr(v reflect.Value, t string) error {\n\treturn fmt.Errorf(\"failed to encode %s as %s\", v.Kind().String(), t)\n}\n\nfunc mapFromStruct(v reflect.Value) (reflect.Value, error) {\n\tres := map[string]interface{}{}\n\ttyp := v.Type()\n\tfor i := 0; i < v.NumField(); i++ {\n\t\tf := typ.Field(i)\n\t\tif f.PkgPath != \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\ttagValue := f.Tag.Get(\"abi\")\n\t\tif tagValue == \"-\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tname := strings.ToLower(f.Name)\n\t\tif tagValue != \"\" {\n\t\t\tname = tagValue\n\t\t}\n\t\tif _, ok := res[name]; !ok {\n\t\t\tres[name] = v.Field(i).Interface()\n\t\t}\n\t}\n\treturn reflect.ValueOf(res), nil\n}\n\nvar (\n\ttt256   = new(big.Int).Lsh(big.NewInt(1), 256)   // 2 ** 256\n\ttt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) // 2 ** 256 - 1\n)\n\n// U256 converts a big Int into a 256bit EVM number.\nfunc toU256(n *big.Int) []byte {\n\tb := new(big.Int)\n\tb = b.Set(n)\n\n\tif b.Sign() < 0 || b.BitLen() > 256 {\n\t\tb.And(b, tt256m1)\n\t}\n\n\treturn leftPad(b.Bytes(), 32)\n}\n\nfunc padBytes(b []byte, size int, left bool) []byte {\n\tl := len(b)\n\tif l == size {\n\t\treturn b\n\t}\n\tif l > size {\n\t\treturn b[l-size:]\n\t}\n\ttmp := make([]byte, size)\n\tif left {\n\t\tcopy(tmp[size-l:], b)\n\t} else {\n\t\tcopy(tmp, b)\n\t}\n\treturn tmp\n}\n\nfunc leftPad(b []byte, size int) []byte {\n\treturn padBytes(b, size, true)\n}\n\nfunc rightPad(b []byte, size int) []byte {\n\treturn padBytes(b, size, false)\n}\n\nfunc encodeHex(b []byte) string {\n\treturn \"0x\" + hex.EncodeToString(b)\n}\n\nfunc decodeHex(str string) ([]byte, error) {\n\tif strings.HasPrefix(str, \"0x\") {\n\t\tstr = str[2:]\n\t}\n\tbuf, err := hex.DecodeString(str)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not decode hex: %v\", err)\n\t}\n\treturn buf, nil\n}\n"
  },
  {
    "path": "abi/encoding_test.go",
    "content": "package abi\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"os\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/compiler\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc mustDecodeHex(str string) []byte {\n\tbuf, err := decodeHex(str)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"could not decode hex: %v\", err))\n\t}\n\treturn buf\n}\n\nfunc TestEncoding(t *testing.T) {\n\tcases := []struct {\n\t\tType  string\n\t\tInput interface{}\n\t}{\n\t\t{\n\t\t\t\"uint40\",\n\t\t\tbig.NewInt(50),\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\tbig.NewInt(2),\n\t\t},\n\t\t{\n\t\t\t\"int256[]\",\n\t\t\t[]*big.Int{big.NewInt(1), big.NewInt(2)},\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\tbig.NewInt(-10),\n\t\t},\n\t\t{\n\t\t\t\"bytes5\",\n\t\t\t[5]byte{0x1, 0x2, 0x3, 0x4, 0x5},\n\t\t},\n\t\t{\n\t\t\t\"bytes\",\n\t\t\tmustDecodeHex(\"0x12345678911121314151617181920211\"),\n\t\t},\n\t\t{\n\t\t\t\"string\",\n\t\t\t\"foobar\",\n\t\t},\n\t\t{\n\t\t\t\"uint8[][2]\",\n\t\t\t[2][]uint8{{1}, {1}},\n\t\t},\n\t\t{\n\t\t\t\"address[]\",\n\t\t\t[]ethgo.Address{{1}, {2}},\n\t\t},\n\t\t{\n\t\t\t\"bytes10[]\",\n\t\t\t[][10]byte{\n\t\t\t\t{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10},\n\t\t\t\t{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"bytes[]\",\n\t\t\t[][]byte{\n\t\t\t\tmustDecodeHex(\"0x11\"),\n\t\t\t\tmustDecodeHex(\"0x22\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"uint32[2][3][4]\",\n\t\t\t[4][3][2]uint32{{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}, {{13, 14}, {15, 16}, {17, 18}}, {{19, 20}, {21, 22}, {23, 24}}},\n\t\t},\n\t\t{\n\t\t\t\"uint8[]\",\n\t\t\t[]uint8{1, 2},\n\t\t},\n\t\t{\n\t\t\t\"string[]\",\n\t\t\t[]string{\"hello\", \"foobar\"},\n\t\t},\n\t\t{\n\t\t\t\"string[2]\",\n\t\t\t[2]string{\"hello\", \"foobar\"},\n\t\t},\n\t\t{\n\t\t\t\"bytes32[][]\",\n\t\t\t[][][32]uint8{{{1}, {2}}, {{3}, {4}, {5}}},\n\t\t},\n\t\t{\n\t\t\t\"bytes32[][2]\",\n\t\t\t[2][][32]uint8{{{1}, {2}}, {{3}, {4}, {5}}},\n\t\t},\n\t\t{\n\t\t\t\"bytes32[3][2]\",\n\t\t\t[2][3][32]uint8{{{1}, {2}, {3}}, {{3}, {4}, {5}}},\n\t\t},\n\t\t{\n\t\t\t\"uint16[][2][]\",\n\t\t\t[][2][]uint16{\n\t\t\t\t{{0, 1}, {2, 3}},\n\t\t\t\t{{4, 5}, {6, 7}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(bytes[] a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [][]byte{{0xf0, 0xf0, 0xf0}, {0xf0, 0xf0, 0xf0}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint32[2][][] a)\",\n\t\t\t// `[{\"type\": \"uint32[2][][]\"}]`,\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [][][2]uint32{{{uint32(1), uint32(200)}, {uint32(1), uint32(1000)}}, {{uint32(1), uint32(200)}, {uint32(1), uint32(1000)}}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint64[2] a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [2]uint64{1, 2},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint32[2][3][4] a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [4][3][2]uint32{{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}, {{13, 14}, {15, 16}, {17, 18}}, {{19, 20}, {21, 22}, {23, 24}}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(int32[] a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": []int32{1, 2},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(int32 a, int32 b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": int32(1),\n\t\t\t\t\"b\": int32(2),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(string a, int32 b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": \"Hello Worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n\t\t\t\t\"b\": int32(2),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(int32[2] a, int32[] b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [2]int32{1, 2},\n\t\t\t\t\"b\": []int32{4, 5, 6},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// tuple with array slice\n\t\t\t\"tuple(address[] a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": []ethgo.Address{\n\t\t\t\t\t{0x1},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// First dynamic second static\n\t\t\t\"tuple(int32[] a, int32[2] b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": []int32{1, 2, 3},\n\t\t\t\t\"b\": [2]int32{4, 5},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// Both dynamic\n\t\t\t\"tuple(int32[] a, int32[] b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": []int32{1, 2, 3},\n\t\t\t\t\"b\": []int32{4, 5, 6},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(string a, int64 b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": \"hello World\",\n\t\t\t\t\"b\": int64(266),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// tuple array\n\t\t\t\"tuple(int32 a, int32 b)[2]\",\n\t\t\t[2]map[string]interface{}{\n\t\t\t\t{\n\t\t\t\t\t\"a\": int32(1),\n\t\t\t\t\t\"b\": int32(2),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"a\": int32(3),\n\t\t\t\t\t\"b\": int32(4),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\t// tuple array with dynamic content\n\t\t\t\"tuple(int32[] a)[2]\",\n\t\t\t[2]map[string]interface{}{\n\t\t\t\t{\n\t\t\t\t\t\"a\": []int32{1, 2, 3},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"a\": []int32{4, 5, 6},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// tuple slice\n\t\t\t\"tuple(int32 a, int32[] b)[]\",\n\t\t\t[]map[string]interface{}{\n\t\t\t\t{\n\t\t\t\t\t\"a\": int32(1),\n\t\t\t\t\t\"b\": []int32{2, 3},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"a\": int32(4),\n\t\t\t\t\t\"b\": []int32{5, 6},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// nested tuple\n\t\t\t\"tuple(tuple(int32 c, int32[] d) a, int32[] b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": map[string]interface{}{\n\t\t\t\t\t\"c\": int32(5),\n\t\t\t\t\t\"d\": []int32{3, 4},\n\t\t\t\t},\n\t\t\t\t\"b\": []int32{1, 2},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint8[2] a, tuple(uint8 e, uint32 f)[2] b, uint16 c, uint64[2][1] d)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [2]uint8{uint8(1), uint8(2)},\n\t\t\t\t\"b\": [2]map[string]interface{}{\n\t\t\t\t\t{\n\t\t\t\t\t\t\"e\": uint8(10),\n\t\t\t\t\t\t\"f\": uint32(11),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"e\": uint8(20),\n\t\t\t\t\t\t\"f\": uint32(21),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"c\": uint16(3),\n\t\t\t\t\"d\": [1][2]uint64{{uint64(4), uint64(5)}},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint16 a, uint16 b)[1][]\",\n\t\t\t[][1]map[string]interface{}{\n\t\t\t\t{\n\t\t\t\t\t{\n\t\t\t\t\t\t\"a\": uint16(1),\n\t\t\t\t\t\t\"b\": uint16(2),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t{\n\t\t\t\t\t\t\"a\": uint16(3),\n\t\t\t\t\t\t\"b\": uint16(4),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t{\n\t\t\t\t\t\t\"a\": uint16(5),\n\t\t\t\t\t\t\"b\": uint16(6),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t{\n\t\t\t\t\t\t\"a\": uint16(7),\n\t\t\t\t\t\t\"b\": uint16(8),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint64[][] a, tuple(uint8 a, uint32 b)[1] b, uint64 c)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": [][]uint64{\n\t\t\t\t\t{3, 4},\n\t\t\t\t},\n\t\t\t\t\"b\": [1]map[string]interface{}{\n\t\t\t\t\t{\n\t\t\t\t\t\t\"a\": uint8(1),\n\t\t\t\t\t\t\"b\": uint32(2),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"c\": uint64(10),\n\t\t\t},\n\t\t},\n\t}\n\n\tserver := testutil.NewTestServer(t)\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\ttt, err := NewType(c.Type)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif err := testEncodeDecode(t, server, tt, c.Input); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestEncodingBestEffort(t *testing.T) {\n\tstrAddress := \"0xdbb881a51CD4023E4400CEF3ef73046743f08da3\"\n\tethAddress := ethgo.HexToAddress(strAddress)\n\toverflowBigInt, _ := new(big.Int).SetString(\"50000000000000000000000000000000000000\", 10)\n\n\tcases := []struct {\n\t\tType     string\n\t\tInput    interface{}\n\t\tExpected interface{}\n\t}{\n\t\t{\n\t\t\t\"uint40\",\n\t\t\tfloat64(50),\n\t\t\tbig.NewInt(50),\n\t\t},\n\t\t{\n\t\t\t\"uint40\",\n\t\t\t\"50\",\n\t\t\tbig.NewInt(50),\n\t\t},\n\t\t{\n\t\t\t\"uint40\",\n\t\t\t\"0x32\",\n\t\t\tbig.NewInt(50),\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\tfloat64(2),\n\t\t\tbig.NewInt(2),\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\t\"50000000000000000000000000000000000000\",\n\t\t\toverflowBigInt,\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\t\"0x259DA6542D43623D04C5112000000000\",\n\t\t\toverflowBigInt,\n\t\t},\n\t\t{\n\t\t\t\"int256[]\",\n\t\t\t[]interface{}{float64(1), float64(2)},\n\t\t\t[]*big.Int{big.NewInt(1), big.NewInt(2)},\n\t\t},\n\t\t{\n\t\t\t\"int256[]\",\n\t\t\t[]interface{}{\"1\", \"2\"},\n\t\t\t[]*big.Int{big.NewInt(1), big.NewInt(2)},\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\tfloat64(-10),\n\t\t\tbig.NewInt(-10),\n\t\t},\n\t\t{\n\t\t\t\"int256\",\n\t\t\t\"-10\",\n\t\t\tbig.NewInt(-10),\n\t\t},\n\t\t{\n\t\t\t\"address[]\",\n\t\t\t[]interface{}{strAddress, strAddress},\n\t\t\t[]ethgo.Address{ethAddress, ethAddress},\n\t\t},\n\t\t{\n\t\t\t\"uint8[]\",\n\t\t\t[]interface{}{float64(1), float64(2)},\n\t\t\t[]uint8{1, 2},\n\t\t},\n\t\t{\n\t\t\t\"uint8[]\",\n\t\t\t[]interface{}{\"1\", \"2\"},\n\t\t\t[]uint8{1, 2},\n\t\t},\n\t\t{\n\t\t\t\"bytes\",\n\t\t\t\"0x11\",\n\t\t\t[]uint8{17},\n\t\t},\n\t\t{\n\t\t\t\"bytes32\",\n\t\t\t\"0x11\",\n\t\t\t[32]uint8{17},\n\t\t},\n\t\t{\n\t\t\t\"tuple(address a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": strAddress,\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": ethAddress,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(address[] a)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": []interface{}{strAddress, strAddress},\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": []ethgo.Address{ethAddress, ethAddress},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(address a, int64 b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": strAddress,\n\t\t\t\t\"b\": float64(266),\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": ethAddress,\n\t\t\t\t\"b\": int64(266),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(address a, int256 b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": strAddress,\n\t\t\t\t\"b\": \"50000000000000000000000000000000000000\",\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": ethAddress,\n\t\t\t\t\"b\": overflowBigInt,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"tuple(address a, int256 b)\",\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": strAddress,\n\t\t\t\t\"b\": \"0x259DA6542D43623D04C5112000000000\",\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": ethAddress,\n\t\t\t\t\"b\": overflowBigInt,\n\t\t\t},\n\t\t},\n\t}\n\n\tserver := testutil.NewTestServer(t)\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\ttt, err := NewType(c.Type)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tres1, err := Encode(c.Input, tt)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tres2, err := Decode(tt, res1)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif !reflect.DeepEqual(res2, c.Expected) {\n\t\t\t\tt.Fatal(\"bad\")\n\t\t\t}\n\t\t\tif tt.kind == KindTuple {\n\t\t\t\tif err := testTypeWithContract(t, server, tt); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestEncodingArguments(t *testing.T) {\n\tcases := []struct {\n\t\tArg   *ArgumentStr\n\t\tInput interface{}\n\t}{\n\t\t{\n\t\t\t&ArgumentStr{\n\t\t\t\tType: \"tuple\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"\",\n\t\t\t\t\t\tType: \"int32\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"\",\n\t\t\t\t\t\tType: \"int32\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"0\": int32(1),\n\t\t\t\t\"1\": int32(2),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t&ArgumentStr{\n\t\t\t\tType: \"tuple\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"a\",\n\t\t\t\t\t\tType: \"int32\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"\",\n\t\t\t\t\t\tType: \"int32\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"a\": int32(1),\n\t\t\t\t\"1\": int32(2),\n\t\t\t},\n\t\t},\n\t}\n\n\tserver := testutil.NewTestServer(t)\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\ttt, err := NewTypeFromArgument(c.Arg)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif err := testEncodeDecode(t, server, tt, c.Input); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc testEncodeDecode(t *testing.T, server *testutil.TestServer, tt *Type, input interface{}) error {\n\tres1, err := Encode(input, tt)\n\tif err != nil {\n\t\treturn err\n\t}\n\tres2, err := Decode(tt, res1)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !reflect.DeepEqual(res2, input) {\n\t\treturn fmt.Errorf(\"bad\")\n\t}\n\tif tt.kind == KindTuple {\n\t\tif err := testTypeWithContract(t, server, tt); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc generateRandomArgs(n int) *Type {\n\tinputs := []*TupleElem{}\n\tfor i := 0; i < randomInt(1, 10); i++ {\n\t\tttt, err := NewType(randomType())\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tinputs = append(inputs, &TupleElem{\n\t\t\tName: fmt.Sprintf(\"arg%d\", i),\n\t\t\tElem: ttt,\n\t\t})\n\t}\n\treturn &Type{\n\t\tkind:  KindTuple,\n\t\ttuple: inputs,\n\t}\n}\n\nfunc TestRandomEncoding(t *testing.T) {\n\trand.Seed(time.Now().UTC().UnixNano())\n\n\tnStr := os.Getenv(\"RANDOM_TESTS\")\n\tn, err := strconv.Atoi(nStr)\n\tif err != nil {\n\t\tn = 100\n\t}\n\n\tserver := testutil.NewTestServer(t)\n\n\tfor i := 0; i < int(n); i++ {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\ttt := generateRandomArgs(randomInt(1, 4))\n\t\t\tinput := generateRandomType(tt)\n\n\t\t\tif err := testEncodeDecode(t, server, tt, input); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tif err := testDecodePanic(tt, input); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc testDecodePanic(tt *Type, input interface{}) error {\n\t// test that the encoded input and random permutattions of the response do not cause\n\t// panics on Decode function\n\tres1, err := Encode(input, tt)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tbuf := make([]byte, len(res1))\n\n\t// change each bit of the input with 1\n\tfor i := 0; i < len(res1); i++ {\n\t\tcopy(buf, res1)\n\t\tbuf[i] = 0xff\n\n\t\tDecode(tt, buf)\n\t}\n\n\treturn nil\n}\n\nfunc testTypeWithContract(t *testing.T, server *testutil.TestServer, typ *Type) error {\n\tg := &generateContractImpl{}\n\tsource := g.run(typ)\n\n\toutput, err := compiler.NewSolidityCompiler(\"solc\").CompileCode(source)\n\tif err != nil {\n\t\treturn err\n\t}\n\tsolcContract, ok := output.Contracts[\"<stdin>:Sample\"]\n\tif !ok {\n\t\treturn fmt.Errorf(\"Expected the contract to be called Sample\")\n\t}\n\n\tabi, err := NewABI(string(solcContract.Abi))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tbinBuf, err := hex.DecodeString(solcContract.Bin)\n\tif err != nil {\n\t\treturn err\n\t}\n\ttxn := &ethgo.Transaction{\n\t\tInput: binBuf,\n\t}\n\treceipt, err := server.SendTxn(txn)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmethod, ok := abi.Methods[\"set\"]\n\tif !ok {\n\t\treturn fmt.Errorf(\"method set not found\")\n\t}\n\n\ttt := method.Inputs\n\tval := generateRandomType(tt)\n\n\tdata, err := method.Encode(val)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tres, err := server.Call(&ethgo.CallMsg{\n\t\tTo:   &receipt.ContractAddress,\n\t\tData: data,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\tif res != encodeHex(data[4:]) { // remove funct signature in data\n\t\treturn fmt.Errorf(\"bad\")\n\t}\n\treturn nil\n}\n\nfunc TestEncodingStruct(t *testing.T) {\n\ttyp := MustNewType(\"tuple(address aa, uint256 b)\")\n\n\ttype Obj struct {\n\t\tA ethgo.Address `abi:\"aa\"`\n\t\tB *big.Int\n\t}\n\tobj := Obj{\n\t\tA: ethgo.Address{0x1},\n\t\tB: big.NewInt(1),\n\t}\n\n\tencoded, err := typ.Encode(&obj)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar obj2 Obj\n\tif err := typ.DecodeStruct(encoded, &obj2); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !reflect.DeepEqual(obj, obj2) {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n\nfunc TestEncodingStruct_camcelCase(t *testing.T) {\n\ttyp := MustNewType(\"tuple(address aA, uint256 b)\")\n\n\ttype Obj struct {\n\t\tA ethgo.Address `abi:\"aA\"`\n\t\tB *big.Int\n\t}\n\tobj := Obj{\n\t\tA: ethgo.Address{0x1},\n\t\tB: big.NewInt(1),\n\t}\n\n\tencoded, err := typ.Encode(&obj)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar obj2 Obj\n\tif err := typ.DecodeStruct(encoded, &obj2); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !reflect.DeepEqual(obj, obj2) {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n"
  },
  {
    "path": "abi/revert.go",
    "content": "package abi\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nvar revertId = []byte{0x8, 0xC3, 0x79, 0xA0}\n\nfunc UnpackRevertError(b []byte) (string, error) {\n\tif !bytes.HasPrefix(b, revertId) {\n\t\treturn \"\", fmt.Errorf(\"revert error prefix not found\")\n\t}\n\n\tb = b[4:]\n\ttt := MustNewType(\"tuple(string)\")\n\tvals, err := tt.Decode(b)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\trevVal := vals.(map[string]interface{})[\"0\"].(string)\n\treturn revVal, nil\n}\n"
  },
  {
    "path": "abi/revert_test.go",
    "content": "package abi\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestUnpackRevertError(t *testing.T) {\n\tdata := \"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000\"\n\n\traw, err := decodeHex(data)\n\tassert.NoError(t, err)\n\n\treason, err := UnpackRevertError(raw)\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"revert reason\", reason)\n}\n"
  },
  {
    "path": "abi/testing.go",
    "content": "package abi\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc randomInt(min, max int) int {\n\treturn min + rand.Intn(max-min)\n}\n\nvar randomTypes = []string{\n\t\"bool\",\n\t\"int\",\n\t\"uint\",\n\t\"array\",\n\t\"slice\",\n\t\"tuple\",\n\t\"address\",\n\t\"string\",\n\t\"bytes\",\n\t\"fixedBytes\",\n}\n\nfunc randomNumberBits() int {\n\treturn randomInt(1, 31) * 8\n}\n\nfunc randomType() string {\n\treturn pickRandomType(1)\n}\n\nfunc pickRandomType(d int) string {\nPICK:\n\tt := randomTypes[rand.Intn(len(randomTypes))]\n\n\tbasicTypes := \"bool,address,string,bytes,function\"\n\tif strings.Contains(basicTypes, t) {\n\t\treturn t\n\t}\n\n\tswitch t {\n\tcase \"int\":\n\t\treturn fmt.Sprintf(\"int%d\", randomNumberBits())\n\n\tcase \"uint\":\n\t\treturn fmt.Sprintf(\"uint%d\", randomNumberBits())\n\n\tcase \"fixedBytes\":\n\t\treturn fmt.Sprintf(\"bytes%d\", randomInt(1, 32))\n\t}\n\n\tif d > 3 {\n\t\t// Allow only for 3 levels of depth\n\t\tgoto PICK\n\t}\n\n\tr := pickRandomType(d + 1)\n\tswitch t {\n\tcase \"slice\":\n\t\treturn fmt.Sprintf(\"%s[]\", r)\n\n\tcase \"array\":\n\t\ts := randomInt(1, 3)\n\t\treturn fmt.Sprintf(\"%s[%d]\", r, s)\n\n\tcase \"tuple\":\n\t\tsize := randomInt(1, 5)\n\t\telems := []string{}\n\t\tfor i := 0; i < size; i++ {\n\t\t\telem := pickRandomType(d + 1)\n\t\t\telems = append(elems, fmt.Sprintf(\"%s arg%d\", elem, i))\n\t\t}\n\t\treturn fmt.Sprintf(\"tuple(%s)\", strings.Join(elems, \",\"))\n\n\tdefault:\n\t\tpanic(fmt.Errorf(\"type not implemented: %s\", t))\n\t}\n}\n\nfunc generateNumber(t *Type) interface{} {\n\tb := make([]byte, t.size/8)\n\tif t.kind == KindUInt {\n\t\trand.Read(b)\n\t} else {\n\t\trand.Read(b[1:])\n\t}\n\n\tnum := big.NewInt(1).SetBytes(b)\n\tif t.size == 8 || t.size == 16 || t.size == 32 || t.size == 64 {\n\t\treturn reflect.ValueOf(num.Int64()).Convert(t.t).Interface()\n\t}\n\treturn num\n}\n\nfunc generateRandomType(t *Type) interface{} {\n\n\tswitch t.kind {\n\tcase KindInt:\n\t\tfallthrough\n\tcase KindUInt:\n\t\treturn generateNumber(t)\n\n\tcase KindBool:\n\t\tif randomInt(0, 1) == 1 {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\n\tcase KindAddress:\n\t\tbuf := ethgo.Address{}\n\t\trand.Read(buf[:])\n\t\treturn buf\n\n\tcase KindString:\n\t\treturn randString(randomInt(1, 100), letters)\n\n\tcase KindBytes:\n\t\tbuf := make([]byte, randomInt(1, 100))\n\t\trand.Read(buf)\n\t\treturn buf\n\n\tcase KindFixedBytes, KindFunction:\n\t\tbuf := make([]byte, t.size)\n\t\trand.Read(buf)\n\n\t\tval := reflect.New(t.t).Elem()\n\t\tfor i := 0; i < len(buf); i++ {\n\t\t\tval.Index(i).Set(reflect.ValueOf(buf[i]))\n\t\t}\n\t\treturn val.Interface()\n\n\tcase KindSlice:\n\t\tsize := randomInt(0, 5)\n\t\tval := reflect.MakeSlice(t.t, size, size)\n\t\tfor i := 0; i < size; i++ {\n\t\t\tval.Index(i).Set(reflect.ValueOf(generateRandomType(t.elem)))\n\t\t}\n\t\treturn val.Interface()\n\n\tcase KindArray:\n\t\tval := reflect.New(t.t).Elem()\n\t\tfor i := 0; i < t.size; i++ {\n\t\t\tval.Index(i).Set(reflect.ValueOf(generateRandomType(t.elem)))\n\t\t}\n\t\treturn val.Interface()\n\n\tcase KindTuple:\n\t\tvals := map[string]interface{}{}\n\t\tfor _, i := range t.tuple {\n\t\t\tvals[i.Name] = generateRandomType(i.Elem)\n\t\t}\n\t\treturn vals\n\n\tdefault:\n\t\tpanic(fmt.Errorf(\"type not implemented: %s\", t.kind.String()))\n\t}\n}\n\nconst hexLetters = \"0123456789abcdef\"\n\nconst letters = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\nfunc randString(n int, dict string) string {\n\tb := make([]byte, n)\n\tfor i := range b {\n\t\tb[i] = dict[rand.Intn(len(dict))]\n\t}\n\treturn string(b)\n}\n\ntype generateContractImpl struct {\n\tstructs []string\n}\n\nfunc (g *generateContractImpl) run(t *Type) string {\n\n\tvar input, output, body []string\n\tfor indx, i := range t.tuple {\n\t\tval := g.getValue(i.Elem)\n\t\tmemory := \"\"\n\t\tif val == \"bytes\" || strings.Contains(val, \"[\") || strings.Contains(val, \"struct\") || strings.Contains(val, \"string\") {\n\t\t\tmemory = \" memory\"\n\t\t}\n\n\t\tinput = append(input, fmt.Sprintf(\"%s%s arg%d\", val, memory, indx))\n\t\toutput = append(output, fmt.Sprintf(\"%s%s\", val, memory))\n\t\tbody = append(body, fmt.Sprintf(\"arg%d\", indx))\n\t}\n\n\tcontractTemplate := `pragma solidity ^0.5.5;\npragma experimental ABIEncoderV2;\n\ncontract Sample {\n\t// structs\n\t%s\n\tfunction set(%s) public view returns (%s) {\n\t\treturn (%s);\n\t}\n}`\n\n\tcontract := fmt.Sprintf(\n\t\tcontractTemplate,\n\t\tstrings.Join(g.structs, \"\\n\"),\n\t\tstrings.Join(input, \",\"),\n\t\tstrings.Join(output, \",\"),\n\t\tstrings.Join(body, \",\"))\n\n\treturn contract\n}\n\nfunc (g *generateContractImpl) getValue(t *Type) string {\n\tswitch t.kind {\n\tcase KindTuple:\n\t\tattrs := []string{}\n\t\tfor indx, i := range t.tuple {\n\t\t\tattrs = append(attrs, fmt.Sprintf(\"%s attr%d;\", g.getValue(i.Elem), indx))\n\t\t}\n\t\tid := len(g.structs)\n\t\tstr := fmt.Sprintf(\"struct struct%d {\\n%s\\n}\\n\", id, strings.Join(attrs, \"\\n\"))\n\t\tg.structs = append(g.structs, str)\n\t\treturn fmt.Sprintf(\"struct%d\", id)\n\n\tcase KindSlice:\n\t\treturn fmt.Sprintf(\"%s[]\", g.getValue(t.elem))\n\n\tcase KindArray:\n\t\treturn fmt.Sprintf(\"%s[%d]\", g.getValue(t.elem), t.size)\n\n\tdefault:\n\t\treturn t.String()\n\t}\n}\n"
  },
  {
    "path": "abi/topics.go",
    "content": "package abi\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"reflect\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// ParseLog parses an event log\nfunc ParseLog(args *Type, log *ethgo.Log) (map[string]interface{}, error) {\n\tvar indexed, nonIndexed []*TupleElem\n\n\tfor _, arg := range args.TupleElems() {\n\t\tif arg.Indexed {\n\t\t\tindexed = append(indexed, arg)\n\t\t} else {\n\t\t\tnonIndexed = append(nonIndexed, arg)\n\t\t}\n\t}\n\n\t// decode indexed fields\n\tindexedObjs, err := ParseTopics(&Type{kind: KindTuple, tuple: indexed}, log.Topics[1:])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar nonIndexedObjs map[string]interface{}\n\tif len(nonIndexed) > 0 {\n\t\tnonIndexedRaw, err := Decode(&Type{kind: KindTuple, tuple: nonIndexed}, log.Data)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\traw, ok := nonIndexedRaw.(map[string]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"bad decoding\")\n\t\t}\n\t\tnonIndexedObjs = raw\n\t}\n\n\tres := map[string]interface{}{}\n\tfor _, arg := range args.TupleElems() {\n\t\tif arg.Indexed {\n\t\t\tres[arg.Name] = indexedObjs[0]\n\t\t\tindexedObjs = indexedObjs[1:]\n\t\t} else {\n\t\t\tres[arg.Name] = nonIndexedObjs[arg.Name]\n\t\t}\n\t}\n\n\treturn res, nil\n}\n\n// ParseTopics parses topics from a log event\nfunc ParseTopics(args *Type, topics []ethgo.Hash) ([]interface{}, error) {\n\tif args.kind != KindTuple {\n\t\treturn nil, fmt.Errorf(\"expected a tuple type\")\n\t}\n\tif len(args.TupleElems()) != len(topics) {\n\t\treturn nil, fmt.Errorf(\"bad length\")\n\t}\n\n\telems := []interface{}{}\n\tfor indx, arg := range args.TupleElems() {\n\t\telem, err := ParseTopic(arg.Elem, topics[indx])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\telems = append(elems, elem)\n\t}\n\n\treturn elems, nil\n}\n\n// ParseTopic parses an individual topic\nfunc ParseTopic(t *Type, topic ethgo.Hash) (interface{}, error) {\n\tswitch t.kind {\n\tcase KindBool:\n\t\tif bytes.Equal(topic[:], topicTrue[:]) {\n\t\t\treturn true, nil\n\t\t} else if bytes.Equal(topic[:], topicFalse[:]) {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn true, fmt.Errorf(\"is not a boolean\")\n\n\tcase KindInt, KindUInt:\n\t\treturn readInteger(t, topic[:]), nil\n\n\tcase KindAddress:\n\t\treturn readAddr(topic[:])\n\n\tcase KindFixedBytes:\n\t\treturn readFixedBytes(t, topic[:])\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"topic parsing for type %s not supported\", t.String())\n\t}\n}\n\n// EncodeTopic encodes a topic\nfunc EncodeTopic(t *Type, val interface{}) (ethgo.Hash, error) {\n\treturn encodeTopic(t, reflect.ValueOf(val))\n}\n\nfunc encodeTopic(t *Type, val reflect.Value) (ethgo.Hash, error) {\n\tswitch t.kind {\n\tcase KindBool:\n\t\treturn encodeTopicBool(val)\n\n\tcase KindUInt, KindInt:\n\t\treturn encodeTopicNum(t, val)\n\n\tcase KindAddress:\n\t\treturn encodeTopicAddress(val)\n\n\t}\n\treturn ethgo.Hash{}, fmt.Errorf(\"not found\")\n}\n\nvar topicTrue, topicFalse ethgo.Hash\n\nfunc init() {\n\ttopicTrue[31] = 1\n}\n\nfunc encodeTopicAddress(val reflect.Value) (res ethgo.Hash, err error) {\n\tvar b []byte\n\tb, err = encodeAddress(val)\n\tif err != nil {\n\t\treturn\n\t}\n\tcopy(res[:], b[:])\n\treturn\n}\n\nfunc encodeTopicNum(t *Type, val reflect.Value) (res ethgo.Hash, err error) {\n\tvar b []byte\n\tb, err = encodeNum(val)\n\tif err != nil {\n\t\treturn\n\t}\n\tcopy(res[:], b[:])\n\treturn\n}\n\nfunc encodeTopicBool(v reflect.Value) (res ethgo.Hash, err error) {\n\tif v.Kind() != reflect.Bool {\n\t\treturn ethgo.Hash{}, encodeErr(v, \"bool\")\n\t}\n\tif v.Bool() {\n\t\treturn topicTrue, nil\n\t}\n\treturn topicFalse, nil\n}\n"
  },
  {
    "path": "abi/topics_test.go",
    "content": "package abi\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc TestTopicEncoding(t *testing.T) {\n\tcases := []struct {\n\t\tType string\n\t\tVal  interface{}\n\t}{\n\t\t{\n\t\t\tType: \"bool\",\n\t\t\tVal:  true,\n\t\t},\n\t\t{\n\t\t\tType: \"bool\",\n\t\t\tVal:  false,\n\t\t},\n\t\t{\n\t\t\tType: \"uint64\",\n\t\t\tVal:  uint64(20),\n\t\t},\n\t\t{\n\t\t\tType: \"uint256\",\n\t\t\tVal:  big.NewInt(1000000),\n\t\t},\n\t\t{\n\t\t\tType: \"address\",\n\t\t\tVal:  ethgo.Address{0x1},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\ttt, err := NewType(c.Type)\n\t\tassert.NoError(t, err)\n\n\t\tres, err := EncodeTopic(tt, c.Val)\n\t\tassert.NoError(t, err)\n\n\t\tval, err := ParseTopic(tt, res)\n\t\tassert.NoError(t, err)\n\n\t\tassert.Equal(t, val, c.Val)\n\t}\n}\n\nfunc TestIntegrationTopics(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\ttype field struct {\n\t\ttyp    string\n\t\tindx   bool\n\t\tval    interface{}\n\t\tvalStr string\n\t}\n\n\tcases := []struct {\n\t\tfields []field\n\t}{\n\t\t{\n\t\t\t// uint\n\t\t\tfields: []field{\n\t\t\t\t{\"uint32\", false, uint32(1), \"1\"},\n\t\t\t\t{\"uint8\", true, uint8(10), \"10\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// fixed bytes\n\t\t\tfields: []field{\n\t\t\t\t{\"bytes1\", false, [1]byte{0x1}, \"0x01\"},\n\t\t\t\t{\"bytes1\", true, [1]byte{0x1}, \"0x01\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tcc := &testutil.Contract{}\n\n\t\tevnt := testutil.NewEvent(\"A\")\n\t\tinput := []string{}\n\n\t\tresult := map[string]interface{}{}\n\t\tfor indx, field := range c.fields {\n\t\t\tevnt.Add(field.typ, field.indx)\n\t\t\tinput = append(input, field.valStr)\n\t\t\tresult[fmt.Sprintf(\"val_%d\", indx)] = field.val\n\t\t}\n\n\t\tcc.AddEvent(evnt)\n\t\tcc.EmitEvent(\"setA\", \"A\", input...)\n\n\t\t// deploy the contract\n\t\tartifact, addr, err := s.DeployContract(cc)\n\t\trequire.NoError(t, err)\n\n\t\treceipt, err := s.TxnTo(addr, \"setA\")\n\t\trequire.NoError(t, err)\n\n\t\t// read the abi\n\t\tabi, err := NewABI(artifact.Abi)\n\t\tassert.NoError(t, err)\n\n\t\t// parse the logs\n\t\tfound, err := ParseLog(abi.Events[\"A\"].Inputs, receipt.Logs[0])\n\t\tassert.NoError(t, err)\n\n\t\tif !reflect.DeepEqual(found, result) {\n\t\t\tt.Fatal(\"not equal\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "abi/type.go",
    "content": "package abi\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// batch of predefined reflect types\nvar (\n\tboolT         = reflect.TypeOf(bool(false))\n\tuint8T        = reflect.TypeOf(uint8(0))\n\tuint16T       = reflect.TypeOf(uint16(0))\n\tuint32T       = reflect.TypeOf(uint32(0))\n\tuint64T       = reflect.TypeOf(uint64(0))\n\tint8T         = reflect.TypeOf(int8(0))\n\tint16T        = reflect.TypeOf(int16(0))\n\tint32T        = reflect.TypeOf(int32(0))\n\tint64T        = reflect.TypeOf(int64(0))\n\taddressT      = reflect.TypeOf(ethgo.Address{})\n\tstringT       = reflect.TypeOf(\"\")\n\tdynamicBytesT = reflect.SliceOf(reflect.TypeOf(byte(0)))\n\tfunctionT     = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))\n\ttupleT        = reflect.TypeOf(map[string]interface{}{})\n\tbigIntT       = reflect.TypeOf(new(big.Int))\n)\n\n// Kind represents the kind of abi type\ntype Kind int\n\nconst (\n\t// KindBool is a boolean\n\tKindBool Kind = iota\n\n\t// KindUInt is an uint\n\tKindUInt\n\n\t// KindInt is an int\n\tKindInt\n\n\t// KindString is a string\n\tKindString\n\n\t// KindArray is an array\n\tKindArray\n\n\t// KindSlice is a slice\n\tKindSlice\n\n\t// KindAddress is an address\n\tKindAddress\n\n\t// KindBytes is a bytes array\n\tKindBytes\n\n\t// KindFixedBytes is a fixed bytes\n\tKindFixedBytes\n\n\t// KindFixedPoint is a fixed point\n\tKindFixedPoint\n\n\t// KindTuple is a tuple\n\tKindTuple\n\n\t// KindFunction is a function\n\tKindFunction\n)\n\nfunc (k Kind) String() string {\n\tnames := [...]string{\n\t\t\"Bool\",\n\t\t\"Uint\",\n\t\t\"Int\",\n\t\t\"String\",\n\t\t\"Array\",\n\t\t\"Slice\",\n\t\t\"Address\",\n\t\t\"Bytes\",\n\t\t\"FixedBytes\",\n\t\t\"FixedPoint\",\n\t\t\"Tuple\",\n\t\t\"Function\",\n\t}\n\n\treturn names[k]\n}\n\n// TupleElem is an element of a tuple\ntype TupleElem struct {\n\tName    string\n\tElem    *Type\n\tIndexed bool\n}\n\n// Type is an ABI type\ntype Type struct {\n\tkind  Kind\n\tsize  int\n\telem  *Type\n\ttuple []*TupleElem\n\tt     reflect.Type\n\titype string\n}\n\nfunc NewTupleType(inputs []*TupleElem) *Type {\n\treturn &Type{\n\t\tkind:  KindTuple,\n\t\ttuple: inputs,\n\t\tt:     tupleT,\n\t}\n}\n\nfunc NewTupleTypeFromArgs(inputs []*ArgumentStr) (*Type, error) {\n\telems := []*TupleElem{}\n\tfor _, i := range inputs {\n\t\ttyp, err := NewTypeFromArgument(i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\telems = append(elems, &TupleElem{\n\t\t\tName:    i.Name,\n\t\t\tElem:    typ,\n\t\t\tIndexed: i.Indexed,\n\t\t})\n\t}\n\treturn NewTupleType(elems), nil\n}\n\n// ParseLog parses a log using this type\nfunc (t *Type) ParseLog(log *ethgo.Log) (map[string]interface{}, error) {\n\treturn ParseLog(t, log)\n}\n\n// Decode decodes an object using this type\nfunc (t *Type) Decode(input []byte) (interface{}, error) {\n\treturn Decode(t, input)\n}\n\n// DecodeStruct decodes an object using this type to the out param\nfunc (t *Type) DecodeStruct(input []byte, out interface{}) error {\n\treturn DecodeStruct(t, input, out)\n}\n\n// InternalType returns the internal type\nfunc (t *Type) InternalType() string {\n\treturn t.itype\n}\n\n// Encode encodes an object using this type\nfunc (t *Type) Encode(v interface{}) ([]byte, error) {\n\treturn Encode(v, t)\n}\n\nfunc (t *Type) String() string {\n\treturn t.Format(false)\n}\n\n// String returns the raw representation of the type\nfunc (t *Type) Format(includeArgs bool) string {\n\tswitch t.kind {\n\tcase KindTuple:\n\t\trawAux := []string{}\n\t\tfor _, i := range t.TupleElems() {\n\t\t\tname := i.Elem.Format(includeArgs)\n\t\t\tif i.Indexed {\n\t\t\t\tname += \" indexed\"\n\t\t\t}\n\t\t\tif includeArgs {\n\t\t\t\tif i.Name != \"\" {\n\t\t\t\t\tname += \" \" + i.Name\n\t\t\t\t}\n\t\t\t}\n\t\t\trawAux = append(rawAux, name)\n\t\t}\n\t\treturn fmt.Sprintf(\"tuple(%s)\", strings.Join(rawAux, \",\"))\n\n\tcase KindArray:\n\t\treturn fmt.Sprintf(\"%s[%d]\", t.elem.Format(includeArgs), t.size)\n\n\tcase KindSlice:\n\t\treturn fmt.Sprintf(\"%s[]\", t.elem.Format(includeArgs))\n\n\tcase KindBytes:\n\t\treturn \"bytes\"\n\n\tcase KindFixedBytes:\n\t\treturn fmt.Sprintf(\"bytes%d\", t.size)\n\n\tcase KindString:\n\t\treturn \"string\"\n\n\tcase KindBool:\n\t\treturn \"bool\"\n\n\tcase KindAddress:\n\t\treturn \"address\"\n\n\tcase KindFunction:\n\t\treturn \"function\"\n\n\tcase KindUInt:\n\t\treturn fmt.Sprintf(\"uint%d\", t.size)\n\n\tcase KindInt:\n\t\treturn fmt.Sprintf(\"int%d\", t.size)\n\n\tdefault:\n\t\tpanic(fmt.Errorf(\"BUG: abi type not found %s\", t.kind.String()))\n\t}\n}\n\n// Elem returns the elem value for slice and arrays\nfunc (t *Type) Elem() *Type {\n\treturn t.elem\n}\n\n// Size returns the size of the type\nfunc (t *Type) Size() int {\n\treturn t.size\n}\n\n// TupleElems returns the elems of the tuple\nfunc (t *Type) TupleElems() []*TupleElem {\n\treturn t.tuple\n}\n\n// GoType returns the go type\nfunc (t *Type) GoType() reflect.Type {\n\treturn t.t\n}\n\n// Kind returns the kind of the type\nfunc (t *Type) Kind() Kind {\n\treturn t.kind\n}\n\nfunc (t *Type) isVariableInput() bool {\n\treturn t.kind == KindSlice || t.kind == KindBytes || t.kind == KindString\n}\n\nfunc (t *Type) isDynamicType() bool {\n\tif t.kind == KindTuple {\n\t\tfor _, elem := range t.tuple {\n\t\t\tif elem.Elem.isDynamicType() {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\treturn t.kind == KindString || t.kind == KindBytes || t.kind == KindSlice || (t.kind == KindArray && t.elem.isDynamicType())\n}\n\nfunc parseType(arg *ArgumentStr) (string, error) {\n\tif !strings.HasPrefix(arg.Type, \"tuple\") {\n\t\treturn arg.Type, nil\n\t}\n\n\tif len(arg.Components) == 0 {\n\t\treturn \"tuple()\", nil\n\t}\n\n\t// parse the arg components from the tuple\n\tstr := []string{}\n\tfor _, i := range arg.Components {\n\t\taux, err := parseType(i)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tif i.Indexed {\n\t\t\tstr = append(str, aux+\" indexed \"+i.Name)\n\t\t} else {\n\t\t\tstr = append(str, aux+\" \"+i.Name)\n\t\t}\n\t}\n\treturn fmt.Sprintf(\"tuple(%s)%s\", strings.Join(str, \",\"), strings.TrimPrefix(arg.Type, \"tuple\")), nil\n}\n\n// NewTypeFromArgument parses an abi type from an argument\nfunc NewTypeFromArgument(arg *ArgumentStr) (*Type, error) {\n\tstr, err := parseType(arg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttyp, err := NewType(str)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// fill-in the `internalType` field into the type elems\n\tfillIn(typ, arg)\n\n\treturn typ, nil\n}\n\nfunc fillIn(typ *Type, arg *ArgumentStr) error {\n\ttyp.itype = arg.InternalType\n\n\tif len(arg.Components) == 0 {\n\t\t// no more items, nothing else to do\n\t\treturn nil\n\t}\n\n\t// tuple types in the ABI with slices are represented as\n\t// tuple()[] or tuple()[2]. Thus, there might be element in the components\n\t// section of the abi but the next item not be a tuple.\n\tfor {\n\t\tkind := typ.kind\n\t\tif kind == KindTuple {\n\t\t\tbreak\n\t\t}\n\t\tif kind != KindArray && kind != KindSlice {\n\t\t\t// error\n\t\t\treturn fmt.Errorf(\"array or slice not found\")\n\t\t}\n\t\ttyp = typ.Elem()\n\t}\n\n\tif len(arg.Components) != len(typ.tuple) {\n\t\t// incorrect length\n\t\treturn fmt.Errorf(\"incorrect size\")\n\t}\n\n\tfor indx, i := range arg.Components {\n\t\tfillIn(typ.tuple[indx].Elem, i)\n\t}\n\n\treturn nil\n}\n\n// NewType parses a type in string format\nfunc NewType(s string) (*Type, error) {\n\tl := newLexer(s)\n\tl.nextToken()\n\n\treturn readType(l)\n}\n\n// MustNewType parses a type in string format or panics if its invalid\nfunc MustNewType(s string) *Type {\n\tt, err := NewType(s)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn t\n}\n\nfunc getTypeSize(t *Type) int {\n\tif t.kind == KindArray && !t.elem.isDynamicType() {\n\t\tif t.elem.kind == KindArray || t.elem.kind == KindTuple {\n\t\t\treturn t.size * getTypeSize(t.elem)\n\t\t}\n\t\treturn t.size * 32\n\t} else if t.kind == KindTuple && !t.isDynamicType() {\n\t\ttotal := 0\n\t\tfor _, elem := range t.tuple {\n\t\t\ttotal += getTypeSize(elem.Elem)\n\t\t}\n\t\treturn total\n\t}\n\treturn 32\n}\n\nvar typeRegexp = regexp.MustCompile(\"^([[:alpha:]]+)([[:digit:]]*)$\")\n\nfunc expectedToken(t tokenType) error {\n\treturn fmt.Errorf(\"expected token %s\", t.String())\n}\n\nfunc notExpectedToken(t tokenType) error {\n\treturn fmt.Errorf(\"token '%s' not expected\", t.String())\n}\n\nfunc readType(l *lexer) (*Type, error) {\n\tvar tt *Type\n\n\ttok := l.nextToken()\n\n\tisTuple := false\n\tif tok.typ == tupleToken {\n\t\tif l.nextToken().typ != lparenToken {\n\t\t\treturn nil, expectedToken(lparenToken)\n\t\t}\n\t\tisTuple = true\n\t} else if tok.typ == lparenToken {\n\t\tisTuple = true\n\t}\n\tif isTuple {\n\t\tvar next token\n\t\telems := []*TupleElem{}\n\t\tfor {\n\n\t\t\tname := \"\"\n\t\t\tindexed := false\n\n\t\t\telem, err := readType(l)\n\t\t\tif err != nil {\n\t\t\t\tif l.current.typ == rparenToken && len(elems) == 0 {\n\t\t\t\t\t// empty tuple 'tuple()'\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"failed to decode type: %v\", err)\n\t\t\t}\n\n\t\t\tswitch l.peek.typ {\n\t\t\tcase strToken:\n\t\t\t\tl.nextToken()\n\t\t\t\tname = l.current.literal\n\n\t\t\tcase indexedToken:\n\t\t\t\tl.nextToken()\n\t\t\t\tindexed = true\n\t\t\t\tif l.peek.typ == strToken {\n\t\t\t\t\tl.nextToken()\n\t\t\t\t\tname = l.current.literal\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telems = append(elems, &TupleElem{\n\t\t\t\tName:    name,\n\t\t\t\tElem:    elem,\n\t\t\t\tIndexed: indexed,\n\t\t\t})\n\n\t\t\tnext = l.nextToken()\n\t\t\tif next.typ == commaToken {\n\t\t\t\tcontinue\n\t\t\t} else if next.typ == rparenToken {\n\t\t\t\tbreak\n\t\t\t} else {\n\t\t\t\treturn nil, notExpectedToken(next.typ)\n\t\t\t}\n\t\t}\n\t\ttt = &Type{kind: KindTuple, tuple: elems, t: tupleT}\n\n\t} else if tok.typ != strToken {\n\t\treturn nil, expectedToken(strToken)\n\n\t} else {\n\t\t// Check normal types\n\t\telem, err := decodeSimpleType(tok.literal)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ttt = elem\n\t}\n\n\t// check for arrays at the end of the type\n\tfor {\n\t\tif l.peek.typ != lbracketToken {\n\t\t\tbreak\n\t\t}\n\n\t\tl.nextToken()\n\t\tn := l.nextToken()\n\n\t\tvar tAux *Type\n\t\tif n.typ == rbracketToken {\n\t\t\ttAux = &Type{kind: KindSlice, elem: tt, t: reflect.SliceOf(tt.t)}\n\n\t\t} else if n.typ == numberToken {\n\t\t\tsize, err := strconv.ParseUint(n.literal, 10, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to read array size '%s': %v\", n.literal, err)\n\t\t\t}\n\n\t\t\ttAux = &Type{kind: KindArray, elem: tt, size: int(size), t: reflect.ArrayOf(int(size), tt.t)}\n\t\t\tif l.nextToken().typ != rbracketToken {\n\t\t\t\treturn nil, expectedToken(rbracketToken)\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, notExpectedToken(n.typ)\n\t\t}\n\n\t\ttt = tAux\n\t}\n\treturn tt, nil\n}\n\nfunc decodeSimpleType(str string) (*Type, error) {\n\tmatch := typeRegexp.FindStringSubmatch(str)\n\tif len(match) == 0 {\n\t\treturn nil, fmt.Errorf(\"type format is incorrect. Expected 'type''bytes' but found '%s'\", str)\n\t}\n\tmatch = match[1:]\n\n\tvar err error\n\tt := match[0]\n\n\tbytes := 0\n\tok := false\n\n\tif bytesStr := match[1]; bytesStr != \"\" {\n\t\tbytes, err = strconv.Atoi(bytesStr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse bytes '%s': %v\", bytesStr, err)\n\t\t}\n\t\tok = true\n\t}\n\n\t// int and uint without bytes default to 256, 'bytes' may\n\t// have or not, the rest dont have bytes\n\tif t == \"int\" || t == \"uint\" {\n\t\tif !ok {\n\t\t\tbytes = 256\n\t\t}\n\t} else if t != \"bytes\" && ok {\n\t\treturn nil, fmt.Errorf(\"type %s does not expect bytes\", t)\n\t}\n\n\tswitch t {\n\tcase \"uint\":\n\t\tvar k reflect.Type\n\t\tswitch bytes {\n\t\tcase 8:\n\t\t\tk = uint8T\n\t\tcase 16:\n\t\t\tk = uint16T\n\t\tcase 32:\n\t\t\tk = uint32T\n\t\tcase 64:\n\t\t\tk = uint64T\n\t\tdefault:\n\t\t\tif bytes%8 != 0 {\n\t\t\t\tpanic(fmt.Errorf(\"number of bytes has to be M mod 8\"))\n\t\t\t}\n\t\t\tk = bigIntT\n\t\t}\n\t\treturn &Type{kind: KindUInt, size: int(bytes), t: k}, nil\n\n\tcase \"int\":\n\t\tvar k reflect.Type\n\t\tswitch bytes {\n\t\tcase 8:\n\t\t\tk = int8T\n\t\tcase 16:\n\t\t\tk = int16T\n\t\tcase 32:\n\t\t\tk = int32T\n\t\tcase 64:\n\t\t\tk = int64T\n\t\tdefault:\n\t\t\tif bytes%8 != 0 {\n\t\t\t\tpanic(fmt.Errorf(\"number of bytes has to be M mod 8\"))\n\t\t\t}\n\t\t\tk = bigIntT\n\t\t}\n\t\treturn &Type{kind: KindInt, size: int(bytes), t: k}, nil\n\n\tcase \"byte\":\n\t\tbytes = 1\n\t\tfallthrough\n\n\tcase \"bytes\":\n\t\tif bytes == 0 {\n\t\t\treturn &Type{kind: KindBytes, t: dynamicBytesT}, nil\n\t\t}\n\t\treturn &Type{kind: KindFixedBytes, size: int(bytes), t: reflect.ArrayOf(int(bytes), reflect.TypeOf(byte(0)))}, nil\n\n\tcase \"string\":\n\t\treturn &Type{kind: KindString, t: stringT}, nil\n\n\tcase \"bool\":\n\t\treturn &Type{kind: KindBool, t: boolT}, nil\n\n\tcase \"address\":\n\t\treturn &Type{kind: KindAddress, t: addressT, size: 20}, nil\n\n\tcase \"function\":\n\t\treturn &Type{kind: KindFunction, size: 24, t: functionT}, nil\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown type '%s'\", t)\n\t}\n}\n\ntype tokenType int\n\nconst (\n\teofToken tokenType = iota\n\tstrToken\n\tnumberToken\n\ttupleToken\n\tlparenToken\n\trparenToken\n\tlbracketToken\n\trbracketToken\n\tcommaToken\n\tindexedToken\n\tinvalidToken\n)\n\nfunc (t tokenType) String() string {\n\tnames := [...]string{\n\t\t\"eof\",\n\t\t\"string\",\n\t\t\"number\",\n\t\t\"tuple\",\n\t\t\"(\",\n\t\t\")\",\n\t\t\"[\",\n\t\t\"]\",\n\t\t\",\",\n\t\t\"indexed\",\n\t\t\"<invalid>\",\n\t}\n\treturn names[t]\n}\n\ntype token struct {\n\ttyp     tokenType\n\tliteral string\n}\n\ntype lexer struct {\n\tinput        string\n\tcurrent      token\n\tpeek         token\n\tposition     int\n\treadPosition int\n\tch           byte\n}\n\nfunc newLexer(input string) *lexer {\n\tl := &lexer{input: input}\n\tl.readChar()\n\treturn l\n}\n\nfunc (l *lexer) readChar() {\n\tif l.readPosition >= len(l.input) {\n\t\tl.ch = 0\n\t} else {\n\t\tl.ch = l.input[l.readPosition]\n\t}\n\n\tl.position = l.readPosition\n\tl.readPosition++\n}\n\nfunc (l *lexer) nextToken() token {\n\tl.current = l.peek\n\tl.peek = l.nextTokenImpl()\n\treturn l.current\n}\n\nfunc (l *lexer) nextTokenImpl() token {\n\tvar tok token\n\n\t// skip whitespace\n\tfor l.ch == ' ' || l.ch == '\\t' || l.ch == '\\n' || l.ch == '\\r' {\n\t\tl.readChar()\n\t}\n\n\tswitch l.ch {\n\tcase ',':\n\t\ttok.typ = commaToken\n\tcase '(':\n\t\ttok.typ = lparenToken\n\tcase ')':\n\t\ttok.typ = rparenToken\n\tcase '[':\n\t\ttok.typ = lbracketToken\n\tcase ']':\n\t\ttok.typ = rbracketToken\n\tcase 0:\n\t\ttok.typ = eofToken\n\tdefault:\n\t\tif isLetter(l.ch) {\n\t\t\ttok.literal = l.readIdentifier()\n\t\t\tif tok.literal == \"tuple\" {\n\t\t\t\ttok.typ = tupleToken\n\t\t\t} else if tok.literal == \"indexed\" {\n\t\t\t\ttok.typ = indexedToken\n\t\t\t} else {\n\t\t\t\ttok.typ = strToken\n\t\t\t}\n\n\t\t\treturn tok\n\t\t} else if isDigit(l.ch) {\n\t\t\treturn token{numberToken, l.readNumber()}\n\t\t} else {\n\t\t\ttok.typ = invalidToken\n\t\t}\n\t}\n\n\tl.readChar()\n\treturn tok\n}\n\nfunc (l *lexer) readIdentifier() string {\n\tpos := l.position\n\tfor isLetter(l.ch) || isDigit(l.ch) {\n\t\tl.readChar()\n\t}\n\n\treturn l.input[pos:l.position]\n}\n\nfunc (l *lexer) readNumber() string {\n\tposition := l.position\n\tfor isDigit(l.ch) {\n\t\tl.readChar()\n\t}\n\treturn l.input[position:l.position]\n}\n\nfunc isDigit(ch byte) bool {\n\treturn '0' <= ch && ch <= '9'\n}\n\nfunc isLetter(ch byte) bool {\n\treturn 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'\n}\n"
  },
  {
    "path": "abi/type_test.go",
    "content": "package abi\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestType(t *testing.T) {\n\tcases := []struct {\n\t\ts   string\n\t\ta   *ArgumentStr\n\t\tt   *Type\n\t\tr   string\n\t\terr bool\n\t}{\n\t\t{\n\t\t\ts: \"bool\",\n\t\t\ta: simpleType(\"bool\"),\n\t\t\tt: &Type{kind: KindBool, t: boolT},\n\t\t},\n\t\t{\n\t\t\ts: \"uint32\",\n\t\t\ta: simpleType(\"uint32\"),\n\t\t\tt: &Type{kind: KindUInt, size: 32, t: uint32T},\n\t\t},\n\t\t{\n\t\t\ts: \"int32\",\n\t\t\ta: simpleType(\"int32\"),\n\t\t\tt: &Type{kind: KindInt, size: 32, t: int32T},\n\t\t},\n\t\t{\n\t\t\ts: \"int32[]\",\n\t\t\ta: simpleType(\"int32[]\"),\n\t\t\tt: &Type{kind: KindSlice, t: reflect.SliceOf(int32T), elem: &Type{kind: KindInt, size: 32, t: int32T}},\n\t\t},\n\t\t{\n\t\t\ts: \"int\",\n\t\t\ta: simpleType(\"int\"),\n\t\t\tt: &Type{kind: KindInt, size: 256, t: bigIntT},\n\t\t\tr: \"int256\",\n\t\t},\n\t\t{\n\t\t\ts: \"int[]\",\n\t\t\ta: simpleType(\"int[]\"),\n\t\t\tt: &Type{kind: KindSlice, t: reflect.SliceOf(bigIntT), elem: &Type{kind: KindInt, size: 256, t: bigIntT}},\n\t\t\tr: \"int256[]\",\n\t\t},\n\t\t{\n\t\t\ts: \"bytes[2]\",\n\t\t\ta: simpleType(\"bytes[2]\"),\n\t\t\tt: &Type{\n\t\t\t\tkind: KindArray,\n\t\t\t\tt:    reflect.ArrayOf(2, dynamicBytesT),\n\t\t\t\tsize: 2,\n\t\t\t\telem: &Type{\n\t\t\t\t\tkind: KindBytes,\n\t\t\t\t\tt:    dynamicBytesT,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"address[]\",\n\t\t\ta: simpleType(\"address[]\"),\n\t\t\tt: &Type{kind: KindSlice, t: reflect.SliceOf(addressT), elem: &Type{kind: KindAddress, size: 20, t: addressT}},\n\t\t},\n\t\t{\n\t\t\ts: \"string[]\",\n\t\t\ta: simpleType(\"string[]\"),\n\t\t\tt: &Type{\n\t\t\t\tkind: KindSlice,\n\t\t\t\tt:    reflect.SliceOf(stringT),\n\t\t\t\telem: &Type{\n\t\t\t\t\tkind: KindString,\n\t\t\t\t\tt:    stringT,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"string[2]\",\n\t\t\ta: simpleType(\"string[2]\"),\n\t\t\tt: &Type{\n\t\t\t\tkind: KindArray,\n\t\t\t\tsize: 2,\n\t\t\t\tt:    reflect.ArrayOf(2, stringT),\n\t\t\t\telem: &Type{\n\t\t\t\t\tkind: KindString,\n\t\t\t\t\tt:    stringT,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\ts: \"string[2][]\",\n\t\t\ta: simpleType(\"string[2][]\"),\n\t\t\tt: &Type{\n\t\t\t\tkind: KindSlice,\n\t\t\t\tt:    reflect.SliceOf(reflect.ArrayOf(2, stringT)),\n\t\t\t\telem: &Type{\n\t\t\t\t\tkind: KindArray,\n\t\t\t\t\tsize: 2,\n\t\t\t\t\tt:    reflect.ArrayOf(2, stringT),\n\t\t\t\t\telem: &Type{\n\t\t\t\t\t\tkind: KindString,\n\t\t\t\t\t\tt:    stringT,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"tuple(int64 indexed arg0)\",\n\t\t\ta: &ArgumentStr{\n\t\t\t\tType: \"tuple\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:    \"arg0\",\n\t\t\t\t\t\tType:    \"int64\",\n\t\t\t\t\t\tIndexed: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tt: &Type{\n\t\t\t\tkind: KindTuple,\n\t\t\t\tt:    tupleT,\n\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"arg0\",\n\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\tkind: KindInt,\n\t\t\t\t\t\t\tsize: 64,\n\t\t\t\t\t\t\tt:    int64T,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tIndexed: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"tuple(int64 arg_0)[2]\",\n\t\t\ta: &ArgumentStr{\n\t\t\t\tType: \"tuple[2]\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"arg_0\",\n\t\t\t\t\t\tType: \"int64\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tt: &Type{\n\t\t\t\tkind: KindArray,\n\t\t\t\tsize: 2,\n\t\t\t\tt:    reflect.ArrayOf(2, tupleT),\n\t\t\t\telem: &Type{\n\t\t\t\t\tkind: KindTuple,\n\t\t\t\t\tt:    tupleT,\n\t\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: \"arg_0\",\n\t\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\t\tkind: KindInt,\n\t\t\t\t\t\t\t\tsize: 64,\n\t\t\t\t\t\t\t\tt:    int64T,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"tuple(int64 a)[]\",\n\t\t\ta: &ArgumentStr{\n\t\t\t\tType: \"tuple[]\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"a\",\n\t\t\t\t\t\tType: \"int64\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tt: &Type{\n\t\t\t\tkind: KindSlice,\n\t\t\t\tt:    reflect.SliceOf(tupleT),\n\t\t\t\telem: &Type{\n\t\t\t\t\tkind: KindTuple,\n\t\t\t\t\tt:    tupleT,\n\t\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: \"a\",\n\t\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\t\tkind: KindInt,\n\t\t\t\t\t\t\t\tsize: 64,\n\t\t\t\t\t\t\t\tt:    int64T,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"tuple(int32 indexed arg0,tuple(int32 c) b_2)\",\n\t\t\ta: &ArgumentStr{\n\t\t\t\tType: \"tuple\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:    \"arg0\",\n\t\t\t\t\t\tType:    \"int32\",\n\t\t\t\t\t\tIndexed: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"b_2\",\n\t\t\t\t\t\tType: \"tuple\",\n\t\t\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tName: \"c\",\n\t\t\t\t\t\t\t\tType: \"int32\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tt: &Type{\n\t\t\t\tkind: KindTuple,\n\t\t\t\tt:    tupleT,\n\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"arg0\",\n\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\tkind: KindInt,\n\t\t\t\t\t\t\tsize: 32,\n\t\t\t\t\t\t\tt:    int32T,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tIndexed: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"b_2\",\n\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\tkind: KindTuple,\n\t\t\t\t\t\t\tt:    tupleT,\n\t\t\t\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tName: \"c\",\n\t\t\t\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\t\t\t\tkind: KindInt,\n\t\t\t\t\t\t\t\t\t\tsize: 32,\n\t\t\t\t\t\t\t\t\t\tt:    int32T,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\ts: \"tuple()\",\n\t\t\ta: &ArgumentStr{\n\t\t\t\tType:       \"tuple\",\n\t\t\t\tComponents: []*ArgumentStr{},\n\t\t\t},\n\t\t\tt: &Type{\n\t\t\t\tkind:  KindTuple,\n\t\t\t\tt:     tupleT,\n\t\t\t\ttuple: []*TupleElem{},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// hidden tuple token\n\t\t\ts: \"tuple((int32))\",\n\t\t\ta: &ArgumentStr{\n\t\t\t\tType: \"tuple\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tType: \"tuple\",\n\t\t\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tType: \"int32\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tt: &Type{\n\t\t\t\tkind: KindTuple,\n\t\t\t\tt:    tupleT,\n\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t{\n\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\tkind: KindTuple,\n\t\t\t\t\t\t\tt:    tupleT,\n\t\t\t\t\t\t\ttuple: []*TupleElem{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tElem: &Type{\n\t\t\t\t\t\t\t\t\t\tkind: KindInt,\n\t\t\t\t\t\t\t\t\t\tsize: 32,\n\t\t\t\t\t\t\t\t\t\tt:    int32T,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tr: \"tuple(tuple(int32))\",\n\t\t},\n\t\t{\n\t\t\ts:   \"int[[\",\n\t\t\terr: true,\n\t\t},\n\t\t{\n\t\t\ts:   \"tuple[](a int32)\",\n\t\t\terr: true,\n\t\t},\n\t\t{\n\t\t\ts:   \"int32[a]\",\n\t\t\terr: true,\n\t\t},\n\t\t{\n\t\t\ts:   \"tuple(a int32\",\n\t\t\terr: true,\n\t\t},\n\t\t{\n\t\t\ts:   \"tuple(a int32,\",\n\t\t\terr: true,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\te0, err := NewType(c.s)\n\t\t\tif err != nil && !c.err {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif err == nil && c.err {\n\t\t\t\tt.Fatal(\"it should have failed\")\n\t\t\t}\n\n\t\t\tif !c.err {\n\t\t\t\t// compare the string\n\t\t\t\texpected := c.s\n\t\t\t\tif c.r != \"\" {\n\t\t\t\t\texpected = c.r\n\t\t\t\t}\n\t\t\t\tassert.Equal(t, expected, e0.Format(true))\n\n\t\t\t\te1, err := NewTypeFromArgument(c.a)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif !reflect.DeepEqual(c.t, e0) {\n\n\t\t\t\t\t// fmt.Println(c.t.t)\n\t\t\t\t\t// fmt.Println(e0.t)\n\n\t\t\t\t\tt.Fatal(\"bad new type\")\n\t\t\t\t}\n\t\t\t\tif !reflect.DeepEqual(c.t, e1) {\n\t\t\t\t\tt.Fatal(\"bad\")\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestTypeArgument_InternalFields(t *testing.T) {\n\targ := &ArgumentStr{\n\t\tType: \"tuple\",\n\t\tComponents: []*ArgumentStr{\n\t\t\t{\n\t\t\t\tType: \"tuple[]\",\n\t\t\t\tComponents: []*ArgumentStr{\n\t\t\t\t\t{\n\t\t\t\t\t\tType:         \"int32\",\n\t\t\t\t\t\tInternalType: \"c\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tInternalType: \"b\",\n\t\t\t},\n\t\t},\n\t}\n\n\tres, err := NewTypeFromArgument(arg)\n\trequire.NoError(t, err)\n\n\trequire.Equal(t, res.tuple[0].Elem.itype, \"b\")\n\trequire.Equal(t, res.tuple[0].Elem.elem.tuple[0].Elem.itype, \"c\")\n}\n\nfunc TestSize(t *testing.T) {\n\tcases := []struct {\n\t\tInput string\n\t\tSize  int\n\t}{\n\t\t{\n\t\t\t\"int32\", 32,\n\t\t},\n\t\t{\n\t\t\t\"int32[]\", 32,\n\t\t},\n\t\t{\n\t\t\t\"int32[2]\", 32 * 2,\n\t\t},\n\t\t{\n\t\t\t\"int32[2][2]\", 32 * 2 * 2,\n\t\t},\n\t\t{\n\t\t\t\"string\", 32,\n\t\t},\n\t\t{\n\t\t\t\"string[]\", 32,\n\t\t},\n\t\t{\n\t\t\t\"tuple(uint8 a, uint32 b)[1]\",\n\t\t\t64,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\ttt, err := NewType(c.Input)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tsize := getTypeSize(tt)\n\t\t\tif size != c.Size {\n\t\t\t\tt.Fatalf(\"expected size %d but found %d\", c.Size, size)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc simpleType(s string) *ArgumentStr {\n\treturn &ArgumentStr{\n\t\tType: s,\n\t}\n}\n"
  },
  {
    "path": "blocktracker/blocktracker.go",
    "content": "package blocktracker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\n// BlockProvider are the eth1x methods required by the block tracker\ntype BlockProvider interface {\n\tGetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block, error)\n\tGetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error)\n}\n\nconst (\n\tdefaultMaxBlockBacklog = 10\n)\n\n// BlockTracker is an interface to track new blocks on the chain\ntype BlockTracker struct {\n\tconfig       *Config\n\tblocks       []*ethgo.Block\n\tblocksLock   sync.Mutex\n\tsubscriber   BlockTrackerInterface\n\tblockChs     []chan *BlockEvent\n\tblockChsLock sync.Mutex\n\tprovider     BlockProvider\n\tonce         sync.Once\n\tcloseCh      chan struct{}\n}\n\ntype Config struct {\n\tTracker         BlockTrackerInterface\n\tMaxBlockBacklog uint64\n}\n\nfunc DefaultConfig() *Config {\n\treturn &Config{\n\t\tMaxBlockBacklog: defaultMaxBlockBacklog,\n\t}\n}\n\ntype ConfigOption func(*Config)\n\nfunc WithBlockMaxBacklog(b uint64) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.MaxBlockBacklog = b\n\t}\n}\n\nfunc WithTracker(b BlockTrackerInterface) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.Tracker = b\n\t}\n}\n\nfunc NewBlockTracker(provider BlockProvider, opts ...ConfigOption) *BlockTracker {\n\tconfig := DefaultConfig()\n\tfor _, opt := range opts {\n\t\topt(config)\n\t}\n\ttracker := config.Tracker\n\tif tracker == nil {\n\t\ttracker = NewJSONBlockTracker(provider)\n\t}\n\treturn &BlockTracker{\n\t\tblocks:     []*ethgo.Block{},\n\t\tblockChs:   []chan *BlockEvent{},\n\t\tconfig:     config,\n\t\tsubscriber: tracker,\n\t\tprovider:   provider,\n\t\tcloseCh:    make(chan struct{}),\n\t}\n}\n\nfunc (b *BlockTracker) Subscribe() chan *BlockEvent {\n\tb.blockChsLock.Lock()\n\tdefer b.blockChsLock.Unlock()\n\n\tch := make(chan *BlockEvent, 1)\n\tb.blockChs = append(b.blockChs, ch)\n\treturn ch\n}\n\nfunc (b *BlockTracker) AcquireLock() Lock {\n\treturn NewLock(&b.blocksLock)\n}\n\nfunc (t *BlockTracker) Init() (err error) {\n\tvar block *ethgo.Block\n\tt.once.Do(func() {\n\t\tblock, err = t.provider.GetBlockByNumber(ethgo.Latest, false)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tif block.Number == 0 {\n\t\t\treturn\n\t\t}\n\n\t\tblocks := make([]*ethgo.Block, t.config.MaxBlockBacklog)\n\n\t\tvar i uint64\n\t\tfor i = 0; i < t.config.MaxBlockBacklog; i++ {\n\t\t\tblocks[t.config.MaxBlockBacklog-i-1] = block\n\t\t\tif block.Number == 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tblock, err = t.provider.GetBlockByHash(block.ParentHash, false)\n\t\t\tif err != nil {\n\t\t\t\treturn\n\t\t\t} else if block == nil {\n\t\t\t\t// if block does not exist (for example reorg happened) GetBlockByHash will return nil, nil\n\t\t\t\terr = fmt.Errorf(\"block with hash %s not found\", block.ParentHash)\n\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif i != t.config.MaxBlockBacklog {\n\t\t\t// less than maxBacklog elements\n\t\t\tblocks = blocks[t.config.MaxBlockBacklog-i-1:]\n\t\t}\n\t\tt.blocks = blocks\n\t})\n\treturn err\n}\n\nfunc (b *BlockTracker) MaxBlockBacklog() uint64 {\n\treturn b.config.MaxBlockBacklog\n}\n\nfunc (b *BlockTracker) LastBlocked() *ethgo.Block {\n\ttarget := b.blocks[len(b.blocks)-1]\n\tif target == nil {\n\t\treturn nil\n\t}\n\treturn target.Copy()\n}\n\nfunc (b *BlockTracker) BlocksBlocked() []*ethgo.Block {\n\tres := []*ethgo.Block{}\n\tfor _, i := range b.blocks {\n\t\tres = append(res, i.Copy())\n\t}\n\treturn res\n}\n\nfunc (b *BlockTracker) Len() int {\n\treturn len(b.blocks)\n}\n\nfunc (b *BlockTracker) Close() error {\n\tclose(b.closeCh)\n\treturn nil\n}\n\nfunc (b *BlockTracker) Start() error {\n\tctx, cancelFn := context.WithCancel(context.Background())\n\tgo func() {\n\t\t<-b.closeCh\n\t\tcancelFn()\n\t}()\n\t// start the polling\n\terr := b.subscriber.Track(ctx, func(block *ethgo.Block) error {\n\t\treturn b.HandleReconcile(block)\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn err\n}\n\nfunc (t *BlockTracker) AddBlockLocked(block *ethgo.Block) error {\n\tif uint64(len(t.blocks)) == t.config.MaxBlockBacklog {\n\t\t// remove past blocks if there are more than maxReconcileBlocks\n\t\tt.blocks = t.blocks[1:]\n\t}\n\tif len(t.blocks) != 0 {\n\t\tlastNum := t.blocks[len(t.blocks)-1].Number\n\t\tif lastNum+1 != block.Number {\n\t\t\treturn fmt.Errorf(\"bad number sequence. %d and %d\", lastNum, block.Number)\n\t\t}\n\t}\n\tt.blocks = append(t.blocks, block)\n\treturn nil\n}\n\nfunc (t *BlockTracker) blockAtIndex(hash ethgo.Hash) int {\n\tfor indx, b := range t.blocks {\n\t\tif b.Hash == hash {\n\t\t\treturn indx\n\t\t}\n\t}\n\treturn -1\n}\n\nfunc (t *BlockTracker) handleReconcileImpl(block *ethgo.Block) ([]*ethgo.Block, int, error) {\n\t// The block already exists\n\tif t.blockAtIndex(block.Hash) != -1 {\n\t\treturn nil, -1, nil\n\t}\n\n\t// The state is empty\n\tif len(t.blocks) == 0 {\n\t\treturn []*ethgo.Block{block}, -1, nil\n\t}\n\n\t// Append to the head of the chain\n\tif t.blocks[len(t.blocks)-1].Hash == block.ParentHash {\n\t\treturn []*ethgo.Block{block}, -1, nil\n\t}\n\n\t// Fork in the middle of the chain\n\tif indx := t.blockAtIndex(block.ParentHash); indx != -1 {\n\t\treturn []*ethgo.Block{block}, indx, nil\n\t}\n\n\t// Backfill. We dont know the parent of the block.\n\t// Need to query the chain untill we find a known block\n\n\tadded := []*ethgo.Block{block}\n\tvar indx int\n\n\tcount := uint64(0)\n\tfor {\n\t\tif count > t.config.MaxBlockBacklog {\n\t\t\treturn nil, -1, fmt.Errorf(\"cannot reconcile more than max backlog values\")\n\t\t}\n\t\tcount++\n\n\t\tparent, err := t.provider.GetBlockByHash(block.ParentHash, false)\n\t\tif err != nil {\n\t\t\treturn nil, -1, fmt.Errorf(\"parent with hash retrieving error: %w\", err)\n\t\t} else if parent == nil {\n\t\t\t// if block does not exist (for example reorg happened) GetBlockByHash will return nil, nil\n\t\t\treturn nil, -1, fmt.Errorf(\"parent with hash %s not found\", block.ParentHash)\n\t\t}\n\n\t\tadded = append(added, parent)\n\t\tif indx = t.blockAtIndex(parent.ParentHash); indx != -1 {\n\t\t\tbreak\n\t\t}\n\t\tblock = parent\n\t}\n\n\t// need the blocks in reverse order\n\tblocks := []*ethgo.Block{}\n\tfor i := len(added) - 1; i >= 0; i-- {\n\t\tblocks = append(blocks, added[i])\n\t}\n\treturn blocks, indx, nil\n}\n\nfunc (t *BlockTracker) HandleBlockEvent(block *ethgo.Block) (*BlockEvent, error) {\n\tt.blocksLock.Lock()\n\tdefer t.blocksLock.Unlock()\n\n\tblocks, indx, err := t.handleReconcileImpl(block)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(blocks) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tblockEvnt := &BlockEvent{}\n\n\t// there are some blocks to remove\n\tif indx != -1 {\n\t\tfor i := indx + 1; i < len(t.blocks); i++ {\n\t\t\tblockEvnt.Removed = append(blockEvnt.Removed, t.blocks[i])\n\t\t}\n\t\tt.blocks = t.blocks[:indx+1]\n\t}\n\n\t// include the new blocks\n\tfor _, block := range blocks {\n\t\tblockEvnt.Added = append(blockEvnt.Added, block)\n\t\tif err := t.AddBlockLocked(block); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn blockEvnt, nil\n}\n\nfunc (t *BlockTracker) HandleReconcile(block *ethgo.Block) error {\n\tblockEvnt, err := t.HandleBlockEvent(block)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif blockEvnt == nil {\n\t\treturn nil\n\t}\n\n\tt.blockChsLock.Lock()\n\tfor _, ch := range t.blockChs {\n\t\tselect {\n\t\tcase ch <- blockEvnt:\n\t\tdefault:\n\t\t}\n\t}\n\tt.blockChsLock.Unlock()\n\n\treturn nil\n}\n\ntype BlockTrackerInterface interface {\n\tTrack(context.Context, func(block *ethgo.Block) error) error\n}\n\nconst (\n\tdefaultPollInterval = 1 * time.Second\n)\n\n// JSONBlockTracker implements the BlockTracker interface using\n// the http jsonrpc endpoint\ntype JSONBlockTracker struct {\n\tPollInterval time.Duration\n\tprovider     BlockProvider\n}\n\n// NewJSONBlockTracker creates a new json block tracker\nfunc NewJSONBlockTracker(provider BlockProvider) *JSONBlockTracker {\n\treturn &JSONBlockTracker{\n\t\tprovider:     provider,\n\t\tPollInterval: defaultPollInterval,\n\t}\n}\n\n// Track implements the BlockTracker interface.\n// This can take a long time so should be run concurrently.\nfunc (k *JSONBlockTracker) Track(ctx context.Context, handle func(block *ethgo.Block) error) error {\n\tvar lastBlock *ethgo.Block\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\n\t\tcase <-time.After(k.PollInterval):\n\t\t\tblock, err := k.provider.GetBlockByNumber(ethgo.Latest, false)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif lastBlock != nil && lastBlock.Hash == block.Hash {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif err := handle(block); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tlastBlock = block\n\t\t}\n\t}\n}\n\n// SubscriptionBlockTracker is an interface to track new blocks using\n// the newHeads subscription endpoint\ntype SubscriptionBlockTracker struct {\n\tclient *jsonrpc.Client\n}\n\n// NewSubscriptionBlockTracker creates a new block tracker using the subscription endpoint\nfunc NewSubscriptionBlockTracker(client *jsonrpc.Client) (*SubscriptionBlockTracker, error) {\n\tif !client.SubscriptionEnabled() {\n\t\treturn nil, fmt.Errorf(\"subscription is not enabled\")\n\t}\n\ts := &SubscriptionBlockTracker{\n\t\tclient: client,\n\t}\n\treturn s, nil\n}\n\n// Track implements the BlockTracker interface\n// This can take a long time so should be run concurrently.\n// Note that the error return variable must be named so that subscription cancellation errors can be returned in defer.\nfunc (s *SubscriptionBlockTracker) Track(ctx context.Context, handle func(block *ethgo.Block) error) (err error) {\n\tdata := make(chan []byte)\n\tdefer close(data)\n\n\t// Subscribe with a callback. This callback must be unsubscribed\n\t// before the data channel is closed, otherwise panic (write to closed channel)\n\tcallback := func(b []byte) {\n\t\tdata <- b\n\t}\n\tunsubscribe, err := s.client.Subscribe(\"newHeads\", callback)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() {\n\t\tif cerr := unsubscribe(); cerr != nil {\n\t\t\t// Ensure subscription cancellation errors are returned via named return var\n\t\t\tif err == nil {\n\t\t\t\terr = cerr\n\t\t\t\treturn\n\t\t\t}\n\t\t\terr = fmt.Errorf(\"failed to cancel: %s, after error %w\", cerr.Error(), err)\n\t\t}\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase buf := <-data:\n\t\t\tvar block ethgo.Block\n\t\t\tif err := block.UnmarshalJSON(buf); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := handle(&block); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\t}\n\t}\n}\n\ntype Lock struct {\n\tLocked bool\n\tlock   *sync.Mutex\n}\n\nfunc NewLock(lock *sync.Mutex) Lock {\n\treturn Lock{lock: lock}\n}\n\nfunc (l *Lock) Lock() {\n\tl.Locked = true\n\tl.lock.Lock()\n}\n\nfunc (l *Lock) Unlock() {\n\tl.Locked = false\n\tl.lock.Unlock()\n}\n\n// EventType is the type of the event\ntype EventType int\n\nconst (\n\t// EventAdd happens when a new event is included in the chain\n\tEventAdd EventType = iota\n\t// EventDel may happen when there is a reorg and a past event is deleted\n\tEventDel\n)\n\n// Event is an event emitted when a new log is included\ntype Event struct {\n\tType    EventType\n\tAdded   []*ethgo.Log\n\tRemoved []*ethgo.Log\n}\n\n// BlockEvent is an event emitted when a new block is included\ntype BlockEvent struct {\n\tType    EventType\n\tAdded   []*ethgo.Block\n\tRemoved []*ethgo.Block\n}\n"
  },
  {
    "path": "blocktracker/blocktracker_test.go",
    "content": "package blocktracker\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc testListener(t *testing.T, server *testutil.TestServer, tracker BlockTrackerInterface) {\n\tctx, cancelFn := context.WithCancel(context.Background())\n\tdefer cancelFn()\n\n\tblocks := make(chan *ethgo.Block)\n\terr := tracker.Track(ctx, func(block *ethgo.Block) error {\n\t\tblocks <- block\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tvar lastBlock *ethgo.Block\n\tcount := uint64(0)\n\trecv := func() {\n\t\tcount++\n\n\t\tselect {\n\t\tcase block := <-blocks:\n\t\t\tif lastBlock != nil {\n\t\t\t\tif lastBlock.Number+1 != block.Number {\n\t\t\t\t\tt.Fatalf(\"bad sequence %d %d\", lastBlock.Number, block.Number)\n\t\t\t\t}\n\t\t\t}\n\t\t\tlastBlock = block\n\n\t\tcase <-time.After(4 * time.Second):\n\t\t\tt.Fatal(\"timeout to receive block tracker block\")\n\t\t}\n\t}\n\n\tserver.ProcessBlock()\n\trecv()\n\n\tserver.ProcessBlock()\n\trecv()\n}\n\nfunc TestBlockTracker_Listener_JsonRPC(t *testing.T) {\n\tt.Skip(\"Too brittle on CI, FIX\")\n\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := jsonrpc.NewClient(s.HTTPAddr())\n\tdefer c.Close()\n\n\ttracker := NewJSONBlockTracker(c.Eth())\n\ttracker.PollInterval = 1 * time.Second\n\ttestListener(t, s, tracker)\n}\n\nfunc TestBlockTracker_Listener_Websocket(t *testing.T) {\n\tt.Skip(\"Too brittle on CI, FIX\")\n\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := jsonrpc.NewClient(s.WSAddr())\n\tdefer c.Close()\n\n\ttracker, err := NewSubscriptionBlockTracker(c)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ttestListener(t, s, tracker)\n}\n\nfunc TestBlockTracker_Lifecycle(t *testing.T) {\n\tt.Skip()\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := jsonrpc.NewClient(s.HTTPAddr())\n\ttr := NewBlockTracker(c.Eth())\n\tassert.NoError(t, tr.Init())\n\n\tgo tr.Start()\n\n\t// try to mine a block at least every 1 second\n\tgo func() {\n\t\tfor i := 0; i < 10; i++ {\n\t\t\ts.ProcessBlock()\n\t\t\ttime.After(1 * time.Second)\n\t\t}\n\t}()\n\n\tsub := tr.Subscribe()\n\tfor i := 0; i < 10; i++ {\n\t\tselect {\n\t\tcase <-sub:\n\t\tcase <-time.After(2 * time.Second):\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t}\n}\n\nfunc TestBlockTracker_PopulateBlocks(t *testing.T) {\n\t// more than maxBackLog blocks\n\t{\n\t\tl := testutil.MockList{}\n\t\tl.Create(0, 15, func(b *testutil.MockBlock) {})\n\n\t\tm := &testutil.MockClient{}\n\t\tm.AddScenario(l)\n\n\t\ttt0 := NewBlockTracker(m)\n\n\t\terr := tt0.Init()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !testutil.CompareBlocks(l.ToBlocks()[5:], tt0.blocks) {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t}\n\t// less than maxBackLog\n\t{\n\t\tl0 := testutil.MockList{}\n\t\tl0.Create(0, 5, func(b *testutil.MockBlock) {})\n\n\t\tm1 := &testutil.MockClient{}\n\t\tm1.AddScenario(l0)\n\n\t\ttt1 := NewBlockTracker(m1)\n\t\ttt1.provider = m1\n\n\t\terr := tt1.Init()\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tif !testutil.CompareBlocks(l0.ToBlocks(), tt1.blocks) {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t}\n}\n\nfunc TestBlockTracker_Events(t *testing.T) {\n\n\ttype TestEvent struct {\n\t\tAdded   testutil.MockList\n\t\tRemoved testutil.MockList\n\t}\n\n\ttype Reconcile struct {\n\t\tblock *testutil.MockBlock\n\t\tevent *TestEvent\n\t}\n\n\tcases := []struct {\n\t\tName      string\n\t\tScenario  testutil.MockList\n\t\tHistory   testutil.MockList\n\t\tReconcile []Reconcile\n\t\tExpected  testutil.MockList\n\t}{\n\t\t{\n\t\t\tName: \"Empty history\",\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x1),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: []*testutil.MockBlock{\n\t\t\t\ttestutil.Mock(1),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Repeated header\",\n\t\t\tHistory: []*testutil.MockBlock{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x1),\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: []*testutil.MockBlock{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"New head\",\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x2),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Ignore block already on history\",\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x2),\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Multi Roll back\",\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\ttestutil.Mock(0x4),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x30).Parent(0x2),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x30).Parent(0x2),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tRemoved: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\t\t\t\ttestutil.Mock(0x4),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x30).Parent(0x2),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Backfills missing blocks\",\n\t\t\tScenario: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\ttestutil.Mock(0x4),\n\t\t\t},\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x5),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\t\t\t\ttestutil.Mock(0x4),\n\t\t\t\t\t\t\ttestutil.Mock(0x5),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\ttestutil.Mock(0x4),\n\t\t\t\ttestutil.Mock(0x5),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Rolls back and backfills\",\n\t\t\tScenario: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Num(3),\n\t\t\t\ttestutil.Mock(0x40).Parent(0x30).Num(4),\n\t\t\t},\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\ttestutil.Mock(0x4),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x50).Parent(0x40).Num(5),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Num(3),\n\t\t\t\t\t\t\ttestutil.Mock(0x40).Parent(0x30).Num(4),\n\t\t\t\t\t\t\ttestutil.Mock(0x50).Parent(0x40).Num(5),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tRemoved: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\t\t\t\ttestutil.Mock(0x4),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Num(3),\n\t\t\t\ttestutil.Mock(0x40).Parent(0x30).Num(4),\n\t\t\t\ttestutil.Mock(0x50).Parent(0x40).Num(5),\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.Name, func(t *testing.T) {\n\t\t\t// safe check for now, we ma need to restart the tracker and mock client for every reconcile scenario?\n\t\t\tif len(c.Reconcile) != 1 {\n\t\t\t\tt.Fatal(\"only one reconcile supported so far\")\n\t\t\t}\n\n\t\t\tm := &testutil.MockClient{}\n\n\t\t\t// add the full scenario with the logs\n\t\t\tm.AddScenario(c.Scenario)\n\n\t\t\ttt := NewBlockTracker(m)\n\n\t\t\t// build past block history\n\t\t\tfor _, b := range c.History.ToBlocks() {\n\t\t\t\ttt.AddBlockLocked(b)\n\t\t\t}\n\n\t\t\tsub := tt.Subscribe()\n\t\t\tfor _, b := range c.Reconcile {\n\t\t\t\tif err := tt.HandleReconcile(b.block.Block()); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tif b.event == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tvar blockEvnt *BlockEvent\n\t\t\t\tselect {\n\t\t\t\tcase blockEvnt = <-sub:\n\t\t\t\tcase <-time.After(1 * time.Second):\n\t\t\t\t\tt.Fatal(\"block event timeout\")\n\t\t\t\t}\n\n\t\t\t\t// check blocks\n\t\t\t\tif !testutil.CompareBlocks(b.event.Added.ToBlocks(), blockEvnt.Added) {\n\t\t\t\t\tt.Fatal(\"err\")\n\t\t\t\t}\n\t\t\t\tif !testutil.CompareBlocks(b.event.Removed.ToBlocks(), blockEvnt.Removed) {\n\t\t\t\t\tt.Fatal(\"err\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !testutil.CompareBlocks(tt.blocks, c.Expected.ToBlocks()) {\n\t\t\t\tt.Fatal(\"bad\")\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "builtin/ens/artifacts/ENS.abi",
    "content": "[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"}]"
  },
  {
    "path": "builtin/ens/artifacts/Resolver.abi",
    "content": "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"ret\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"ret\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"name\":\"ret\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"}]"
  },
  {
    "path": "builtin/ens/ens.go",
    "content": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: bfee2618a5908e1a24f19dcce873d3b8e797374138dd7604f7b593db3cca5c17\n// Version: 0.1.1\npackage ens\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nvar (\n\t_ = big.NewInt\n\t_ = jsonrpc.NewClient\n)\n\n// ENS is a solidity contract\ntype ENS struct {\n\tc *contract.Contract\n}\n\n// DeployENS deploys a new ENS contract\nfunc DeployENS(provider *jsonrpc.Client, from ethgo.Address, args []interface{}, opts ...contract.ContractOption) (contract.Txn, error) {\n\treturn contract.DeployContract(abiENS, binENS, args, opts...)\n}\n\n// NewENS creates a new instance of the contract at a specific address\nfunc NewENS(addr ethgo.Address, opts ...contract.ContractOption) *ENS {\n\treturn &ENS{c: contract.NewContract(addr, abiENS, opts...)}\n}\n\n// calls\n\n// Owner calls the owner method in the solidity contract\nfunc (e *ENS) Owner(node [32]byte, block ...ethgo.BlockNumber) (retval0 ethgo.Address, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"owner\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(ethgo.Address)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Resolver calls the resolver method in the solidity contract\nfunc (e *ENS) Resolver(node [32]byte, block ...ethgo.BlockNumber) (retval0 ethgo.Address, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"resolver\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(ethgo.Address)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Ttl calls the ttl method in the solidity contract\nfunc (e *ENS) Ttl(node [32]byte, block ...ethgo.BlockNumber) (retval0 uint64, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"ttl\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(uint64)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// txns\n\n// SetOwner sends a setOwner transaction in the solidity contract\nfunc (e *ENS) SetOwner(node [32]byte, owner ethgo.Address) (contract.Txn, error) {\n\treturn e.c.Txn(\"setOwner\", node, owner)\n}\n\n// SetResolver sends a setResolver transaction in the solidity contract\nfunc (e *ENS) SetResolver(node [32]byte, resolver ethgo.Address) (contract.Txn, error) {\n\treturn e.c.Txn(\"setResolver\", node, resolver)\n}\n\n// SetSubnodeOwner sends a setSubnodeOwner transaction in the solidity contract\nfunc (e *ENS) SetSubnodeOwner(node [32]byte, label [32]byte, owner ethgo.Address) (contract.Txn, error) {\n\treturn e.c.Txn(\"setSubnodeOwner\", node, label, owner)\n}\n\n// SetTTL sends a setTTL transaction in the solidity contract\nfunc (e *ENS) SetTTL(node [32]byte, ttl uint64) (contract.Txn, error) {\n\treturn e.c.Txn(\"setTTL\", node, ttl)\n}\n\n// events\n\nfunc (e *ENS) NewOwnerEventSig() ethgo.Hash {\n\treturn e.c.GetABI().Events[\"NewOwner\"].ID()\n}\n\nfunc (e *ENS) NewResolverEventSig() ethgo.Hash {\n\treturn e.c.GetABI().Events[\"NewResolver\"].ID()\n}\n\nfunc (e *ENS) NewTTLEventSig() ethgo.Hash {\n\treturn e.c.GetABI().Events[\"NewTTL\"].ID()\n}\n\nfunc (e *ENS) TransferEventSig() ethgo.Hash {\n\treturn e.c.GetABI().Events[\"Transfer\"].ID()\n}\n"
  },
  {
    "path": "builtin/ens/ens_artifacts.go",
    "content": "package ens\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiENS *abi.ABI\n\n// ENSAbi returns the abi of the ENS contract\nfunc ENSAbi() *abi.ABI {\n\treturn abiENS\n}\n\nvar binENS []byte\n\n// ENSBin returns the bin of the ENS contract\nfunc ENSBin() []byte {\n\treturn binENS\n}\n\nfunc init() {\n\tvar err error\n\tabiENS, err = abi.NewABI(abiENSStr)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"cannot parse ENS abi: %v\", err))\n\t}\n\tif len(binENSStr) != 0 {\n\t\tbinENS, err = hex.DecodeString(binENSStr[2:])\n\t\tif err != nil {\n\t\t\tpanic(fmt.Errorf(\"cannot parse ENS bin: %v\", err))\n\t\t}\n\t}\n}\n\nvar binENSStr = \"0x6060604052341561000f57600080fd5b60008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a033316600160a060020a0319909116179055610503806100626000396000f3006060604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100b957806306ab5923146100cf57806314ab9038146100f657806316a25cbd146101195780631896f70a1461014c5780635b0fc9c31461016e575b600080fd5b341561009257600080fd5b61009d600435610190565b604051600160a060020a03909116815260200160405180910390f35b34156100c457600080fd5b61009d6004356101ae565b34156100da57600080fd5b6100f4600435602435600160a060020a03604435166101c9565b005b341561010157600080fd5b6100f460043567ffffffffffffffff6024351661028b565b341561012457600080fd5b61012f600435610357565b60405167ffffffffffffffff909116815260200160405180910390f35b341561015757600080fd5b6100f4600435600160a060020a036024351661038e565b341561017957600080fd5b6100f4600435600160a060020a0360243516610434565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b600083815260208190526040812054849033600160a060020a039081169116146101f257600080fd5b8484604051918252602082015260409081019051908190039020915083857fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8285604051600160a060020a03909116815260200160405180910390a3506000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555050565b600082815260208190526040902054829033600160a060020a039081169116146102b457600080fd5b827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa688360405167ffffffffffffffff909116815260200160405180910390a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b600082815260208190526040902054829033600160a060020a039081169116146103b757600080fd5b827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600082815260208190526040902054829033600160a060020a0390811691161461045d57600080fd5b827fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26683604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555600a165627a7a72305820f4c798d4c84c9912f389f64631e85e8d16c3e6644f8c2e1579936015c7d5f6660029\"\n\nvar abiENSStr = `[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"}]`\n"
  },
  {
    "path": "builtin/ens/ens_resolver.go",
    "content": "package ens\n\nimport (\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"strings\"\n)\n\ntype ENSResolver struct {\n\te        *ENS\n\tprovider *jsonrpc.Eth\n}\n\nfunc NewENSResolver(addr ethgo.Address, provider *jsonrpc.Client) *ENSResolver {\n\treturn &ENSResolver{NewENS(addr, contract.WithJsonRPC(provider.Eth())), provider.Eth()}\n}\n\nfunc (e *ENSResolver) Resolve(addr string, block ...ethgo.BlockNumber) (res ethgo.Address, err error) {\n\taddrHash := NameHash(addr)\n\tresolver, err := e.prepareResolver(addrHash, block...)\n\tif err != nil {\n\t\treturn\n\t}\n\tres, err = resolver.Addr(addrHash, block...)\n\treturn\n}\n\nfunc addressToReverseDomain(addr ethgo.Address) string {\n\treturn strings.ToLower(strings.TrimPrefix(addr.String(), \"0x\")) + \".addr.reverse\"\n}\n\nfunc (e *ENSResolver) ReverseResolve(addr ethgo.Address, block ...ethgo.BlockNumber) (res string, err error) {\n\taddrHash := NameHash(addressToReverseDomain(addr))\n\n\tresolver, err := e.prepareResolver(addrHash, block...)\n\tif err != nil {\n\t\treturn\n\t}\n\tres, err = resolver.Name(addrHash, block...)\n\treturn\n}\n\nfunc (e *ENSResolver) prepareResolver(inputHash ethgo.Hash, block ...ethgo.BlockNumber) (*Resolver, error) {\n\tresolverAddr, err := e.e.Resolver(inputHash, block...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresolver := NewResolver(resolverAddr, contract.WithJsonRPC(e.provider))\n\treturn resolver, nil\n}\n"
  },
  {
    "path": "builtin/ens/ens_resolver_test.go",
    "content": "package ens\n\nimport (\n\t\"encoding/hex\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nvar (\n\tmainnetAddr = ethgo.HexToAddress(\"0x314159265dD8dbb310642f98f50C066173C1259b\")\n)\n\nfunc TestResolveAddr(t *testing.T) {\n\tc, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))\n\tr := NewENSResolver(mainnetAddr, c)\n\n\tcases := []struct {\n\t\tAddr     string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\tAddr:     \"arachnid.eth\",\n\t\t\tExpected: \"0xfdb33f8ac7ce72d7d4795dd8610e323b4c122fbb\",\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tfound, err := r.Resolve(c.Addr)\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.Equal(t, \"0x\"+hex.EncodeToString(found[:]), c.Expected)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "builtin/ens/resolver.go",
    "content": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: 3d1ecdf4aa6a2c578e0c3bbb14cc28ae2c8ebc4495f7d6128959f961afd0f635\n// Version: 0.1.1\npackage ens\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nvar (\n\t_ = big.NewInt\n\t_ = jsonrpc.NewClient\n)\n\n// Resolver is a solidity contract\ntype Resolver struct {\n\tc *contract.Contract\n}\n\n// DeployResolver deploys a new Resolver contract\nfunc DeployResolver(provider *jsonrpc.Client, from ethgo.Address, args []interface{}, opts ...contract.ContractOption) (contract.Txn, error) {\n\treturn contract.DeployContract(abiResolver, binResolver, args, opts...)\n}\n\n// NewResolver creates a new instance of the contract at a specific address\nfunc NewResolver(addr ethgo.Address, opts ...contract.ContractOption) *Resolver {\n\treturn &Resolver{c: contract.NewContract(addr, abiResolver, opts...)}\n}\n\n// calls\n\n// ABI calls the ABI method in the solidity contract\nfunc (r *Resolver) ABI(node [32]byte, contentTypes *big.Int, block ...ethgo.BlockNumber) (retval0 *big.Int, retval1 []byte, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = r.c.Call(\"ABI\", ethgo.EncodeBlock(block...), node, contentTypes)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"contentType\"].(*big.Int)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\tretval1, ok = out[\"data\"].([]byte)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 1\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Addr calls the addr method in the solidity contract\nfunc (r *Resolver) Addr(node [32]byte, block ...ethgo.BlockNumber) (retval0 ethgo.Address, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = r.c.Call(\"addr\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"ret\"].(ethgo.Address)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Content calls the content method in the solidity contract\nfunc (r *Resolver) Content(node [32]byte, block ...ethgo.BlockNumber) (retval0 [32]byte, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = r.c.Call(\"content\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"ret\"].([32]byte)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Name calls the name method in the solidity contract\nfunc (r *Resolver) Name(node [32]byte, block ...ethgo.BlockNumber) (retval0 string, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = r.c.Call(\"name\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"ret\"].(string)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Pubkey calls the pubkey method in the solidity contract\nfunc (r *Resolver) Pubkey(node [32]byte, block ...ethgo.BlockNumber) (retval0 [32]byte, retval1 [32]byte, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = r.c.Call(\"pubkey\", ethgo.EncodeBlock(block...), node)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"x\"].([32]byte)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\tretval1, ok = out[\"y\"].([32]byte)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 1\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// SupportsInterface calls the supportsInterface method in the solidity contract\nfunc (r *Resolver) SupportsInterface(interfaceID [4]byte, block ...ethgo.BlockNumber) (retval0 bool, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = r.c.Call(\"supportsInterface\", ethgo.EncodeBlock(block...), interfaceID)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(bool)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// txns\n\n// SetABI sends a setABI transaction in the solidity contract\nfunc (r *Resolver) SetABI(node [32]byte, contentType *big.Int, data []byte) (contract.Txn, error) {\n\treturn r.c.Txn(\"setABI\", node, contentType, data)\n}\n\n// SetAddr sends a setAddr transaction in the solidity contract\nfunc (r *Resolver) SetAddr(node [32]byte, addr ethgo.Address) (contract.Txn, error) {\n\treturn r.c.Txn(\"setAddr\", node, addr)\n}\n\n// SetContent sends a setContent transaction in the solidity contract\nfunc (r *Resolver) SetContent(node [32]byte, hash [32]byte) (contract.Txn, error) {\n\treturn r.c.Txn(\"setContent\", node, hash)\n}\n\n// SetName sends a setName transaction in the solidity contract\nfunc (r *Resolver) SetName(node [32]byte, name string) (contract.Txn, error) {\n\treturn r.c.Txn(\"setName\", node, name)\n}\n\n// SetPubkey sends a setPubkey transaction in the solidity contract\nfunc (r *Resolver) SetPubkey(node [32]byte, x [32]byte, y [32]byte) (contract.Txn, error) {\n\treturn r.c.Txn(\"setPubkey\", node, x, y)\n}\n\n// events\n\nfunc (r *Resolver) ABIChangedEventSig() ethgo.Hash {\n\treturn r.c.GetABI().Events[\"ABIChanged\"].ID()\n}\n\nfunc (r *Resolver) AddrChangedEventSig() ethgo.Hash {\n\treturn r.c.GetABI().Events[\"AddrChanged\"].ID()\n}\n\nfunc (r *Resolver) ContentChangedEventSig() ethgo.Hash {\n\treturn r.c.GetABI().Events[\"ContentChanged\"].ID()\n}\n\nfunc (r *Resolver) NameChangedEventSig() ethgo.Hash {\n\treturn r.c.GetABI().Events[\"NameChanged\"].ID()\n}\n\nfunc (r *Resolver) PubkeyChangedEventSig() ethgo.Hash {\n\treturn r.c.GetABI().Events[\"PubkeyChanged\"].ID()\n}\n"
  },
  {
    "path": "builtin/ens/resolver_artifacts.go",
    "content": "package ens\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiResolver *abi.ABI\n\n// ResolverAbi returns the abi of the Resolver contract\nfunc ResolverAbi() *abi.ABI {\n\treturn abiResolver\n}\n\nvar binResolver []byte\n\n// ResolverBin returns the bin of the Resolver contract\nfunc ResolverBin() []byte {\n\treturn binResolver\n}\n\nfunc init() {\n\tvar err error\n\tabiResolver, err = abi.NewABI(abiResolverStr)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"cannot parse Resolver abi: %v\", err))\n\t}\n\tif len(binResolverStr) != 0 {\n\t\tbinResolver, err = hex.DecodeString(binResolverStr[2:])\n\t\tif err != nil {\n\t\t\tpanic(fmt.Errorf(\"cannot parse Resolver bin: %v\", err))\n\t\t}\n\t}\n}\n\nvar binResolverStr = \"0x6060604052341561000f57600080fd5b6040516020806111b28339810160405280805160008054600160a060020a03909216600160a060020a0319909216919091179055505061115e806100546000396000f3006060604052600436106100ab5763ffffffff60e060020a60003504166301ffc9a781146100b057806310f13a8c146100e45780632203ab561461017e57806329cd62ea146102155780632dff6941146102315780633b3b57de1461025957806359d1d43c1461028b578063623195b014610358578063691f3431146103b457806377372213146103ca578063c3d014d614610420578063c869023314610439578063d5fa2b0014610467575b600080fd5b34156100bb57600080fd5b6100d0600160e060020a031960043516610489565b604051901515815260200160405180910390f35b34156100ef57600080fd5b61017c600480359060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f0160208091040260200160405190810160405281815292919060208401838380828437509496506105f695505050505050565b005b341561018957600080fd5b610197600435602435610807565b60405182815260406020820181815290820183818151815260200191508051906020019080838360005b838110156101d95780820151838201526020016101c1565b50505050905090810190601f1680156102065780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561022057600080fd5b61017c600435602435604435610931565b341561023c57600080fd5b610247600435610a30565b60405190815260200160405180910390f35b341561026457600080fd5b61026f600435610a46565b604051600160a060020a03909116815260200160405180910390f35b341561029657600080fd5b6102e1600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610a6195505050505050565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561031d578082015183820152602001610305565b50505050905090810190601f16801561034a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561036357600080fd5b61017c600480359060248035919060649060443590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610b8095505050505050565b34156103bf57600080fd5b6102e1600435610c7c565b34156103d557600080fd5b61017c600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610d4295505050505050565b341561042b57600080fd5b61017c600435602435610e8c565b341561044457600080fd5b61044f600435610f65565b60405191825260208201526040908101905180910390f35b341561047257600080fd5b61017c600435600160a060020a0360243516610f82565b6000600160e060020a031982167f3b3b57de0000000000000000000000000000000000000000000000000000000014806104ec5750600160e060020a031982167fd8389dc500000000000000000000000000000000000000000000000000000000145b806105205750600160e060020a031982167f691f343100000000000000000000000000000000000000000000000000000000145b806105545750600160e060020a031982167f2203ab5600000000000000000000000000000000000000000000000000000000145b806105885750600160e060020a031982167fc869023300000000000000000000000000000000000000000000000000000000145b806105bc5750600160e060020a031982167f59d1d43c00000000000000000000000000000000000000000000000000000000145b806105f05750600160e060020a031982167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561064f57600080fd5b6102c65a03f1151561066057600080fd5b50505060405180519050600160a060020a031614151561067f57600080fd5b6000848152600160205260409081902083916005909101908590518082805190602001908083835b602083106106c65780518252601f1990920191602091820191016106a7565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902090805161070a929160200190611085565b50826040518082805190602001908083835b6020831061073b5780518252601f19909201916020918201910161071c565b6001836020036101000a0380198251168184511617909252505050919091019250604091505051908190039020847fd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a75508560405160208082528190810183818151815260200191508051906020019080838360005b838110156107c75780820151838201526020016107af565b50505050905090810190601f1680156107f45780820380516001836020036101000a031916815260200191505b509250505060405180910390a350505050565b6000610811611103565b60008481526001602081905260409091209092505b838311610924578284161580159061085f5750600083815260068201602052604081205460026000196101006001841615020190911604115b15610919578060060160008481526020019081526020016000208054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561090d5780601f106108e25761010080835404028352916020019161090d565b820191906000526020600020905b8154815290600101906020018083116108f057829003601f168201915b50505050509150610929565b600290920291610826565b600092505b509250929050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561098a57600080fd5b6102c65a03f1151561099b57600080fd5b50505060405180519050600160a060020a03161415156109ba57600080fd5b6040805190810160409081528482526020808301859052600087815260019091522060030181518155602082015160019091015550837f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e46848460405191825260208201526040908101905180910390a250505050565b6000908152600160208190526040909120015490565b600090815260016020526040902054600160a060020a031690565b610a69611103565b60008381526001602052604090819020600501908390518082805190602001908083835b60208310610aac5780518252601f199092019160209182019101610a8d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b735780601f10610b4857610100808354040283529160200191610b73565b820191906000526020600020905b815481529060010190602001808311610b5657829003601f168201915b5050505050905092915050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610bd957600080fd5b6102c65a03f11515610bea57600080fd5b50505060405180519050600160a060020a0316141515610c0957600080fd5b6000198301831615610c1a57600080fd5b60008481526001602090815260408083208684526006019091529020828051610c47929160200190611085565b5082847faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe360405160405180910390a350505050565b610c84611103565b6001600083600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d365780601f10610d0b57610100808354040283529160200191610d36565b820191906000526020600020905b815481529060010190602001808311610d1957829003601f168201915b50505050509050919050565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610d9b57600080fd5b6102c65a03f11515610dac57600080fd5b50505060405180519050600160a060020a0316141515610dcb57600080fd5b6000838152600160205260409020600201828051610ded929160200190611085565b50827fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78360405160208082528190810183818151815260200191508051906020019080838360005b83811015610e4d578082015183820152602001610e35565b50505050905090810190601f168015610e7a5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505050565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610ee557600080fd5b6102c65a03f11515610ef657600080fd5b50505060405180519050600160a060020a0316141515610f1557600080fd5b6000838152600160208190526040918290200183905583907f0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc9084905190815260200160405180910390a2505050565b600090815260016020526040902060038101546004909101549091565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610fdb57600080fd5b6102c65a03f11515610fec57600080fd5b50505060405180519050600160a060020a031614151561100b57600080fd5b60008381526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03851617905583907f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd290849051600160a060020a03909116815260200160405180910390a2505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106110c657805160ff19168380011785556110f3565b828001600101855582156110f3579182015b828111156110f35782518255916020019190600101906110d8565b506110ff929150611115565b5090565b60206040519081016040526000815290565b61112f91905b808211156110ff576000815560010161111b565b905600a165627a7a723058201ecacbc445b9fbcd91b0ab164389f69d7283b856883bc7437eeed1008345a4920029\"\n\nvar abiResolverStr = `[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"ret\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"ret\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"name\":\"ret\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"}]`\n"
  },
  {
    "path": "builtin/ens/utils.go",
    "content": "package ens\n\nimport (\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\n// NameHash returns the hash of an ENS name\nfunc NameHash(str string) (node ethgo.Hash) {\n\tif str == \"\" {\n\t\treturn\n\t}\n\n\taux := make([]byte, 32)\n\thash := sha3.NewLegacyKeccak256()\n\n\tlabels := strings.Split(str, \".\")\n\tfor i := len(labels) - 1; i >= 0; i-- {\n\t\tlabel := labels[i]\n\n\t\thash.Write([]byte(label))\n\t\taux = hash.Sum(aux) // append the hash of the label to node\n\t\thash.Reset()\n\n\t\thash.Write(aux)\n\t\taux = hash.Sum(aux[:0])\n\t\thash.Reset()\n\t}\n\n\tcopy(node[:], aux)\n\treturn\n}\n"
  },
  {
    "path": "builtin/ens/utils_test.go",
    "content": "package ens\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNameHash(t *testing.T) {\n\tcases := []struct {\n\t\tName     string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\tName:     \"eth\",\n\t\t\tExpected: \"0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae\",\n\t\t},\n\t\t{\n\t\t\tName:     \"foo.eth\",\n\t\t\tExpected: \"0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f\",\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\tfound := NameHash(c.Name)\n\t\t\tassert.Equal(t, c.Expected, found.String())\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "builtin/erc20/artifacts/ERC20.abi",
    "content": "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"}]"
  },
  {
    "path": "builtin/erc20/erc20.go",
    "content": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: a1a873d70d345feef023ee086fd6135b24d775444b950ee9d5ea411e72b0f373\n// Version: 0.1.1\npackage erc20\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nvar (\n\t_ = big.NewInt\n\t_ = jsonrpc.NewClient\n)\n\n// ERC20 is a solidity contract\ntype ERC20 struct {\n\tc *contract.Contract\n}\n\n// NewERC20 creates a new instance of the contract at a specific address\nfunc NewERC20(addr ethgo.Address, opts ...contract.ContractOption) *ERC20 {\n\treturn &ERC20{c: contract.NewContract(addr, abiERC20, opts...)}\n}\n\n// calls\n\n// Allowance calls the allowance method in the solidity contract\nfunc (e *ERC20) Allowance(owner ethgo.Address, spender ethgo.Address, block ...ethgo.BlockNumber) (retval0 *big.Int, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"allowance\", ethgo.EncodeBlock(block...), owner, spender)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(*big.Int)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// BalanceOf calls the balanceOf method in the solidity contract\nfunc (e *ERC20) BalanceOf(owner ethgo.Address, block ...ethgo.BlockNumber) (retval0 *big.Int, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"balanceOf\", ethgo.EncodeBlock(block...), owner)\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"balance\"].(*big.Int)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Decimals calls the decimals method in the solidity contract\nfunc (e *ERC20) Decimals(block ...ethgo.BlockNumber) (retval0 uint8, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"decimals\", ethgo.EncodeBlock(block...))\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(uint8)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Name calls the name method in the solidity contract\nfunc (e *ERC20) Name(block ...ethgo.BlockNumber) (retval0 string, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"name\", ethgo.EncodeBlock(block...))\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(string)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// Symbol calls the symbol method in the solidity contract\nfunc (e *ERC20) Symbol(block ...ethgo.BlockNumber) (retval0 string, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"symbol\", ethgo.EncodeBlock(block...))\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(string)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// TotalSupply calls the totalSupply method in the solidity contract\nfunc (e *ERC20) TotalSupply(block ...ethgo.BlockNumber) (retval0 *big.Int, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = e.c.Call(\"totalSupply\", ethgo.EncodeBlock(block...))\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(*big.Int)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// txns\n\n// Approve sends a approve transaction in the solidity contract\nfunc (e *ERC20) Approve(spender ethgo.Address, value *big.Int) (contract.Txn, error) {\n\treturn e.c.Txn(\"approve\", spender, value)\n}\n\n// Transfer sends a transfer transaction in the solidity contract\nfunc (e *ERC20) Transfer(to ethgo.Address, value *big.Int) (contract.Txn, error) {\n\treturn e.c.Txn(\"transfer\", to, value)\n}\n\n// TransferFrom sends a transferFrom transaction in the solidity contract\nfunc (e *ERC20) TransferFrom(from ethgo.Address, to ethgo.Address, value *big.Int) (contract.Txn, error) {\n\treturn e.c.Txn(\"transferFrom\", from, to, value)\n}\n\n// events\n\nfunc (e *ERC20) ApprovalEventSig() ethgo.Hash {\n\treturn e.c.GetABI().Events[\"Approval\"].ID()\n}\n\nfunc (e *ERC20) TransferEventSig() ethgo.Hash {\n\treturn e.c.GetABI().Events[\"Transfer\"].ID()\n}\n"
  },
  {
    "path": "builtin/erc20/erc20_artifacts.go",
    "content": "package erc20\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiERC20 *abi.ABI\n\n// ERC20Abi returns the abi of the ERC20 contract\nfunc ERC20Abi() *abi.ABI {\n\treturn abiERC20\n}\n\nvar binERC20 []byte\n\nfunc init() {\n\tvar err error\n\tabiERC20, err = abi.NewABI(abiERC20Str)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"cannot parse ERC20 abi: %v\", err))\n\t}\n\tif len(binERC20Str) != 0 {\n\t\tbinERC20, err = hex.DecodeString(binERC20Str[2:])\n\t\tif err != nil {\n\t\t\tpanic(fmt.Errorf(\"cannot parse ERC20 bin: %v\", err))\n\t\t}\n\t}\n}\n\nvar binERC20Str = \"\"\n\nvar abiERC20Str = `[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"}]`\n"
  },
  {
    "path": "builtin/erc20/erc20_test.go",
    "content": "package erc20\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nvar (\n\tzeroX = ethgo.HexToAddress(\"0xe41d2489571d322189246dafa5ebde1f4699f498\")\n)\n\nfunc TestERC20Decimals(t *testing.T) {\n\tc, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))\n\terc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))\n\n\tdecimals, err := erc20.Decimals()\n\tassert.NoError(t, err)\n\tif decimals != 18 {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n\nfunc TestERC20Name(t *testing.T) {\n\tc, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))\n\terc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))\n\n\tname, err := erc20.Name()\n\tassert.NoError(t, err)\n\tassert.Equal(t, name, \"0x Protocol Token\")\n}\n\nfunc TestERC20Symbol(t *testing.T) {\n\tc, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))\n\terc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))\n\n\tsymbol, err := erc20.Symbol()\n\tassert.NoError(t, err)\n\tassert.Equal(t, symbol, \"ZRX\")\n}\n\nfunc TestTotalSupply(t *testing.T) {\n\tc, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))\n\terc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))\n\n\tsupply, err := erc20.TotalSupply()\n\tassert.NoError(t, err)\n\tassert.Equal(t, supply.String(), \"1000000000000000000000000000\")\n}\n"
  },
  {
    "path": "cmd/abigen/abigen.go",
    "content": "package abigen\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"strings\"\n\n\t\"path/filepath\"\n\n\t\"github.com/umbracle/ethgo/compiler\"\n)\n\nfunc Parse(sources string, pckg string, output string) error {\n\tconfig := &config{\n\t\tPackage: pckg,\n\t\tOutput:  output,\n\t}\n\n\tif sources == \"\" {\n\t\treturn fmt.Errorf(\"no source\")\n\t}\n\n\tfor _, source := range strings.Split(sources, \",\") {\n\t\tmatches, err := filepath.Glob(source)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Failed to read files: %v\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tif len(matches) == 0 {\n\t\t\tfmt.Printf(\"No match for source: %s\\n\", source)\n\t\t\tcontinue\n\t\t}\n\t\tfor _, source := range matches {\n\t\t\tartifacts, err := process(source, config)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Printf(\"Failed to parse sources: %v\", err)\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\n\t\t\t// hash the source file\n\t\t\traw := sha256.Sum256([]byte(source))\n\t\t\thash := hex.EncodeToString(raw[:])\n\n\t\t\tif err := gen(artifacts, config, hash); err != nil {\n\t\t\t\tfmt.Printf(\"Failed to generate sources: %v\", err)\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nconst (\n\tsolExt  = 1\n\tabiExt  = 2\n\tjsonExt = 3\n)\n\nfunc process(sources string, config *config) (map[string]*compiler.Artifact, error) {\n\tfiles := strings.Split(sources, \",\")\n\tif len(files) == 0 {\n\t\treturn nil, fmt.Errorf(\"input not found\")\n\t}\n\n\tprev := -1\n\tfor _, f := range files {\n\t\tvar ext int\n\t\tswitch extt := filepath.Ext(f); extt {\n\t\tcase \".abi\":\n\t\t\text = abiExt\n\t\tcase \".sol\":\n\t\t\text = solExt\n\t\tcase \".json\":\n\t\t\text = jsonExt\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"file extension '%s' not found\", extt)\n\t\t}\n\n\t\tif prev == -1 {\n\t\t\tprev = ext\n\t\t} else if ext != prev {\n\t\t\treturn nil, fmt.Errorf(\"two file formats found\")\n\t\t}\n\t}\n\n\tswitch prev {\n\tcase abiExt:\n\t\treturn processAbi(files, config)\n\tcase solExt:\n\t\treturn processSolc(files)\n\tcase jsonExt:\n\t\treturn processJson(files)\n\t}\n\n\treturn nil, nil\n}\n\nfunc processSolc(sources []string) (map[string]*compiler.Artifact, error) {\n\tc := compiler.NewSolidityCompiler(\"solc\")\n\traw, err := c.Compile(sources...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tres := map[string]*compiler.Artifact{}\n\tfor rawName, entry := range raw.Contracts {\n\t\tname := strings.Split(rawName, \":\")[1]\n\t\tres[strings.Title(name)] = entry\n\t}\n\treturn res, nil\n}\n\nfunc processAbi(sources []string, config *config) (map[string]*compiler.Artifact, error) {\n\tartifacts := map[string]*compiler.Artifact{}\n\n\tfor _, abiPath := range sources {\n\t\tcontent, err := ioutil.ReadFile(abiPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read abi file (%s): %v\", abiPath, err)\n\t\t}\n\n\t\t// Use the name of the file to name the contract\n\t\tpath, name := filepath.Split(abiPath)\n\n\t\tname = strings.TrimSuffix(name, filepath.Ext(name))\n\t\tbinPath := filepath.Join(path, name+\".bin\")\n\n\t\tbin, err := ioutil.ReadFile(binPath)\n\t\tif err != nil {\n\t\t\t// bin not found\n\t\t\tbin = []byte{}\n\t\t}\n\t\tartifacts[strings.Title(name)] = &compiler.Artifact{\n\t\t\tAbi: string(content),\n\t\t\tBin: string(bin),\n\t\t}\n\t}\n\treturn artifacts, nil\n}\n\ntype JSONArtifact struct {\n\tBytecode string          `json:\"bytecode\"`\n\tAbi      json.RawMessage `json:\"abi\"`\n}\n\nfunc processJson(sources []string) (map[string]*compiler.Artifact, error) {\n\tartifacts := map[string]*compiler.Artifact{}\n\n\tfor _, jsonPath := range sources {\n\t\tcontent, err := ioutil.ReadFile(jsonPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read abi file (%s): %v\", jsonPath, err)\n\t\t}\n\n\t\t// Use the name of the file to name the contract\n\t\t_, name := filepath.Split(jsonPath)\n\t\tname = strings.TrimSuffix(name, \".json\")\n\n\t\tvar art *JSONArtifact\n\t\tif err := json.Unmarshal(content, &art); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tartifacts[strings.Title(name)] = &compiler.Artifact{\n\t\t\tAbi: string(art.Abi),\n\t\t\tBin: \"0x\" + art.Bytecode,\n\t\t}\n\t}\n\treturn artifacts, nil\n}\n"
  },
  {
    "path": "cmd/abigen/gen.go",
    "content": "package abigen\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/cmd/version\"\n\t\"github.com/umbracle/ethgo/compiler\"\n)\n\ntype config struct {\n\tPackage string\n\tOutput  string\n}\n\nfunc cleanName(str string) string {\n\treturn handleSnakeCase(strings.Trim(str, \"_\"))\n}\n\nfunc outputArg(str string) string {\n\treturn str\n}\n\nfunc handleSnakeCase(str string) string {\n\tif !strings.Contains(str, \"_\") {\n\t\treturn str\n\t}\n\n\tspl := strings.Split(str, \"_\")\n\tres := \"\"\n\tfor indx, elem := range spl {\n\t\tif indx != 0 {\n\t\t\telem = strings.Title(elem)\n\t\t}\n\t\tres += elem\n\t}\n\treturn res\n}\n\nfunc funcName(str string) string {\n\treturn strings.Title(handleSnakeCase(str))\n}\n\nfunc encodeSimpleArg(typ *abi.Type) string {\n\tswitch typ.Kind() {\n\tcase abi.KindAddress:\n\t\treturn \"ethgo.Address\"\n\n\tcase abi.KindString:\n\t\treturn \"string\"\n\n\tcase abi.KindBool:\n\t\treturn \"bool\"\n\n\tcase abi.KindInt:\n\t\treturn typ.GoType().String()\n\n\tcase abi.KindUInt:\n\t\treturn typ.GoType().String()\n\n\tcase abi.KindFixedBytes:\n\t\treturn fmt.Sprintf(\"[%d]byte\", typ.Size())\n\n\tcase abi.KindBytes:\n\t\treturn \"[]byte\"\n\n\tcase abi.KindSlice:\n\t\treturn \"[]\" + encodeSimpleArg(typ.Elem())\n\n\tdefault:\n\t\treturn fmt.Sprintf(\"input not done for type: %s\", typ.String())\n\t}\n}\n\nfunc encodeArg(str interface{}) string {\n\targ, ok := str.(*abi.TupleElem)\n\tif !ok {\n\t\tpanic(\"bad 1\")\n\t}\n\treturn encodeSimpleArg(arg.Elem)\n}\n\nfunc tupleLen(tuple interface{}) interface{} {\n\tif isNil(tuple) {\n\t\treturn 0\n\t}\n\targ, ok := tuple.(*abi.Type)\n\tif !ok {\n\t\tpanic(\"bad tuple\")\n\t}\n\treturn len(arg.TupleElems())\n}\n\nfunc tupleElems(tuple interface{}) []interface{} {\n\tres := []interface{}{}\n\tif isNil(tuple) {\n\t\treturn res\n\t}\n\n\targ, ok := tuple.(*abi.Type)\n\tif !ok {\n\t\tpanic(\"bad tuple\")\n\t}\n\tfor _, i := range arg.TupleElems() {\n\t\tres = append(res, i)\n\t}\n\treturn res\n}\n\nfunc isNil(c interface{}) bool {\n\treturn c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil())\n}\n\nfunc gen(artifacts map[string]*compiler.Artifact, config *config, hash string) error {\n\tfuncMap := template.FuncMap{\n\t\t\"title\":      strings.Title,\n\t\t\"clean\":      cleanName,\n\t\t\"arg\":        encodeArg,\n\t\t\"outputArg\":  outputArg,\n\t\t\"funcName\":   funcName,\n\t\t\"tupleElems\": tupleElems,\n\t\t\"tupleLen\":   tupleLen,\n\t}\n\ttmplAbi, err := template.New(\"eth-abi\").Funcs(funcMap).Parse(templateAbiStr)\n\tif err != nil {\n\t\treturn err\n\t}\n\ttmplBin, err := template.New(\"eth-abi\").Funcs(funcMap).Parse(templateBinStr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor name, artifact := range artifacts {\n\t\t// parse abi\n\t\tabi, err := abi.NewABI(artifact.Abi)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tinput := map[string]interface{}{\n\t\t\t\"Hash\":     hash,\n\t\t\t\"Version\":  version.Version,\n\t\t\t\"Ptr\":      strings.ToLower(string(name[0])),\n\t\t\t\"Config\":   config,\n\t\t\t\"Contract\": artifact,\n\t\t\t\"Abi\":      abi,\n\t\t\t\"Name\":     name,\n\t\t}\n\n\t\tfilename := strings.ToLower(name)\n\n\t\tvar b bytes.Buffer\n\t\tif err := tmplAbi.Execute(&b, input); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := ioutil.WriteFile(filepath.Join(config.Output, filename+\".go\"), []byte(b.Bytes()), 0644); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tb.Reset()\n\t\tif err := tmplBin.Execute(&b, input); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := ioutil.WriteFile(filepath.Join(config.Output, filename+\"_artifacts.go\"), []byte(b.Bytes()), 0644); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nvar templateAbiStr = `// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: {{.Hash}}\n// Version: {{.Version}}\npackage {{.Config.Package}}\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nvar (\n\t_ = big.NewInt\n\t_ = jsonrpc.NewClient\n)\n\n// {{.Name}} is a solidity contract\ntype {{.Name}} struct {\n\tc *contract.Contract\n}\n{{if .Contract.Bin}}\n// Deploy{{.Name}} deploys a new {{.Name}} contract\nfunc Deploy{{.Name}}(provider *jsonrpc.Client, from ethgo.Address, args []interface{}, opts ...contract.ContractOption) (contract.Txn, error) {\n\treturn contract.DeployContract(abi{{.Name}}, bin{{.Name}}, args, opts...)\n}\n{{end}}\n// New{{.Name}} creates a new instance of the contract at a specific address\nfunc New{{.Name}}(addr ethgo.Address, opts ...contract.ContractOption) *{{.Name}} {\n\treturn &{{.Name}}{c: contract.NewContract(addr, abi{{.Name}}, opts...)}\n}\n\n// calls\n{{range $key, $value := .Abi.Methods}}{{if .Const}}\n// {{funcName $key}} calls the {{$key}} method in the solidity contract\nfunc ({{$.Ptr}} *{{$.Name}}) {{funcName $key}}({{range $index, $val := tupleElems .Inputs}}{{if .Name}}{{clean .Name}}{{else}}val{{$index}}{{end}} {{arg .}}, {{end}}block ...ethgo.BlockNumber) ({{range $index, $val := tupleElems .Outputs}}retval{{$index}} {{arg .}}, {{end}}err error) {\n\tvar out map[string]interface{}\n\t{{ $length := tupleLen .Outputs }}{{ if ne $length 0 }}var ok bool{{ end }}\n\n\tout, err = {{$.Ptr}}.c.Call(\"{{$key}}\", ethgo.EncodeBlock(block...){{range $index, $val := tupleElems .Inputs}}, {{if .Name}}{{clean .Name}}{{else}}val{{$index}}{{end}}{{end}})\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\t{{range $index, $val := tupleElems .Outputs}}retval{{$index}}, ok = out[\"{{if .Name}}{{.Name}}{{else}}{{$index}}{{end}}\"].({{arg .}})\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index {{$index}}\")\n\t\treturn\n\t}\n\t{{end}}\n\treturn\n}\n{{end}}{{end}}\n// txns\n{{range $key, $value := .Abi.Methods}}{{if not .Const}}\n// {{funcName $key}} sends a {{$key}} transaction in the solidity contract\nfunc ({{$.Ptr}} *{{$.Name}}) {{funcName $key}}({{range $index, $input := tupleElems .Inputs}}{{if $index}}, {{end}}{{clean .Name}} {{arg .}}{{end}}) (contract.Txn, error) {\n\treturn {{$.Ptr}}.c.Txn(\"{{$key}}\"{{range $index, $elem := tupleElems .Inputs}}, {{clean $elem.Name}}{{end}})\n}\n{{end}}{{end}}\n// events\n{{range $key, $value := .Abi.Events}}\nfunc ({{$.Ptr}} *{{$.Name}}) {{funcName $key}}EventSig() ethgo.Hash {\n\treturn {{$.Ptr}}.c.GetABI().Events[\"{{funcName $key}}\"].ID()\n}\n{{end}}`\n\nvar templateBinStr = `package {{.Config.Package}}\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abi{{.Name}} *abi.ABI\n\n// {{.Name}}Abi returns the abi of the {{.Name}} contract\nfunc {{.Name}}Abi() *abi.ABI {\n\treturn abi{{.Name}}\n}\n\nvar bin{{.Name}} []byte\n{{if .Contract.Bin}}\n// {{.Name}}Bin returns the bin of the {{.Name}} contract\nfunc {{.Name}}Bin() []byte {\n\treturn bin{{.Name}}\n}\n{{end}}\nfunc init() {\n\tvar err error\n\tabi{{.Name}}, err = abi.NewABI(abi{{.Name}}Str)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"cannot parse {{.Name}} abi: %v\", err))\n\t}\n\tif len(bin{{.Name}}Str) != 0 {\n\t\tbin{{.Name}}, err = hex.DecodeString(bin{{.Name}}Str[2:])\n\t\tif err != nil {\n\t\t\tpanic(fmt.Errorf(\"cannot parse {{.Name}} bin: %v\", err))\n\t\t}\n\t}\n}\n\nvar bin{{.Name}}Str = \"{{.Contract.Bin}}\"\n\nvar abi{{.Name}}Str = ` + \"`\" + `{{.Contract.Abi}}` + \"`\\n\"\n"
  },
  {
    "path": "cmd/abigen/testdata/testdata.abi",
    "content": "[\n    {\n        \"constant\": false,\n        \"inputs\": [\n            {\n                \"name\": \"_val1\",\n                \"type\": \"address\"\n            },\n            {\n                \"name\": \"_val2\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"txnBasicInput\",\n        \"outputs\": [\n            {\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"payable\": false,\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"constant\": true,\n        \"inputs\": [],\n        \"name\": \"callBasicInput\",\n        \"outputs\": [\n            {\n                \"name\": \"\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"payable\": false,\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"anonymous\": false,\n        \"inputs\": [\n            {\n                \"indexed\": true,\n                \"name\": \"owner\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": true,\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": false,\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"eventBasic\",\n        \"type\": \"event\"\n    }\n]"
  },
  {
    "path": "cmd/abigen/testdata/testdata.go",
    "content": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: 3f1af52b391dcf1991b5cee7468a69f382cfa0f819eaff85474464c969fe7ea9\n// Version: 0.1.1\npackage testdata\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nvar (\n\t_ = big.NewInt\n\t_ = jsonrpc.NewClient\n)\n\n// Testdata is a solidity contract\ntype Testdata struct {\n\tc *contract.Contract\n}\n\n// NewTestdata creates a new instance of the contract at a specific address\nfunc NewTestdata(addr ethgo.Address, opts ...contract.ContractOption) *Testdata {\n\treturn &Testdata{c: contract.NewContract(addr, abiTestdata, opts...)}\n}\n\n// calls\n\n// CallBasicInput calls the callBasicInput method in the solidity contract\nfunc (t *Testdata) CallBasicInput(block ...ethgo.BlockNumber) (retval0 *big.Int, retval1 ethgo.Address, err error) {\n\tvar out map[string]interface{}\n\tvar ok bool\n\n\tout, err = t.c.Call(\"callBasicInput\", ethgo.EncodeBlock(block...))\n\tif err != nil {\n\t\treturn\n\t}\n\n\t// decode outputs\n\tretval0, ok = out[\"0\"].(*big.Int)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 0\")\n\t\treturn\n\t}\n\tretval1, ok = out[\"1\"].(ethgo.Address)\n\tif !ok {\n\t\terr = fmt.Errorf(\"failed to encode output at index 1\")\n\t\treturn\n\t}\n\t\n\treturn\n}\n\n// txns\n\n// TxnBasicInput sends a txnBasicInput transaction in the solidity contract\nfunc (t *Testdata) TxnBasicInput(val1 ethgo.Address, val2 *big.Int) (contract.Txn, error) {\n\treturn t.c.Txn(\"txnBasicInput\", val1, val2)\n}\n\n// events\n\nfunc (t *Testdata) EventBasicEventSig() ethgo.Hash {\n\treturn t.c.GetABI().Events[\"EventBasic\"].ID()\n}\n"
  },
  {
    "path": "cmd/abigen/testdata/testdata_artifacts.go",
    "content": "package testdata\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiTestdata *abi.ABI\n\n// TestdataAbi returns the abi of the Testdata contract\nfunc TestdataAbi() *abi.ABI {\n\treturn abiTestdata\n}\n\nvar binTestdata []byte\n\nfunc init() {\n\tvar err error\n\tabiTestdata, err = abi.NewABI(abiTestdataStr)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"cannot parse Testdata abi: %v\", err))\n\t}\n\tif len(binTestdataStr) != 0 {\n\t\tbinTestdata, err = hex.DecodeString(binTestdataStr[2:])\n\t\tif err != nil {\n\t\t\tpanic(fmt.Errorf(\"cannot parse Testdata bin: %v\", err))\n\t\t}\n\t}\n}\n\nvar binTestdataStr = \"\"\n\nvar abiTestdataStr = `[\n    {\n        \"constant\": false,\n        \"inputs\": [\n            {\n                \"name\": \"_val1\",\n                \"type\": \"address\"\n            },\n            {\n                \"name\": \"_val2\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"txnBasicInput\",\n        \"outputs\": [\n            {\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"payable\": false,\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"constant\": true,\n        \"inputs\": [],\n        \"name\": \"callBasicInput\",\n        \"outputs\": [\n            {\n                \"name\": \"\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"payable\": false,\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"anonymous\": false,\n        \"inputs\": [\n            {\n                \"indexed\": true,\n                \"name\": \"owner\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": true,\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": false,\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"eventBasic\",\n        \"type\": \"event\"\n    }\n]`\n"
  },
  {
    "path": "cmd/commands/4byte.go",
    "content": "package commands\n\nimport (\n\t\"github.com/mitchellh/cli\"\n\tfourbyte \"github.com/umbracle/ethgo/4byte\"\n)\n\n// FourByteCommand is the command to resolve 4byte actions\ntype FourByteCommand struct {\n\tUI cli.Ui\n}\n\n// Help implements the cli.Command interface\nfunc (c *FourByteCommand) Help() string {\n\treturn `Usage: ethgo 4byte [signature]\n\n  Resolve a 4byte signature`\n}\n\n// Synopsis implements the cli.Command interface\nfunc (c *FourByteCommand) Synopsis() string {\n\treturn \"Resolve a 4byte signature\"\n}\n\n// Run implements the cli.Command interface\nfunc (c *FourByteCommand) Run(args []string) int {\n\tif len(args) == 0 {\n\t\tc.UI.Output(\"No arguments provided\")\n\t\treturn 1\n\t}\n\n\tfound, err := fourbyte.Resolve(args[0])\n\tif err != nil {\n\t\tc.UI.Output(err.Error())\n\t\treturn 1\n\t}\n\tif found == \"\" {\n\t\tc.UI.Output(\"Resolve not found\")\n\t\treturn 1\n\t}\n\n\tc.UI.Output(found)\n\treturn 0\n}\n"
  },
  {
    "path": "cmd/commands/abigen.go",
    "content": "package commands\n\nimport (\n\tflag \"github.com/spf13/pflag\"\n\t\"github.com/umbracle/ethgo/cmd/abigen\"\n)\n\n// VersionCommand is the command to show the version of the agent\ntype AbigenCommand struct {\n\t*baseCommand\n\n\tsource string\n\tpckg   string\n\toutput string\n}\n\n// Help implements the cli.Command interface\nfunc (c *AbigenCommand) Help() string {\n\treturn `Usage: ethgo abigen\n\t\n  Compute the abigen.\n` + c.Flags().FlagUsages()\n}\n\n// Synopsis implements the cli.Command interface\nfunc (c *AbigenCommand) Synopsis() string {\n\treturn \"Compute the abigen\"\n}\n\nfunc (c *AbigenCommand) Flags() *flag.FlagSet {\n\tflags := c.baseCommand.Flags(\"abigen\")\n\n\tflags.StringVar(&c.source, \"source\", \"\", \"Source data\")\n\tflags.StringVar(&c.pckg, \"package\", \"main\", \"Name of the package\")\n\tflags.StringVar(&c.output, \"output\", \".\", \"Output directory\")\n\n\treturn flags\n}\n\n// Run implements the cli.Command interface\nfunc (c *AbigenCommand) Run(args []string) int {\n\tflags := c.Flags()\n\tif err := flags.Parse(args); err != nil {\n\t\tc.UI.Error(err.Error())\n\t\treturn 1\n\t}\n\n\tif err := abigen.Parse(c.source, c.pckg, c.output); err != nil {\n\t\tc.UI.Error(err.Error())\n\t\treturn 1\n\t}\n\treturn 0\n}\n"
  },
  {
    "path": "cmd/commands/commands.go",
    "content": "package commands\n\nimport (\n\t\"os\"\n\n\t\"github.com/mitchellh/cli\"\n\tflag \"github.com/spf13/pflag\"\n)\n\nfunc Commands() map[string]cli.CommandFactory {\n\tui := &cli.BasicUi{\n\t\tReader:      os.Stdin,\n\t\tWriter:      os.Stdout,\n\t\tErrorWriter: os.Stderr,\n\t}\n\n\tbaseCommand := &baseCommand{\n\t\tUI: ui,\n\t}\n\n\treturn map[string]cli.CommandFactory{\n\t\t\"abigen\": func() (cli.Command, error) {\n\t\t\treturn &AbigenCommand{\n\t\t\t\tbaseCommand: baseCommand,\n\t\t\t}, nil\n\t\t},\n\t\t\"4byte\": func() (cli.Command, error) {\n\t\t\treturn &FourByteCommand{\n\t\t\t\tUI: ui,\n\t\t\t}, nil\n\t\t},\n\t\t\"ens\": func() (cli.Command, error) {\n\t\t\treturn &EnsCommand{\n\t\t\t\tUI: ui,\n\t\t\t}, nil\n\t\t},\n\t\t\"ens resolve\": func() (cli.Command, error) {\n\t\t\treturn &EnsResolveCommand{\n\t\t\t\tUI: ui,\n\t\t\t}, nil\n\t\t},\n\t\t\"version\": func() (cli.Command, error) {\n\t\t\treturn &VersionCommand{\n\t\t\t\tUI: ui,\n\t\t\t}, nil\n\t\t},\n\t}\n}\n\ntype baseCommand struct {\n\tUI cli.Ui\n}\n\nfunc (b *baseCommand) Flags(name string) *flag.FlagSet {\n\tflags := flag.NewFlagSet(name, 0)\n\treturn flags\n}\n"
  },
  {
    "path": "cmd/commands/ens.go",
    "content": "package commands\n\nimport (\n\t\"github.com/mitchellh/cli\"\n)\n\n// EnsCommand is the group command for ens\ntype EnsCommand struct {\n\tUI cli.Ui\n}\n\n// Help implements the cli.Command interface\nfunc (c *EnsCommand) Help() string {\n\treturn `Usage: ethgo ens\n\n  Interact with ens`\n}\n\n// Synopsis implements the cli.Command interface\nfunc (c *EnsCommand) Synopsis() string {\n\treturn \"Interact with ens\"\n}\n\n// Run implements the cli.Command interface\nfunc (c *EnsCommand) Run(args []string) int {\n\treturn 0\n}\n"
  },
  {
    "path": "cmd/commands/ens_resolve.go",
    "content": "package commands\n\nimport (\n\t\"os\"\n\n\t\"github.com/mitchellh/cli\"\n\tflag \"github.com/spf13/pflag\"\n\t\"github.com/umbracle/ethgo/ens\"\n)\n\nfunc defaultJsonRPCProvider() string {\n\tif provider := os.Getenv(\"JSONRPC_PROVIDER\"); provider != \"\" {\n\t\treturn provider\n\t}\n\treturn \"http://localhost:8545\"\n}\n\n// EnsResolveCommand is the command to resolve an ens name\ntype EnsResolveCommand struct {\n\tUI cli.Ui\n\n\tprovider string\n}\n\n// Help implements the cli.Command interface\nfunc (c *EnsResolveCommand) Help() string {\n\treturn `Usage: ethgo ens resolve <name>\n\n  Resolve an ens name\n` + c.Flags().FlagUsages()\n}\n\n// Synopsis implements the cli.Command interface\nfunc (c *EnsResolveCommand) Synopsis() string {\n\treturn \"Resolve an ens name\"\n}\n\nfunc (c *EnsResolveCommand) Flags() *flag.FlagSet {\n\tflags := flag.NewFlagSet(\"ens resolve\", flag.PanicOnError)\n\tflags.StringVar(&c.provider, \"provider\", defaultJsonRPCProvider(), \"\")\n\n\treturn flags\n}\n\n// Run implements the cli.Command interface\nfunc (c *EnsResolveCommand) Run(args []string) int {\n\tflags := c.Flags()\n\tif err := flags.Parse(args); err != nil {\n\t\tc.UI.Error(err.Error())\n\t\treturn 1\n\t}\n\n\targs = flags.Args()\n\tif len(args) != 1 {\n\t\tc.UI.Error(\"one argument <name> expected\")\n\t\treturn 1\n\t}\n\n\te, err := ens.NewENS(ens.WithAddress(c.provider))\n\tif err != nil {\n\t\tc.UI.Error(err.Error())\n\t\treturn 1\n\t}\n\n\taddr, err := e.Resolve(args[0])\n\tif err != nil {\n\t\tc.UI.Error(err.Error())\n\t\treturn 1\n\t}\n\n\tc.UI.Output(addr.String())\n\treturn 0\n}\n"
  },
  {
    "path": "cmd/commands/version.go",
    "content": "package commands\n\nimport (\n\t\"github.com/mitchellh/cli\"\n\t\"github.com/umbracle/ethgo/cmd/version\"\n)\n\n// VersionCommand is the command to show the version of the agent\ntype VersionCommand struct {\n\tUI cli.Ui\n}\n\n// Help implements the cli.Command interface\nfunc (c *VersionCommand) Help() string {\n\treturn `Usage: ethgo version\n\n  Display the Ethgo version`\n}\n\n// Synopsis implements the cli.Command interface\nfunc (c *VersionCommand) Synopsis() string {\n\treturn \"Display the Ethgo version\"\n}\n\n// Run implements the cli.Command interface\nfunc (c *VersionCommand) Run(args []string) int {\n\tc.UI.Output(version.GetVersion())\n\treturn 0\n}\n"
  },
  {
    "path": "cmd/go.mod",
    "content": "module github.com/umbracle/ethgo/cmd\n\ngo 1.17\n\nrequire (\n\tgithub.com/mitchellh/cli v1.1.2\n\tgithub.com/umbracle/ethgo v0.0.0-20220303093617-1621d9ff042b\n)\n\nrequire github.com/spf13/pflag v1.0.5\n\nrequire (\n\tgithub.com/Masterminds/goutils v1.1.0 // indirect\n\tgithub.com/Masterminds/semver v1.5.0 // indirect\n\tgithub.com/Masterminds/sprig v2.22.0+incompatible // indirect\n\tgithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect\n\tgithub.com/bgentry/speakeasy v0.1.0 // indirect\n\tgithub.com/btcsuite/btcd v0.22.1 // indirect\n\tgithub.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect\n\tgithub.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect\n\tgithub.com/fatih/color v1.7.0 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/google/uuid v1.1.2 // indirect\n\tgithub.com/gorilla/websocket v1.4.1 // indirect\n\tgithub.com/hashicorp/errwrap v1.0.0 // indirect\n\tgithub.com/hashicorp/go-multierror v1.0.0 // indirect\n\tgithub.com/huandu/xstrings v1.3.2 // indirect\n\tgithub.com/imdario/mergo v0.3.11 // indirect\n\tgithub.com/klauspost/compress v1.4.1 // indirect\n\tgithub.com/klauspost/cpuid v1.2.0 // indirect\n\tgithub.com/mattn/go-colorable v0.0.9 // indirect\n\tgithub.com/mattn/go-isatty v0.0.3 // indirect\n\tgithub.com/mitchellh/copystructure v1.0.0 // indirect\n\tgithub.com/mitchellh/mapstructure v1.1.2 // indirect\n\tgithub.com/mitchellh/reflectwalk v1.0.0 // indirect\n\tgithub.com/posener/complete v1.1.1 // indirect\n\tgithub.com/tyler-smith/go-bip39 v1.1.0 // indirect\n\tgithub.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect\n\tgithub.com/valyala/bytebufferpool v1.0.0 // indirect\n\tgithub.com/valyala/fasthttp v1.4.0 // indirect\n\tgithub.com/valyala/fastjson v1.4.1 // indirect\n\tgolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect\n\tgolang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect\n\tgolang.org/x/text v0.3.2 // indirect\n)\n\nreplace github.com/umbracle/ethgo => ../\n"
  },
  {
    "path": "cmd/go.sum",
    "content": "bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=\ngithub.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=\ngithub.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=\ngithub.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=\ngithub.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=\ngithub.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=\ngithub.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=\ngithub.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=\ngithub.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=\ngithub.com/Microsoft/go-winio v0.4.13 h1:Hmi80lzZuI/CaYmlJp/b+FjZdRZhKu9c2mDVqKlLWVs=\ngithub.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=\ngithub.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=\ngithub.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=\ngithub.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=\ngithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=\ngithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=\ngithub.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=\ngithub.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=\ngithub.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=\ngithub.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=\ngithub.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=\ngithub.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=\ngithub.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=\ngithub.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=\ngithub.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=\ngithub.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ=\ngithub.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o=\ngithub.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=\ngithub.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=\ngithub.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=\ngithub.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=\ngithub.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=\ngithub.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=\ngithub.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=\ngithub.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=\ngithub.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=\ngithub.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b h1:pik3LX++5O3UiNWv45wfP/WT81l7ukBJzd3uUiifbSU=\ngithub.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=\ngithub.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=\ngithub.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=\ngithub.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=\ngithub.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=\ngithub.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=\ngithub.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=\ngithub.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=\ngithub.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=\ngithub.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=\ngithub.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=\ngithub.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=\ngithub.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=\ngithub.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=\ngithub.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=\ngithub.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=\ngithub.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=\ngithub.com/klauspost/compress v1.4.1 h1:8VMb5+0wMgdBykOV96DwNwKFQ+WTI4pzYURP99CcB9E=\ngithub.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=\ngithub.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=\ngithub.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=\ngithub.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=\ngithub.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=\ngithub.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=\ngithub.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=\ngithub.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=\ngithub.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=\ngithub.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=\ngithub.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=\ngithub.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=\ngithub.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=\ngithub.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=\ngithub.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=\ngithub.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=\ngithub.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=\ngithub.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=\ngithub.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=\ngithub.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=\ngithub.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=\ngithub.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=\ngithub.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=\ngithub.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=\ngithub.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=\ngithub.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=\ngithub.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=\ngithub.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=\ngithub.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E=\ngithub.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=\ngithub.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=\ngithub.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=\ngithub.com/valyala/fasthttp v1.4.0 h1:PuaTGZIw3mjYhhhbVbCQp8aciRZN9YdoB7MGX9Ko76A=\ngithub.com/valyala/fasthttp v1.4.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=\ngithub.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE=\ngithub.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o=\ngithub.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=\ngolang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=\ngolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=\ngolang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=\ngolang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngoogle.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=\ngopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=\n"
  },
  {
    "path": "cmd/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/mitchellh/cli\"\n\t\"github.com/umbracle/ethgo/cmd/commands\"\n)\n\nfunc main() {\n\tos.Exit(Run(os.Args[1:]))\n}\n\n// Run starts the cli\nfunc Run(args []string) int {\n\tcommands := commands.Commands()\n\n\tcli := &cli.CLI{\n\t\tName:     \"ethgo\",\n\t\tArgs:     args,\n\t\tCommands: commands,\n\t}\n\n\texitCode, err := cli.Run()\n\tif err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"Error executing CLI: %s\\n\", err.Error())\n\t\treturn 1\n\t}\n\n\treturn exitCode\n}\n"
  },
  {
    "path": "cmd/version/version.go",
    "content": "package version\n\nimport \"fmt\"\n\nvar (\n\t// GitCommit is the git commit that was compiled.\n\tGitCommit string\n\n\t// Version is the main version at the moment.\n\tVersion = \"0.1.3\"\n\n\t// VersionPrerelease is a marker for the version.\n\tVersionPrerelease = \"\"\n)\n\n// GetVersion returns a string representation of the version\nfunc GetVersion() string {\n\tversion := Version\n\n\trelease := VersionPrerelease\n\tif release != \"\" {\n\t\tversion += fmt.Sprintf(\"-%s\", release)\n\n\t\tif GitCommit != \"\" {\n\t\t\tversion += fmt.Sprintf(\" (%s)\", GitCommit)\n\t\t}\n\t}\n\n\treturn version\n}\n"
  },
  {
    "path": "compiler/fixtures/ballot.sol",
    "content": "pragma solidity >=0.4.22 <0.6.0;\n\n/// @title Voting with delegation.\ncontract Ballot {\n    // This declares a new complex type which will\n    // be used for variables later.\n    // It will represent a single voter.\n    struct Voter {\n        uint weight; // weight is accumulated by delegation\n        bool voted;  // if true, that person already voted\n        address delegate; // person delegated to\n        uint vote;   // index of the voted proposal\n    }\n\n    // This is a type for a single proposal.\n    struct Proposal {\n        bytes32 name;   // short name (up to 32 bytes)\n        uint voteCount; // number of accumulated votes\n    }\n\n    address public chairperson;\n\n    // This declares a state variable that\n    // stores a `Voter` struct for each possible address.\n    mapping(address => Voter) public voters;\n\n    // A dynamically-sized array of `Proposal` structs.\n    Proposal[] public proposals;\n\n    /// Create a new ballot to choose one of `proposalNames`.\n    constructor(bytes32[] memory proposalNames) public {\n        chairperson = msg.sender;\n        voters[chairperson].weight = 1;\n\n        // For each of the provided proposal names,\n        // create a new proposal object and add it\n        // to the end of the array.\n        for (uint i = 0; i < proposalNames.length; i++) {\n            // `Proposal({...})` creates a temporary\n            // Proposal object and `proposals.push(...)`\n            // appends it to the end of `proposals`.\n            proposals.push(Proposal({\n                name: proposalNames[i],\n                voteCount: 0\n            }));\n        }\n    }\n\n    // Give `voter` the right to vote on this ballot.\n    // May only be called by `chairperson`.\n    function giveRightToVote(address voter) public {\n        // If the first argument of `require` evaluates\n        // to `false`, execution terminates and all\n        // changes to the state and to Ether balances\n        // are reverted.\n        // This used to consume all gas in old EVM versions, but\n        // not anymore.\n        // It is often a good idea to use `require` to check if\n        // functions are called correctly.\n        // As a second argument, you can also provide an\n        // explanation about what went wrong.\n        require(\n            msg.sender == chairperson,\n            \"Only chairperson can give right to vote.\"\n        );\n        require(\n            !voters[voter].voted,\n            \"The voter already voted.\"\n        );\n        require(voters[voter].weight == 0);\n        voters[voter].weight = 1;\n    }\n\n    /// Delegate your vote to the voter `to`.\n    function delegate(address to) public {\n        // assigns reference\n        Voter storage sender = voters[msg.sender];\n        require(!sender.voted, \"You already voted.\");\n\n        require(to != msg.sender, \"Self-delegation is disallowed.\");\n\n        // Forward the delegation as long as\n        // `to` also delegated.\n        // In general, such loops are very dangerous,\n        // because if they run too long, they might\n        // need more gas than is available in a block.\n        // In this case, the delegation will not be executed,\n        // but in other situations, such loops might\n        // cause a contract to get \"stuck\" completely.\n        while (voters[to].delegate != address(0)) {\n            to = voters[to].delegate;\n\n            // We found a loop in the delegation, not allowed.\n            require(to != msg.sender, \"Found loop in delegation.\");\n        }\n\n        // Since `sender` is a reference, this\n        // modifies `voters[msg.sender].voted`\n        sender.voted = true;\n        sender.delegate = to;\n        Voter storage delegate_ = voters[to];\n        if (delegate_.voted) {\n            // If the delegate already voted,\n            // directly add to the number of votes\n            proposals[delegate_.vote].voteCount += sender.weight;\n        } else {\n            // If the delegate did not vote yet,\n            // add to her weight.\n            delegate_.weight += sender.weight;\n        }\n    }\n\n    /// Give your vote (including votes delegated to you)\n    /// to proposal `proposals[proposal].name`.\n    function vote(uint proposal) public {\n        Voter storage sender = voters[msg.sender];\n        require(sender.weight != 0, \"Has no right to vote\");\n        require(!sender.voted, \"Already voted.\");\n        sender.voted = true;\n        sender.vote = proposal;\n\n        // If `proposal` is out of the range of the array,\n        // this will throw automatically and revert all\n        // changes.\n        proposals[proposal].voteCount += sender.weight;\n    }\n\n    /// @dev Computes the winning proposal taking all\n    /// previous votes into account.\n    function winningProposal() public view\n            returns (uint winningProposal_)\n    {\n        uint winningVoteCount = 0;\n        for (uint p = 0; p < proposals.length; p++) {\n            if (proposals[p].voteCount > winningVoteCount) {\n                winningVoteCount = proposals[p].voteCount;\n                winningProposal_ = p;\n            }\n        }\n    }\n\n    // Calls winningProposal() function to get the index\n    // of the winner contained in the proposals array and then\n    // returns the name of the winner\n    function winnerName() public view\n            returns (bytes32 winnerName_)\n    {\n        winnerName_ = proposals[winningProposal()].name;\n    }\n}"
  },
  {
    "path": "compiler/fixtures/simple_auction.sol",
    "content": "pragma solidity >=0.4.22 <0.6.0;\n\ncontract SimpleAuction {\n    // Parameters of the auction. Times are either\n    // absolute unix timestamps (seconds since 1970-01-01)\n    // or time periods in seconds.\n    address payable public beneficiary;\n    uint public auctionEndTime;\n\n    // Current state of the auction.\n    address public highestBidder;\n    uint public highestBid;\n\n    // Allowed withdrawals of previous bids\n    mapping(address => uint) pendingReturns;\n\n    // Set to true at the end, disallows any change.\n    // By default initialized to `false`.\n    bool ended;\n\n    // Events that will be emitted on changes.\n    event HighestBidIncreased(address bidder, uint amount);\n    event AuctionEnded(address winner, uint amount);\n\n    // The following is a so-called natspec comment,\n    // recognizable by the three slashes.\n    // It will be shown when the user is asked to\n    // confirm a transaction.\n\n    /// Create a simple auction with `_biddingTime`\n    /// seconds bidding time on behalf of the\n    /// beneficiary address `_beneficiary`.\n    constructor(\n        uint _biddingTime,\n        address payable _beneficiary\n    ) public {\n        beneficiary = _beneficiary;\n        auctionEndTime = now + _biddingTime;\n    }\n\n    /// Bid on the auction with the value sent\n    /// together with this transaction.\n    /// The value will only be refunded if the\n    /// auction is not won.\n    function bid() public payable {\n        // No arguments are necessary, all\n        // information is already part of\n        // the transaction. The keyword payable\n        // is required for the function to\n        // be able to receive Ether.\n\n        // Revert the call if the bidding\n        // period is over.\n        require(\n            now <= auctionEndTime,\n            \"Auction already ended.\"\n        );\n\n        // If the bid is not higher, send the\n        // money back.\n        require(\n            msg.value > highestBid,\n            \"There already is a higher bid.\"\n        );\n\n        if (highestBid != 0) {\n            // Sending back the money by simply using\n            // highestBidder.send(highestBid) is a security risk\n            // because it could execute an untrusted contract.\n            // It is always safer to let the recipients\n            // withdraw their money themselves.\n            pendingReturns[highestBidder] += highestBid;\n        }\n        highestBidder = msg.sender;\n        highestBid = msg.value;\n        emit HighestBidIncreased(msg.sender, msg.value);\n    }\n\n    /// Withdraw a bid that was overbid.\n    function withdraw() public returns (bool) {\n        uint amount = pendingReturns[msg.sender];\n        if (amount > 0) {\n            // It is important to set this to zero because the recipient\n            // can call this function again as part of the receiving call\n            // before `send` returns.\n            pendingReturns[msg.sender] = 0;\n\n            if (!msg.sender.send(amount)) {\n                // No need to call throw here, just reset the amount owing\n                pendingReturns[msg.sender] = amount;\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /// End the auction and send the highest bid\n    /// to the beneficiary.\n    function auctionEnd() public {\n        // It is a good guideline to structure functions that interact\n        // with other contracts (i.e. they call functions or send Ether)\n        // into three phases:\n        // 1. checking conditions\n        // 2. performing actions (potentially changing conditions)\n        // 3. interacting with other contracts\n        // If these phases are mixed up, the other contract could call\n        // back into the current contract and modify the state or cause\n        // effects (ether payout) to be performed multiple times.\n        // If functions called internally include interaction with external\n        // contracts, they also have to be considered interaction with\n        // external contracts.\n\n        // 1. Conditions\n        require(now >= auctionEndTime, \"Auction not yet ended.\");\n        require(!ended, \"auctionEnd has already been called.\");\n\n        // 2. Effects\n        ended = true;\n        emit AuctionEnded(highestBidder, highestBid);\n\n        // 3. Interaction\n        beneficiary.transfer(highestBid);\n    }\n}"
  },
  {
    "path": "compiler/solidity.go",
    "content": "package compiler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\ntype Output struct {\n\tContracts map[string]*Artifact\n\tSources   map[string]*Source\n\tVersion   string\n}\n\ntype Source struct {\n\tAST map[string]interface{}\n}\n\ntype Artifact struct {\n\tAbi           string\n\tBin           string\n\tBinRuntime    string `json:\"bin-runtime\"`\n\tSrcMap        string `json:\"srcmap\"`\n\tSrcMapRuntime string `json:\"srcmap-runtime\"`\n}\n\n// Solidity is the solidity compiler\ntype Solidity struct {\n\tpath string\n}\n\n// NewSolidityCompiler instantiates a new solidity compiler\nfunc NewSolidityCompiler(path string) *Solidity {\n\treturn &Solidity{path}\n}\n\n// CompileCode compiles a solidity code\nfunc (s *Solidity) CompileCode(code string) (*Output, error) {\n\tif code == \"\" {\n\t\treturn nil, fmt.Errorf(\"code is empty\")\n\t}\n\toutput, err := s.compileImpl(code)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn output, nil\n}\n\n// Compile implements the compiler interface\nfunc (s *Solidity) Compile(files ...string) (*Output, error) {\n\tif len(files) == 0 {\n\t\treturn nil, fmt.Errorf(\"no input files\")\n\t}\n\treturn s.compileImpl(\"\", files...)\n}\n\nfunc (s *Solidity) compileImpl(code string, files ...string) (*Output, error) {\n\targs := []string{\n\t\t\"--combined-json\",\n\t\t\"bin,bin-runtime,srcmap-runtime,abi,srcmap,ast\",\n\t}\n\tif code != \"\" {\n\t\targs = append(args, \"-\")\n\t}\n\tif len(files) != 0 {\n\t\targs = append(args, files...)\n\t}\n\n\tvar stdout, stderr bytes.Buffer\n\tcmd := exec.Command(s.path, args...)\n\tif code != \"\" {\n\t\tcmd.Stdin = strings.NewReader(code)\n\t}\n\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr\n\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to compile: %s\", string(stderr.Bytes()))\n\t}\n\n\tvar output *Output\n\tif err := json.Unmarshal(stdout.Bytes(), &output); err != nil {\n\t\treturn nil, err\n\t}\n\treturn output, nil\n}\n\n// DownloadSolidity downloads the solidity compiler\nfunc DownloadSolidity(version string, dst string, renameDst bool) error {\n\turl := \"https://github.com/ethereum/solidity/releases/download/v\" + version + \"/solc-static-linux\"\n\n\t// check if the dst is correct\n\texists := false\n\tfi, err := os.Stat(dst)\n\tif err == nil {\n\t\tswitch mode := fi.Mode(); {\n\t\tcase mode.IsDir():\n\t\t\texists = true\n\t\tcase mode.IsRegular():\n\t\t\treturn fmt.Errorf(\"dst is a file\")\n\t\t}\n\t} else {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"failed to stat dst '%s': %v\", dst, err)\n\t\t}\n\t}\n\n\t// create the destiny path if does not exists\n\tif !exists {\n\t\tif err := os.MkdirAll(dst, 0755); err != nil {\n\t\t\treturn fmt.Errorf(\"cannot create dst path: %v\", err)\n\t\t}\n\t}\n\n\t// rename binary\n\tname := \"solidity\"\n\tif renameDst {\n\t\tname += \"-\" + version\n\t}\n\n\t// tmp folder to download the binary\n\ttmpDir, err := ioutil.TempDir(\"/tmp\", \"solc-\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer os.RemoveAll(tmpDir)\n\n\tpath := filepath.Join(tmpDir, name)\n\n\t// Get the data\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\t// Create the file\n\tout, err := os.Create(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer out.Close()\n\n\t// Write the body to file\n\t_, err = io.Copy(out, resp.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// make binary executable\n\tif err := os.Chmod(path, 0755); err != nil {\n\t\treturn err\n\t}\n\n\t// move file to dst\n\tif err := os.Rename(path, filepath.Join(dst, name)); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "compiler/solidity_test.go",
    "content": "package compiler\n\nimport (\n\t\"bytes\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nvar (\n\tsolcDir  = \"/tmp/ethgo-solc\"\n\tsolcPath = solcDir + \"/solidity\"\n)\n\nfunc init() {\n\t_, err := os.Stat(solcDir)\n\tif err == nil {\n\t\t// already exists\n\t\treturn\n\t}\n\tif !os.IsNotExist(err) {\n\t\tpanic(err)\n\t}\n\t// solc folder does not exists\n\tif err := DownloadSolidity(\"0.5.5\", solcDir, false); err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc TestSolidityInline(t *testing.T) {\n\tsolc := NewSolidityCompiler(solcPath)\n\n\tcases := []struct {\n\t\tcode      string\n\t\tcontracts []string\n\t}{\n\t\t{\n\t\t\t`\n\t\tpragma solidity >0.0.0;\n\t\tcontract foo{}\n\t\t\t`,\n\t\t\t[]string{\n\t\t\t\t\"foo\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t`\n\t\tpragma solidity >0.0.0;\n\t\tcontract foo{}\n\t\tcontract bar{}\n\t\t\t`,\n\t\t\t[]string{\n\t\t\t\t\"bar\",\n\t\t\t\t\"foo\",\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\toutput, err := solc.CompileCode(c.code)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tresult := map[string]struct{}{}\n\t\t\tfor i := range output.Contracts {\n\t\t\t\tresult[strings.TrimPrefix(i, \"<stdin>:\")] = struct{}{}\n\t\t\t}\n\n\t\t\t// only one source file\n\t\t\tassert.Len(t, output.Sources, 1)\n\n\t\t\texpected := map[string]struct{}{}\n\t\t\tfor _, i := range c.contracts {\n\t\t\t\texpected[i] = struct{}{}\n\t\t\t}\n\n\t\t\tif !reflect.DeepEqual(result, expected) {\n\t\t\t\tt.Fatal(\"bad\")\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSolidity(t *testing.T) {\n\tsolc := NewSolidityCompiler(solcPath)\n\n\tfiles := []string{\n\t\t\"./fixtures/ballot.sol\",\n\t\t\"./fixtures/simple_auction.sol\",\n\t}\n\toutput, err := solc.Compile(files...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(output.Contracts) != 2 {\n\t\tt.Fatal(\"two expected\")\n\t}\n}\n\nfunc existsSolidity(t *testing.T, path string) bool {\n\t_, err := os.Stat(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn false\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\n\tcmd := exec.Command(path, \"--version\")\n\tvar stderr, stdout bytes.Buffer\n\tcmd.Stderr = &stderr\n\tcmd.Stdout = &stdout\n\tif err := cmd.Run(); err != nil {\n\t\tt.Fatalf(\"solidity version failed: %s\", string(stderr.Bytes()))\n\t}\n\tif len(stdout.Bytes()) == 0 {\n\t\tt.Fatal(\"empty output\")\n\t}\n\treturn true\n}\n\nfunc TestDownloadSolidityCompiler(t *testing.T) {\n\tdst1, err := ioutil.TempDir(\"/tmp\", \"ethgo-\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(dst1)\n\n\tif err := DownloadSolidity(\"0.5.5\", dst1, true); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif existsSolidity(t, filepath.Join(dst1, \"solidity\")) {\n\t\tt.Fatal(\"it should not exist\")\n\t}\n\tif !existsSolidity(t, filepath.Join(dst1, \"solidity-0.5.5\")) {\n\t\tt.Fatal(\"it should exist\")\n\t}\n\n\tdst2, err := ioutil.TempDir(\"/tmp\", \"ethgo-\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer os.RemoveAll(dst2)\n\n\tif err := DownloadSolidity(\"0.5.5\", dst2, false); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !existsSolidity(t, filepath.Join(dst2, \"solidity\")) {\n\t\tt.Fatal(\"it should exist\")\n\t}\n\tif existsSolidity(t, filepath.Join(dst2, \"solidity-0.5.5\")) {\n\t\tt.Fatal(\"it should not exist\")\n\t}\n}\n"
  },
  {
    "path": "contract/contract.go",
    "content": "package contract\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/wallet\"\n)\n\n// Provider handles the interactions with the Ethereum 1x node\ntype Provider interface {\n\tCall(ethgo.Address, []byte, *CallOpts) ([]byte, error)\n\tTxn(ethgo.Address, ethgo.Key, []byte) (Txn, error)\n}\n\ntype jsonRPCNodeProvider struct {\n\tclient  *jsonrpc.Eth\n\teip1559 bool\n}\n\nfunc (j *jsonRPCNodeProvider) Call(addr ethgo.Address, input []byte, opts *CallOpts) ([]byte, error) {\n\tmsg := &ethgo.CallMsg{\n\t\tTo:   &addr,\n\t\tData: input,\n\t}\n\tif opts.From != ethgo.ZeroAddress {\n\t\tmsg.From = opts.From\n\t}\n\trawStr, err := j.client.Call(msg, opts.Block)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\traw, err := hex.DecodeString(rawStr[2:])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn raw, nil\n}\n\nfunc (j *jsonRPCNodeProvider) Txn(addr ethgo.Address, key ethgo.Key, input []byte) (Txn, error) {\n\ttxn := &jsonrpcTransaction{\n\t\topts:    &TxnOpts{},\n\t\tinput:   input,\n\t\tclient:  j.client,\n\t\tkey:     key,\n\t\tto:      addr,\n\t\teip1559: j.eip1559,\n\t}\n\treturn txn, nil\n}\n\ntype jsonrpcTransaction struct {\n\tto      ethgo.Address\n\tinput   []byte\n\thash    ethgo.Hash\n\topts    *TxnOpts\n\tkey     ethgo.Key\n\tclient  *jsonrpc.Eth\n\ttxn     *ethgo.Transaction\n\ttxnRaw  []byte\n\teip1559 bool\n}\n\nfunc (j *jsonrpcTransaction) Hash() ethgo.Hash {\n\treturn j.hash\n}\n\nfunc (j *jsonrpcTransaction) WithOpts(opts *TxnOpts) {\n\tj.opts = opts\n}\n\nfunc (j *jsonrpcTransaction) Build() error {\n\tvar err error\n\tfrom := j.key.Address()\n\n\t// estimate gas price\n\tif j.opts.GasPrice == 0 && !j.eip1559 {\n\t\tj.opts.GasPrice, err = j.client.GasPrice()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// estimate gas limit\n\tif j.opts.GasLimit == 0 {\n\t\tmsg := &ethgo.CallMsg{\n\t\t\tFrom:     from,\n\t\t\tTo:       nil,\n\t\t\tData:     j.input,\n\t\t\tValue:    j.opts.Value,\n\t\t\tGasPrice: j.opts.GasPrice,\n\t\t}\n\t\tif j.to != ethgo.ZeroAddress {\n\t\t\tmsg.To = &j.to\n\t\t}\n\t\tj.opts.GasLimit, err = j.client.EstimateGas(msg)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// calculate the nonce\n\tif j.opts.Nonce == 0 {\n\t\tj.opts.Nonce, err = j.client.GetNonce(from, ethgo.Latest)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to calculate nonce: %v\", err)\n\t\t}\n\t}\n\n\tchainID, err := j.client.ChainID()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// send transaction\n\trawTxn := &ethgo.Transaction{\n\t\tFrom:     from,\n\t\tInput:    j.input,\n\t\tGasPrice: j.opts.GasPrice,\n\t\tGas:      j.opts.GasLimit,\n\t\tValue:    j.opts.Value,\n\t\tNonce:    j.opts.Nonce,\n\t\tChainID:  chainID,\n\t}\n\tif j.to != ethgo.ZeroAddress {\n\t\trawTxn.To = &j.to\n\t}\n\n\tif j.eip1559 {\n\t\trawTxn.Type = ethgo.TransactionDynamicFee\n\n\t\t// use gas price as fee data\n\t\tgasPrice, err := j.client.GasPrice()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trawTxn.MaxFeePerGas = new(big.Int).SetUint64(gasPrice)\n\t\trawTxn.MaxPriorityFeePerGas = new(big.Int).SetUint64(gasPrice)\n\t}\n\n\tj.txn = rawTxn\n\treturn nil\n}\n\nfunc (j *jsonrpcTransaction) Do() error {\n\tif j.txn == nil {\n\t\tif err := j.Build(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tsigner := wallet.NewEIP155Signer(j.txn.ChainID.Uint64())\n\tsignedTxn, err := signer.SignTx(j.txn, j.key)\n\tif err != nil {\n\t\treturn err\n\t}\n\ttxnRaw, err := signedTxn.MarshalRLPTo(nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tj.txnRaw = txnRaw\n\thash, err := j.client.SendRawTransaction(j.txnRaw)\n\tif err != nil {\n\t\treturn err\n\t}\n\tj.hash = hash\n\treturn nil\n}\n\nfunc (j *jsonrpcTransaction) Wait() (*ethgo.Receipt, error) {\n\tif (j.hash == ethgo.Hash{}) {\n\t\tpanic(\"transaction not executed\")\n\t}\n\n\tfor {\n\t\treceipt, err := j.client.GetTransactionReceipt(j.hash)\n\t\tif err != nil {\n\t\t\tif err.Error() != \"not found\" {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\tif receipt != nil {\n\t\t\treturn receipt, nil\n\t\t}\n\t}\n}\n\n// Txn is the transaction object returned\ntype Txn interface {\n\tHash() ethgo.Hash\n\tWithOpts(opts *TxnOpts)\n\tDo() error\n\tWait() (*ethgo.Receipt, error)\n}\n\ntype Opts struct {\n\tJsonRPCEndpoint string\n\tJsonRPCClient   *jsonrpc.Eth\n\tProvider        Provider\n\tSender          ethgo.Key\n\tEIP1559         bool\n}\n\ntype ContractOption func(*Opts)\n\nfunc WithJsonRPCEndpoint(endpoint string) ContractOption {\n\treturn func(o *Opts) {\n\t\to.JsonRPCEndpoint = endpoint\n\t}\n}\n\nfunc WithJsonRPC(client *jsonrpc.Eth) ContractOption {\n\treturn func(o *Opts) {\n\t\to.JsonRPCClient = client\n\t}\n}\n\nfunc WithProvider(provider Provider) ContractOption {\n\treturn func(o *Opts) {\n\t\to.Provider = provider\n\t}\n}\n\nfunc WithSender(sender ethgo.Key) ContractOption {\n\treturn func(o *Opts) {\n\t\to.Sender = sender\n\t}\n}\n\nfunc WithEIP1559() ContractOption {\n\treturn func(o *Opts) {\n\t\to.EIP1559 = true\n\t}\n}\n\nfunc DeployContract(abi *abi.ABI, bin []byte, args []interface{}, opts ...ContractOption) (Txn, error) {\n\ta := NewContract(ethgo.Address{}, abi, opts...)\n\ta.bin = bin\n\treturn a.Txn(\"constructor\", args...)\n}\n\nfunc NewContract(addr ethgo.Address, abi *abi.ABI, opts ...ContractOption) *Contract {\n\topt := &Opts{\n\t\tJsonRPCEndpoint: \"http://localhost:8545\",\n\t}\n\tfor _, c := range opts {\n\t\tc(opt)\n\t}\n\n\tvar provider Provider\n\tif opt.Provider != nil {\n\t\tprovider = opt.Provider\n\t} else if opt.JsonRPCClient != nil {\n\t\tprovider = &jsonRPCNodeProvider{client: opt.JsonRPCClient, eip1559: opt.EIP1559}\n\t} else {\n\t\tclient, _ := jsonrpc.NewClient(opt.JsonRPCEndpoint)\n\t\tprovider = &jsonRPCNodeProvider{client: client.Eth(), eip1559: opt.EIP1559}\n\t}\n\n\ta := &Contract{\n\t\taddr:     addr,\n\t\tabi:      abi,\n\t\tprovider: provider,\n\t\tkey:      opt.Sender,\n\t}\n\n\treturn a\n}\n\n// Contract is a wrapper to make abi calls to contract with a state provider\ntype Contract struct {\n\taddr     ethgo.Address\n\tabi      *abi.ABI\n\tbin      []byte\n\tprovider Provider\n\tkey      ethgo.Key\n}\n\nfunc (a *Contract) GetABI() *abi.ABI {\n\treturn a.abi\n}\n\ntype TxnOpts struct {\n\tValue    *big.Int\n\tGasPrice uint64\n\tGasLimit uint64\n\tNonce    uint64\n}\n\nfunc (a *Contract) Txn(method string, args ...interface{}) (Txn, error) {\n\tif a.key == nil {\n\t\treturn nil, fmt.Errorf(\"no key selected\")\n\t}\n\n\tisContractDeployment := method == \"constructor\"\n\n\tvar input []byte\n\tif isContractDeployment {\n\t\tinput = append(input, a.bin...)\n\t}\n\n\tvar abiMethod *abi.Method\n\tif isContractDeployment {\n\t\tif a.abi.Constructor != nil {\n\t\t\tabiMethod = a.abi.Constructor\n\t\t}\n\t} else {\n\t\tif abiMethod = a.abi.GetMethod(method); abiMethod == nil {\n\t\t\treturn nil, fmt.Errorf(\"method %s not found\", method)\n\t\t}\n\t}\n\tif abiMethod != nil {\n\t\tdata, err := abi.Encode(args, abiMethod.Inputs)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to encode arguments: %v\", err)\n\t\t}\n\t\tif isContractDeployment {\n\t\t\tinput = append(input, data...)\n\t\t} else {\n\t\t\tinput = append(abiMethod.ID(), data...)\n\t\t}\n\t}\n\n\ttxn, err := a.provider.Txn(a.addr, a.key, input)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn txn, nil\n}\n\ntype CallOpts struct {\n\tBlock ethgo.BlockNumber\n\tFrom  ethgo.Address\n}\n\nfunc (a *Contract) Call(method string, block ethgo.BlockNumber, args ...interface{}) (map[string]interface{}, error) {\n\tm := a.abi.GetMethod(method)\n\tif m == nil {\n\t\treturn nil, fmt.Errorf(\"method %s not found\", method)\n\t}\n\n\tdata, err := m.Encode(args)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\topts := &CallOpts{\n\t\tBlock: block,\n\t}\n\tif a.key != nil {\n\t\topts.From = a.key.Address()\n\t}\n\trawOutput, err := a.provider.Call(a.addr, data, opts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresp, err := m.Decode(rawOutput)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn resp, nil\n}\n"
  },
  {
    "path": "contract/contract_test.go",
    "content": "package contract\n\nimport (\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/testutil\"\n\t\"github.com/umbracle/ethgo/wallet\"\n)\n\nvar (\n\taddr0  = \"0x0000000000000000000000000000000000000000\"\n\taddr0B = ethgo.HexToAddress(addr0)\n)\n\nfunc TestContract_NoInput(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tcc := &testutil.Contract{}\n\tcc.AddOutputCaller(\"set\")\n\n\tcontract, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi0, err := abi.NewABI(contract.Abi)\n\tassert.NoError(t, err)\n\n\tp, _ := jsonrpc.NewClient(s.HTTPAddr())\n\tc := NewContract(addr, abi0, WithJsonRPC(p.Eth()))\n\n\tvals, err := c.Call(\"set\", ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, vals[\"0\"], big.NewInt(1))\n\n\tabi1, err := abi.NewABIFromList([]string{\n\t\t\"function set() view returns (uint256)\",\n\t})\n\tassert.NoError(t, err)\n\n\tc1 := NewContract(addr, abi1, WithJsonRPC(p.Eth()))\n\tvals, err = c1.Call(\"set\", ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, vals[\"0\"], big.NewInt(1))\n}\n\nfunc TestContract_IO(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tcc := &testutil.Contract{}\n\tcc.AddDualCaller(\"setA\", \"address\", \"uint256\")\n\n\tcontract, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi, err := abi.NewABI(contract.Abi)\n\tassert.NoError(t, err)\n\n\tc := NewContract(addr, abi, WithJsonRPCEndpoint(s.HTTPAddr()))\n\n\tresp, err := c.Call(\"setA\", ethgo.Latest, addr0B, 1000)\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, resp[\"0\"], addr0B)\n\tassert.Equal(t, resp[\"1\"], big.NewInt(1000))\n}\n\nfunc TestContract_From(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tcc := &testutil.Contract{}\n\tcc.AddCallback(func() string {\n\t\treturn `function example() public view returns (address) {\n\t\t\treturn msg.sender;\t\n\t\t}`\n\t})\n\n\tcontract, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi, err := abi.NewABI(contract.Abi)\n\tassert.NoError(t, err)\n\n\tfrom := ethgo.Address{0x1}\n\tc := NewContract(addr, abi, WithSender(from), WithJsonRPCEndpoint(s.HTTPAddr()))\n\n\tresp, err := c.Call(\"example\", ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, resp[\"0\"], from)\n}\n\nfunc TestContract_Deploy(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\t// create an address and fund it\n\tkey, _ := wallet.GenerateKey()\n\ts.Fund(key.Address())\n\n\tp, _ := jsonrpc.NewClient(s.HTTPAddr())\n\n\tcc := &testutil.Contract{}\n\tcc.AddConstructor(\"address\", \"uint256\")\n\n\tartifact, err := cc.Compile()\n\tassert.NoError(t, err)\n\n\tabi, err := abi.NewABI(artifact.Abi)\n\tassert.NoError(t, err)\n\n\tbin, err := hex.DecodeString(artifact.Bin)\n\tassert.NoError(t, err)\n\n\ttxn, err := DeployContract(abi, bin, []interface{}{ethgo.Address{0x1}, 1000}, WithJsonRPC(p.Eth()), WithSender(key))\n\tassert.NoError(t, err)\n\n\tassert.NoError(t, txn.Do())\n\treceipt, err := txn.Wait()\n\tassert.NoError(t, err)\n\n\ti := NewContract(receipt.ContractAddress, abi, WithJsonRPC(p.Eth()))\n\tresp, err := i.Call(\"val_0\", ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, resp[\"0\"], ethgo.Address{0x1})\n\n\tresp, err = i.Call(\"val_1\", ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, resp[\"0\"], big.NewInt(1000))\n}\n\nfunc TestContract_Transaction(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\t// create an address and fund it\n\tkey, _ := wallet.GenerateKey()\n\ts.Fund(key.Address())\n\n\tcc := &testutil.Contract{}\n\tcc.AddEvent(testutil.NewEvent(\"A\").Add(\"uint256\", true))\n\tcc.EmitEvent(\"setA\", \"A\", \"1\")\n\n\tartifact, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi, err := abi.NewABI(artifact.Abi)\n\tassert.NoError(t, err)\n\n\t// send multiple transactions\n\tcontract := NewContract(addr, abi, WithJsonRPCEndpoint(s.HTTPAddr()), WithSender(key))\n\n\tfor i := 0; i < 10; i++ {\n\t\ttxn, err := contract.Txn(\"setA\")\n\t\tassert.NoError(t, err)\n\n\t\terr = txn.Do()\n\t\tassert.NoError(t, err)\n\n\t\treceipt, err := txn.Wait()\n\t\tassert.NoError(t, err)\n\t\tassert.Len(t, receipt.Logs, 1)\n\t}\n}\n\nfunc TestContract_CallAtBlock(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\t// create an address and fund it\n\tkey, _ := wallet.GenerateKey()\n\ts.Fund(key.Address())\n\n\tcc := &testutil.Contract{}\n\tcc.AddCallback(func() string {\n\t\treturn `\n\t\tuint256 val = 1;\n\t\tfunction getVal() public view returns (uint256) {\n\t\t\treturn val;\n\t\t}\n\t\tfunction change() public payable {\n\t\t\tval = 2;\n\t\t}`\n\t})\n\n\tartifact, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi, err := abi.NewABI(artifact.Abi)\n\tassert.NoError(t, err)\n\n\tcontract := NewContract(addr, abi, WithJsonRPCEndpoint(s.HTTPAddr()), WithSender(key))\n\n\tcheckVal := func(block ethgo.BlockNumber, expected *big.Int) {\n\t\tresp, err := contract.Call(\"getVal\", block)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, resp[\"0\"], expected)\n\t}\n\n\t// initial value is 1\n\tcheckVal(ethgo.Latest, big.NewInt(1))\n\n\t// send a transaction to update the state\n\tvar receipt *ethgo.Receipt\n\t{\n\t\ttxn, err := contract.Txn(\"change\")\n\t\tassert.NoError(t, err)\n\n\t\terr = txn.Do()\n\t\tassert.NoError(t, err)\n\n\t\treceipt, err = txn.Wait()\n\t\tassert.NoError(t, err)\n\t}\n\n\t// validate the state at different blocks\n\t{\n\t\t// value at receipt block is 2\n\t\tcheckVal(ethgo.BlockNumber(receipt.BlockNumber), big.NewInt(2))\n\n\t\t// value at previous block is 1\n\t\tcheckVal(ethgo.BlockNumber(receipt.BlockNumber-1), big.NewInt(1))\n\t}\n}\n\nfunc TestContract_SendValueContractCall(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tkey, _ := wallet.GenerateKey()\n\ts.Fund(key.Address())\n\n\tcc := &testutil.Contract{}\n\tcc.AddCallback(func() string {\n\t\treturn `\n\t\tfunction deposit() public payable {\n\t\t}`\n\t})\n\n\tartifact, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi, err := abi.NewABI(artifact.Abi)\n\tassert.NoError(t, err)\n\n\tcontract := NewContract(addr, abi, WithJsonRPCEndpoint(s.HTTPAddr()), WithSender(key))\n\n\tbalance := big.NewInt(1)\n\n\ttxn, err := contract.Txn(\"deposit\")\n\ttxn.WithOpts(&TxnOpts{Value: balance})\n\tassert.NoError(t, err)\n\n\terr = txn.Do()\n\tassert.NoError(t, err)\n\n\t_, err = txn.Wait()\n\tassert.NoError(t, err)\n\n\tclient, _ := jsonrpc.NewClient(s.HTTPAddr())\n\tfound, err := client.Eth().GetBalance(addr, ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, found, balance)\n}\n\nfunc TestContract_EIP1559(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tkey, _ := wallet.GenerateKey()\n\ts.Fund(key.Address())\n\n\tcc := &testutil.Contract{}\n\tcc.AddOutputCaller(\"example\")\n\n\tartifact, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tabi, err := abi.NewABI(artifact.Abi)\n\tassert.NoError(t, err)\n\n\tclient, _ := jsonrpc.NewClient(s.HTTPAddr())\n\tcontract := NewContract(addr, abi, WithJsonRPC(client.Eth()), WithSender(key), WithEIP1559())\n\n\ttxn, err := contract.Txn(\"example\")\n\tassert.NoError(t, err)\n\n\terr = txn.Do()\n\tassert.NoError(t, err)\n\n\t_, err = txn.Wait()\n\tassert.NoError(t, err)\n\n\t// get transaction from rpc endpoint\n\ttxnObj, err := client.Eth().GetTransactionByHash(txn.Hash())\n\tassert.NoError(t, err)\n\n\tassert.Zero(t, txnObj.GasPrice)\n\tassert.NotZero(t, txnObj.Gas)\n\tassert.NotZero(t, txnObj.MaxFeePerGas)\n\tassert.NotZero(t, txnObj.MaxPriorityFeePerGas)\n}\n"
  },
  {
    "path": "e2e/transaction_test.go",
    "content": "package e2e\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/testutil\"\n\t\"github.com/umbracle/ethgo/wallet\"\n)\n\nfunc TestSendSignedTransaction(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tkey, err := wallet.GenerateKey()\n\tassert.NoError(t, err)\n\n\t// add value to the new key\n\tvalue := big.NewInt(1000000000000000000)\n\ts.Transfer(key.Address(), value)\n\n\tc, _ := jsonrpc.NewClient(s.HTTPAddr())\n\n\tfound, _ := c.Eth().GetBalance(key.Address(), ethgo.Latest)\n\tassert.Equal(t, found, value)\n\n\tchainID, err := c.Eth().ChainID()\n\tassert.NoError(t, err)\n\n\t// send a signed transaction\n\tto := ethgo.Address{0x1}\n\ttransferVal := big.NewInt(1000)\n\n\tgasPrice, err := c.Eth().GasPrice()\n\tassert.NoError(t, err)\n\n\ttxn := &ethgo.Transaction{\n\t\tTo:       &to,\n\t\tValue:    transferVal,\n\t\tNonce:    0,\n\t\tGasPrice: gasPrice,\n\t}\n\n\t{\n\t\tmsg := &ethgo.CallMsg{\n\t\t\tFrom:     key.Address(),\n\t\t\tTo:       &to,\n\t\t\tValue:    transferVal,\n\t\t\tGasPrice: gasPrice,\n\t\t}\n\t\tlimit, err := c.Eth().EstimateGas(msg)\n\t\tassert.NoError(t, err)\n\n\t\ttxn.Gas = limit\n\t}\n\n\tsigner := wallet.NewEIP155Signer(chainID.Uint64())\n\ttxn, err = signer.SignTx(txn, key)\n\tassert.NoError(t, err)\n\n\tfrom, err := signer.RecoverSender(txn)\n\tassert.NoError(t, err)\n\tassert.Equal(t, from, key.Address())\n\n\tdata, err := txn.MarshalRLPTo(nil)\n\tassert.NoError(t, err)\n\n\thash, err := c.Eth().SendRawTransaction(data)\n\tassert.NoError(t, err)\n\n\t_, err = s.WaitForReceipt(hash)\n\tassert.NoError(t, err)\n\n\tbalance, err := c.Eth().GetBalance(to, ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, balance, transferVal)\n}\n"
  },
  {
    "path": "encoding.go",
    "content": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype ArgBig big.Int\n\nfunc (a *ArgBig) UnmarshalText(input []byte) error {\n\tbuf, err := decodeToHex(input)\n\tif err != nil {\n\t\treturn err\n\t}\n\tb := new(big.Int)\n\tb.SetBytes(buf)\n\t*a = ArgBig(*b)\n\treturn nil\n}\n\nfunc (a ArgBig) MarshalText() ([]byte, error) {\n\tb := (*big.Int)(&a)\n\treturn []byte(\"0x\" + b.Text(16)), nil\n}\n\ntype ArgUint64 uint64\n\nfunc (b ArgUint64) MarshalText() ([]byte, error) {\n\tbuf := make([]byte, 2, 10)\n\tcopy(buf, `0x`)\n\tbuf = strconv.AppendUint(buf, uint64(b), 16)\n\treturn buf, nil\n}\n\nfunc (u *ArgUint64) UnmarshalText(input []byte) error {\n\tstr := strings.TrimPrefix(string(input), \"0x\")\n\tif str == \"\" {\n\t\tstr = \"0\"\n\t}\n\tnum, err := strconv.ParseUint(str, 16, 64)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*u = ArgUint64(num)\n\treturn nil\n}\n\nfunc (u *ArgUint64) Uint64() uint64 {\n\treturn uint64(*u)\n}\n\ntype ArgBytes []byte\n\nfunc (b ArgBytes) MarshalText() ([]byte, error) {\n\treturn encodeToHex(b), nil\n}\n\nfunc (b *ArgBytes) UnmarshalText(input []byte) error {\n\thh, err := decodeToHex(input)\n\tif err != nil {\n\t\treturn nil\n\t}\n\taux := make([]byte, len(hh))\n\tcopy(aux[:], hh[:])\n\t*b = aux\n\treturn nil\n}\n\nfunc (b *ArgBytes) Bytes() []byte {\n\treturn *b\n}\n\nfunc decodeToHex(b []byte) ([]byte, error) {\n\tstr := string(b)\n\tstr = strings.TrimPrefix(str, \"0x\")\n\tif len(str)%2 != 0 {\n\t\tstr = \"0\" + str\n\t}\n\treturn hex.DecodeString(str)\n}\n\nfunc encodeToHex(b []byte) []byte {\n\tstr := hex.EncodeToString(b)\n\tif len(str)%2 != 0 {\n\t\tstr = \"0\" + str\n\t}\n\treturn []byte(\"0x\" + str)\n}\n"
  },
  {
    "path": "ens/address_mapping.go",
    "content": "package ens\n\nimport \"github.com/umbracle/ethgo\"\n\nvar defaultEnsAddr = ethgo.HexToAddress(\"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e\")\n\nvar builtinEnsAddr = map[uint64]ethgo.Address{\n\t1: defaultEnsAddr,\n\t3: defaultEnsAddr,\n\t4: defaultEnsAddr,\n\t5: defaultEnsAddr,\n}\n"
  },
  {
    "path": "ens/ens.go",
    "content": "package ens\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/builtin/ens\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\ntype EnsConfig struct {\n\tLogger   *log.Logger\n\tClient   *jsonrpc.Client\n\tAddr     string\n\tResolver ethgo.Address\n}\n\ntype EnsOption func(*EnsConfig)\n\nfunc WithResolver(resolver ethgo.Address) EnsOption {\n\treturn func(c *EnsConfig) {\n\t\tc.Resolver = resolver\n\t}\n}\n\nfunc WithLogger(logger *log.Logger) EnsOption {\n\treturn func(c *EnsConfig) {\n\t\tc.Logger = logger\n\t}\n}\n\nfunc WithAddress(addr string) EnsOption {\n\treturn func(c *EnsConfig) {\n\t\tc.Addr = addr\n\t}\n}\n\nfunc WithClient(client *jsonrpc.Client) EnsOption {\n\treturn func(c *EnsConfig) {\n\t\tc.Client = client\n\t}\n}\n\ntype ENS struct {\n\tconfig *EnsConfig\n}\n\nfunc NewENS(opts ...EnsOption) (*ENS, error) {\n\tconfig := &EnsConfig{}\n\tfor _, opt := range opts {\n\t\topt(config)\n\t}\n\n\tif config.Client == nil {\n\t\t// addr must be set\n\t\tif config.Addr == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"jsonrpc addr is empty\")\n\t\t}\n\t\tclient, err := jsonrpc.NewClient(config.Addr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tconfig.Client = client\n\t}\n\n\tif config.Resolver == ethgo.ZeroAddress {\n\t\t// try to get the resolver address from the builtin list\n\t\tchainID, err := config.Client.Eth().ChainID()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\taddr, ok := builtinEnsAddr[chainID.Uint64()]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"no builtin Ens resolver found for chain %s\", chainID)\n\t\t}\n\t\tconfig.Resolver = addr\n\t}\n\tens := &ENS{\n\t\tconfig: config,\n\t}\n\treturn ens, nil\n}\n\nfunc (e *ENS) Resolve(name string) (ethgo.Address, error) {\n\tresolver := ens.NewENSResolver(e.config.Resolver, e.config.Client)\n\treturn resolver.Resolve(name)\n}\n\nfunc (e *ENS) ReverseResolve(addr ethgo.Address) (string, error) {\n\tresolver := ens.NewENSResolver(e.config.Resolver, e.config.Client)\n\treturn resolver.ReverseResolve(addr)\n}\n"
  },
  {
    "path": "ens/ens_test.go",
    "content": "package ens\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc TestENS_Resolve(t *testing.T) {\n\tens, err := NewENS(WithAddress(testutil.TestInfuraEndpoint(t)))\n\tassert.NoError(t, err)\n\n\taddr, err := ens.Resolve(\"nick.eth\")\n\tassert.NoError(t, err)\n\tassert.Equal(t, ethgo.HexToAddress(\"0xb8c2C29ee19D8307cb7255e1Cd9CbDE883A267d5\"), addr)\n\n\tname, err := ens.ReverseResolve(ethgo.HexToAddress(\"0xb8c2C29ee19D8307cb7255e1Cd9CbDE883A267d5\"))\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"nick.eth\", name)\n}\n"
  },
  {
    "path": "etherscan/etherscan.go",
    "content": "package etherscan\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/jsonrpc/codec\"\n\t\"github.com/valyala/fasthttp\"\n)\n\n// Etherscan is a provider using the Etherscan api\ntype Etherscan struct {\n\tclient fasthttp.Client\n\turl    string\n\tapiKey string\n}\n\n// NewEtherscanFromNetwork creates a new client from the network id\nfunc NewEtherscanFromNetwork(n ethgo.Network, apiKey string) (*Etherscan, error) {\n\tvar url string\n\tswitch n {\n\tcase ethgo.Mainnet:\n\t\turl = \"https://api.etherscan.io\"\n\n\tcase ethgo.Ropsten:\n\t\turl = \"https://ropsten.etherscan.io\"\n\n\tcase ethgo.Rinkeby:\n\t\turl = \"https://rinkeby.etherscan.io\"\n\n\tcase ethgo.Goerli:\n\t\turl = \"https://goerli.etherscan.io\"\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknwon network id %d\", n)\n\t}\n\treturn NewEtherscan(url, apiKey), nil\n}\n\n// NewEtherscan creates a new Etherscan service from a url\nfunc NewEtherscan(url, apiKey string) *Etherscan {\n\treturn &Etherscan{url: url, apiKey: apiKey}\n}\n\ntype proxyResponse struct {\n\tStatus  string\n\tMessage string\n\tResult  json.RawMessage\n}\n\n// Query sends a query to Etherscan\nfunc (e *Etherscan) Query(module, action string, out interface{}, params map[string]string) error {\n\turl := fmt.Sprintf(\"%s/api?module=%s&action=%s\", e.url, module, action)\n\tif len(params) != 0 {\n\t\tres := []string{}\n\t\tfor k, v := range params {\n\t\t\tres = append(res, k+\"=\"+v)\n\t\t}\n\t\turl += \"&\" + strings.Join(res, \"&\")\n\t}\n\tif e.apiKey != \"\" {\n\t\turl = url + \"&apikey=\" + e.apiKey\n\t}\n\n\treq := fasthttp.AcquireRequest()\n\tres := fasthttp.AcquireResponse()\n\n\tdefer fasthttp.ReleaseRequest(req)\n\tdefer fasthttp.ReleaseResponse(res)\n\n\treq.SetRequestURI(url)\n\treq.Header.SetMethod(\"GET\")\n\n\tif err := e.client.Do(req, res); err != nil {\n\t\treturn err\n\t}\n\n\t// Decode json-rpc response\n\tvar result json.RawMessage\n\n\tif module == \"proxy\" {\n\t\tvar response codec.Response\n\t\tif err := json.Unmarshal(res.Body(), &response); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif response.Error != nil {\n\t\t\treturn response.Error\n\t\t}\n\t\tresult = response.Result\n\t} else {\n\t\tvar response proxyResponse\n\t\tif err := json.Unmarshal(res.Body(), &response); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tresult = response.Result\n\t}\n\n\tif err := json.Unmarshal(result, out); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// BlockNumber returns the number of most recent block.\nfunc (e *Etherscan) BlockNumber() (uint64, error) {\n\tvar out string\n\tif err := e.Query(\"proxy\", \"eth_blockNumber\", &out, nil); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n\n// GetBlockByNumber returns information about a block by block number.\nfunc (e *Etherscan) GetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error) {\n\tvar b *ethgo.Block\n\tparams := map[string]string{\n\t\t\"tag\":     i.String(),\n\t\t\"boolean\": strconv.FormatBool(full),\n\t}\n\tif err := e.Query(\"proxy\", \"eth_getBlockByNumber\", &b, params); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\ntype ContractCode struct {\n\tSourceCode           string\n\tContractName         string\n\tRuns                 string\n\tCompilerVersion      string\n\tConstructorArguments string\n}\n\nfunc (e *Etherscan) GetContractCode(addr ethgo.Address) (*ContractCode, error) {\n\tvar out []*ContractCode\n\terr := e.Query(\"contract\", \"getsourcecode\", &out, map[string]string{\n\t\t\"address\": addr.String(),\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(out) != 1 {\n\t\treturn nil, fmt.Errorf(\"incorrect values\")\n\t}\n\treturn out[0], nil\n}\n\nfunc (e *Etherscan) GasPrice() (uint64, error) {\n\tvar out struct {\n\t\tLastBlock string `json:\"LastBlock\"`\n\t}\n\tif err := e.Query(\"gastracker\", \"gasoracle\", &out, map[string]string{}); err != nil {\n\t\treturn 0, err\n\t}\n\tnum, err := strconv.Atoi(out.LastBlock)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint64(num), nil\n}\n\nfunc (e *Etherscan) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error) {\n\tif len(filter.Address) == 0 {\n\t\treturn nil, fmt.Errorf(\"an address to filter is required\")\n\t}\n\tstrBlockNumber := func(b ethgo.BlockNumber) string {\n\t\tswitch b {\n\t\tcase ethgo.Latest:\n\t\t\treturn \"latest\"\n\t\tcase ethgo.Earliest:\n\t\t\treturn \"earliest\"\n\t\tcase ethgo.Pending:\n\t\t\treturn \"pending\"\n\t\t}\n\t\tif b < 0 {\n\t\t\tpanic(\"internal. blocknumber is negative\")\n\t\t}\n\t\treturn fmt.Sprintf(\"%d\", uint64(b))\n\t}\n\n\tparams := map[string]string{\n\t\t\"address\": filter.Address[0].String(),\n\t}\n\tif filter.From != nil {\n\t\tparams[\"fromBlock\"] = strBlockNumber(*filter.From)\n\t}\n\tif filter.To != nil {\n\t\tparams[\"toBlock\"] = strBlockNumber(*filter.To)\n\t}\n\tvar out []*ethgo.Log\n\tif err := e.Query(\"logs\", \"getLogs\", &out, params); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc parseUint64orHex(str string) (uint64, error) {\n\tbase := 10\n\tif strings.HasPrefix(str, \"0x\") {\n\t\tstr = str[2:]\n\t\tbase = 16\n\t}\n\treturn strconv.ParseUint(str, base, 64)\n}\n"
  },
  {
    "path": "etherscan/etherscan_test.go",
    "content": "package etherscan\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc testEtherscanMainnet(t *testing.T) *Etherscan {\n\tapiKey := os.Getenv(\"ETHERSCAN_APIKEY\")\n\tif apiKey == \"\" {\n\t\tt.Skip(\"Etherscan APIKey not specified\")\n\t}\n\treturn &Etherscan{url: \"https://api.etherscan.io\", apiKey: apiKey}\n}\n\nfunc TestNewEtherscan(t *testing.T) {\n\twantUrl := \"http://test.url/\"\n\twantApiKey := \"abc123\"\n\te := NewEtherscan(wantUrl, wantApiKey)\n\tassert.Equal(t, wantUrl, e.url)\n\tassert.Equal(t, wantApiKey, e.apiKey)\n}\n\nfunc TestBlockByNumber(t *testing.T) {\n\te := testEtherscanMainnet(t)\n\tn, err := e.BlockNumber()\n\tassert.NoError(t, err)\n\tassert.NotEqual(t, n, 0)\n}\n\nfunc TestGetBlockByNumber(t *testing.T) {\n\te := testEtherscanMainnet(t)\n\tb, err := e.GetBlockByNumber(1, false)\n\tassert.NoError(t, err)\n\tassert.Equal(t, b.Number, uint64(1))\n}\n\nfunc TestContract(t *testing.T) {\n\te := testEtherscanMainnet(t)\n\n\t// uniswap v2. router\n\tcode, err := e.GetContractCode(ethgo.HexToAddress(\"0x7a250d5630b4cf539739df2c5dacb4c659f2488d\"))\n\tassert.NoError(t, err)\n\tassert.Equal(t, code.Runs, \"999999\")\n}\n\nfunc TestGetLogs(t *testing.T) {\n\te := testEtherscanMainnet(t)\n\n\tfrom := ethgo.BlockNumber(379224)\n\tto := ethgo.Latest\n\n\tfilter := &ethgo.LogFilter{\n\t\tFrom: &from,\n\t\tTo:   &to,\n\t\tAddress: []ethgo.Address{\n\t\t\tethgo.HexToAddress(\"0x33990122638b9132ca29c723bdf037f1a891a70c\"),\n\t\t},\n\t}\n\tlogs, err := e.GetLogs(filter)\n\tassert.NoError(t, err)\n\tassert.NotEmpty(t, logs)\n}\n\nfunc TestGasPrice(t *testing.T) {\n\te := testEtherscanMainnet(t)\n\n\tgas, err := e.GasPrice()\n\tassert.NoError(t, err)\n\tassert.NotZero(t, gas)\n}\n"
  },
  {
    "path": "examples/contract-call-basic.go",
    "content": "package examples\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nfunc handleErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// call a contract\nfunc contractCall() {\n\tvar functions = []string{\n\t\t\"function totalSupply() view returns (uint256)\",\n\t}\n\n\tabiContract, err := abi.NewABIFromList(functions)\n\thandleErr(err)\n\n\t// Matic token\n\taddr := ethgo.HexToAddress(\"0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0\")\n\n\tclient, err := jsonrpc.NewClient(\"https://mainnet.infura.io\")\n\thandleErr(err)\n\n\tc := contract.NewContract(addr, abiContract, contract.WithJsonRPC(client.Eth()))\n\tres, err := c.Call(\"totalSupply\", ethgo.Latest)\n\thandleErr(err)\n\n\tfmt.Printf(\"TotalSupply: %s\", res[\"totalSupply\"].(*big.Int))\n}\n"
  },
  {
    "path": "examples/contract-call-from.go",
    "content": "package examples\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\n// call a contract and use a custom `from` address\nfunc contractCallFrom() {\n\tvar functions = []string{\n\t\t\"function totalSupply() view returns (uint256)\",\n\t}\n\n\tabiContract, err := abi.NewABIFromList(functions)\n\thandleErr(err)\n\n\t// Matic token\n\taddr := ethgo.HexToAddress(\"0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0\")\n\n\tclient, err := jsonrpc.NewClient(\"https://mainnet.infura.io\")\n\thandleErr(err)\n\n\t// from address (msg.sender in solidity)\n\tfrom := ethgo.Address{0x1}\n\n\tc := contract.NewContract(addr, abiContract, contract.WithSender(from), contract.WithJsonRPC(client.Eth()))\n\tres, err := c.Call(\"totalSupply\", ethgo.Latest)\n\thandleErr(err)\n\n\tfmt.Printf(\"TotalSupply: %s\", res[\"totalSupply\"].(*big.Int))\n}\n"
  },
  {
    "path": "examples/contract-deploy.go",
    "content": "package examples\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/contract\"\n)\n\nfunc contractDeploy() {\n\tabiContract, err := abi.NewABIFromList([]string{})\n\thandleErr(err)\n\n\t// bytecode of the contract\n\tbin := []byte{}\n\n\ttxn, err := contract.DeployContract(abiContract, bin, []interface{}{})\n\thandleErr(err)\n\n\terr = txn.Do()\n\thandleErr(err)\n\n\treceipt, err := txn.Wait()\n\thandleErr(err)\n\n\tfmt.Printf(\"Contract: %s\", receipt.ContractAddress)\n}\n"
  },
  {
    "path": "examples/contract-transaction.go",
    "content": "package examples\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/wallet\"\n)\n\nfunc contractTransaction() {\n\tvar functions = []string{\n\t\t\"function transferFrom(address from, address to, uint256 value)\",\n\t}\n\n\tabiContract, err := abi.NewABIFromList(functions)\n\thandleErr(err)\n\n\t// Matic token\n\taddr := ethgo.HexToAddress(\"0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0\")\n\n\tclient, err := jsonrpc.NewClient(\"https://mainnet.infura.io\")\n\thandleErr(err)\n\n\t// wallet signer\n\tkey, err := wallet.GenerateKey()\n\thandleErr(err)\n\n\topts := []contract.ContractOption{\n\t\tcontract.WithJsonRPC(client.Eth()),\n\t\tcontract.WithSender(key),\n\t}\n\tc := contract.NewContract(addr, abiContract, opts...)\n\ttxn, err := c.Txn(\"transferFrom\", ethgo.Latest)\n\thandleErr(err)\n\n\terr = txn.Do()\n\thandleErr(err)\n\n\treceipt, err := txn.Wait()\n\thandleErr(err)\n\n\tfmt.Printf(\"Transaction mined at: %s\", receipt.TransactionHash)\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/umbracle/ethgo\n\ngo 1.18\n\nrequire (\n\tgithub.com/btcsuite/btcd v0.23.3\n\tgithub.com/btcsuite/btcd/btcec/v2 v2.1.3\n\tgithub.com/btcsuite/btcd/btcutil v1.1.0\n\tgithub.com/gorilla/websocket v1.4.1\n\tgithub.com/jmoiron/sqlx v1.2.0\n\tgithub.com/lib/pq v1.2.0\n\tgithub.com/mitchellh/mapstructure v1.4.1\n\tgithub.com/ory/dockertest v3.3.5+incompatible\n\tgithub.com/stretchr/testify v1.8.0\n\tgithub.com/tyler-smith/go-bip39 v1.1.0\n\tgithub.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722\n\tgithub.com/valyala/fasthttp v1.4.0\n\tgithub.com/valyala/fastjson v1.4.1\n\tgo.etcd.io/bbolt v1.3.6\n\tgolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad\n\tgolang.org/x/text v0.8.0\n\tpgregory.net/rapid v0.5.5\n)\n\nrequire (\n\tgithub.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect\n\tgithub.com/Microsoft/go-winio v0.6.0 // indirect\n\tgithub.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect\n\tgithub.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect\n\tgithub.com/cenkalti/backoff v2.2.1+incompatible // indirect\n\tgithub.com/containerd/continuity v0.3.0 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect\n\tgithub.com/docker/go-connections v0.4.0 // indirect\n\tgithub.com/docker/go-units v0.4.0 // indirect\n\tgithub.com/go-sql-driver/mysql v1.6.0 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect\n\tgithub.com/klauspost/compress v1.4.1 // indirect\n\tgithub.com/klauspost/cpuid v1.2.0 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/opencontainers/image-spec v1.0.2 // indirect\n\tgithub.com/opencontainers/runc v1.1.5 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n\tgithub.com/sirupsen/logrus v1.8.1 // indirect\n\tgithub.com/valyala/bytebufferpool v1.0.0 // indirect\n\tgolang.org/x/mod v0.9.0 // indirect\n\tgolang.org/x/net v0.8.0 // indirect\n\tgolang.org/x/sys v0.7.0 // indirect\n\tgolang.org/x/tools v0.7.0 // indirect\n\tgopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tgotest.tools v2.2.0+incompatible // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=\ngithub.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=\ngithub.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=\ngithub.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=\ngithub.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=\ngithub.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=\ngithub.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=\ngithub.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=\ngithub.com/btcsuite/btcd v0.23.3 h1:4KH/JKy9WiCd+iUS9Mu0Zp7Dnj17TGdKrg9xc/FGj24=\ngithub.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=\ngithub.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=\ngithub.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE=\ngithub.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=\ngithub.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=\ngithub.com/btcsuite/btcd/btcutil v1.1.0 h1:MO4klnGY+EWJdoWF12Wkuf4AWDBPMpZNeN/jRLrklUU=\ngithub.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=\ngithub.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=\ngithub.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=\ngithub.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=\ngithub.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=\ngithub.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=\ngithub.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=\ngithub.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=\ngithub.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=\ngithub.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=\ngithub.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=\ngithub.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=\ngithub.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=\ngithub.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=\ngithub.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=\ngithub.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=\ngithub.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=\ngithub.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=\ngithub.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=\ngithub.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=\ngithub.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=\ngithub.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=\ngithub.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=\ngithub.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=\ngithub.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=\ngithub.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=\ngithub.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=\ngithub.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=\ngithub.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=\ngithub.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=\ngithub.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=\ngithub.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=\ngithub.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=\ngithub.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=\ngithub.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=\ngithub.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=\ngithub.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=\ngithub.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=\ngithub.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=\ngithub.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=\ngithub.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=\ngithub.com/klauspost/compress v1.4.1 h1:8VMb5+0wMgdBykOV96DwNwKFQ+WTI4pzYURP99CcB9E=\ngithub.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=\ngithub.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=\ngithub.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=\ngithub.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=\ngithub.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=\ngithub.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=\ngithub.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=\ngithub.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=\ngithub.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=\ngithub.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=\ngithub.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=\ngithub.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=\ngithub.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=\ngithub.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=\ngithub.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=\ngithub.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=\ngithub.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=\ngithub.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=\ngithub.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=\ngithub.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=\ngithub.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=\ngithub.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=\ngithub.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=\ngithub.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=\ngithub.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=\ngithub.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=\ngithub.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E=\ngithub.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=\ngithub.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=\ngithub.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=\ngithub.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=\ngithub.com/valyala/fasthttp v1.4.0 h1:PuaTGZIw3mjYhhhbVbCQp8aciRZN9YdoB7MGX9Ko76A=\ngithub.com/valyala/fasthttp v1.4.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=\ngithub.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE=\ngithub.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o=\ngithub.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=\ngithub.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=\ngithub.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=\ngo.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=\ngo.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=\ngolang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=\ngolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=\ngolang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=\ngolang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=\ngolang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=\ngolang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=\ngolang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=\ngolang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=\ngoogle.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=\ngotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=\npgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA=\npgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=\n"
  },
  {
    "path": "jsonrpc/client.go",
    "content": "package jsonrpc\n\nimport (\n\t\"github.com/umbracle/ethgo/jsonrpc/transport\"\n)\n\n// Client is the jsonrpc client\ntype Client struct {\n\ttransport transport.Transport\n\tendpoints endpoints\n}\n\ntype endpoints struct {\n\tw *Web3\n\te *Eth\n\tn *Net\n\td *Debug\n}\n\ntype Config struct {\n\theaders map[string]string\n}\n\ntype ConfigOption func(*Config)\n\nfunc WithHeaders(headers map[string]string) ConfigOption {\n\treturn func(c *Config) {\n\t\tfor k, v := range headers {\n\t\t\tc.headers[k] = v\n\t\t}\n\t}\n}\n\nfunc NewClient(addr string, opts ...ConfigOption) (*Client, error) {\n\tconfig := &Config{headers: map[string]string{}}\n\tfor _, opt := range opts {\n\t\topt(config)\n\t}\n\n\tc := &Client{}\n\tc.endpoints.w = &Web3{c}\n\tc.endpoints.e = &Eth{c}\n\tc.endpoints.n = &Net{c}\n\tc.endpoints.d = &Debug{c}\n\n\tt, err := transport.NewTransport(addr, config.headers)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tc.transport = t\n\treturn c, nil\n}\n\n// Close closes the transport\nfunc (c *Client) Close() error {\n\treturn c.transport.Close()\n}\n\n// Call makes a jsonrpc call\nfunc (c *Client) Call(method string, out interface{}, params ...interface{}) error {\n\treturn c.transport.Call(method, out, params...)\n}\n\n// SetMaxConnsLimit sets the maximum number of connections that can be established with a host\nfunc (c *Client) SetMaxConnsLimit(count int) {\n\tc.transport.SetMaxConnsPerHost(count)\n}\n"
  },
  {
    "path": "jsonrpc/codec/codec.go",
    "content": "package codec\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// Request is a jsonrpc request\ntype Request struct {\n\tJsonRPC string          `json:\"jsonrpc\"`\n\tID      uint64          `json:\"id\"`\n\tMethod  string          `json:\"method\"`\n\tParams  json.RawMessage `json:\"params\"`\n}\n\n// Response is a jsonrpc response\ntype Response struct {\n\tID     uint64          `json:\"id\"`\n\tResult json.RawMessage `json:\"result\"`\n\tError  *ErrorObject    `json:\"error,omitempty\"`\n}\n\n// ErrorObject is a jsonrpc error\ntype ErrorObject struct {\n\tCode    int         `json:\"code\"`\n\tMessage string      `json:\"message\"`\n\tData    interface{} `json:\"data,omitempty\"`\n}\n\n// Subscription is a jsonrpc subscription\ntype Subscription struct {\n\tID     string          `json:\"subscription\"`\n\tResult json.RawMessage `json:\"result\"`\n}\n\n// Error implements error interface\nfunc (e *ErrorObject) Error() string {\n\tdata, err := json.Marshal(e)\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"jsonrpc.internal marshal error: %v\", err)\n\t}\n\treturn string(data)\n}\n"
  },
  {
    "path": "jsonrpc/debug.go",
    "content": "package jsonrpc\n\nimport \"github.com/umbracle/ethgo\"\n\ntype Debug struct {\n\tc *Client\n}\n\n// Debug returns the reference to the debug namespace\nfunc (c *Client) Debug() *Debug {\n\treturn c.endpoints.d\n}\n\ntype TraceTransactionOptions struct {\n\tEnableMemory     bool                   `json:\"enableMemory\"`\n\tDisableStack     bool                   `json:\"disableStack\"`\n\tDisableStorage   bool                   `json:\"disableStorage\"`\n\tEnableReturnData bool                   `json:\"enableReturnData\"`\n\tTimeout          string                 `json:\"timeout,omitempty\"`\n\tTracer           string                 `json:\"tracer,omitempty\"`\n\tTracerConfig     map[string]interface{} `json:\"tracerConfig,omitempty\"`\n}\n\ntype TransactionTrace struct {\n\tGas         uint64\n\tReturnValue string\n\tStructLogs  []*StructLogs\n}\n\ntype StructLogs struct {\n\tDepth   int\n\tGas     int\n\tGasCost int\n\tOp      string\n\tPc      int\n\tMemory  []string\n\tStack   []string\n\tStorage map[string]string\n}\n\nfunc (d *Debug) TraceTransaction(hash ethgo.Hash, opts TraceTransactionOptions) (*TransactionTrace, error) {\n\tvar res *TransactionTrace\n\terr := d.c.Call(\"debug_traceTransaction\", &res, hash, opts)\n\treturn res, err\n}\n"
  },
  {
    "path": "jsonrpc/debug_test.go",
    "content": "package jsonrpc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc TestDebug_TraceTransaction(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tcc := &testutil.Contract{}\n\tcc.AddEvent(testutil.NewEvent(\"A\").Add(\"address\", true))\n\tcc.EmitEvent(\"setA\", \"A\", addr0.String())\n\n\t_, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tr, err := s.TxnTo(addr, \"setA2\")\n\trequire.NoError(t, err)\n\n\ttrace, err := c.Debug().TraceTransaction(r.TransactionHash, TraceTransactionOptions{})\n\tassert.NoError(t, err)\n\tassert.Greater(t, trace.Gas, uint64(20000))\n\tassert.NotEmpty(t, trace.StructLogs)\n}\n"
  },
  {
    "path": "jsonrpc/eth.go",
    "content": "package jsonrpc\n\nimport (\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// Eth is the eth namespace\ntype Eth struct {\n\tc *Client\n}\n\n// Eth returns the reference to the eth namespace\nfunc (c *Client) Eth() *Eth {\n\treturn c.endpoints.e\n}\n\n// GetCode returns the code of a contract\nfunc (e *Eth) GetCode(addr ethgo.Address, block ethgo.BlockNumberOrHash) (string, error) {\n\tvar res string\n\tif err := e.c.Call(\"eth_getCode\", &res, addr, block.Location()); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn res, nil\n}\n\n// Accounts returns a list of addresses owned by client.\nfunc (e *Eth) Accounts() ([]ethgo.Address, error) {\n\tvar out []ethgo.Address\n\tif err := e.c.Call(\"eth_accounts\", &out); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// GetStorageAt returns the value from a storage position at a given address.\nfunc (e *Eth) GetStorageAt(addr ethgo.Address, slot ethgo.Hash, block ethgo.BlockNumberOrHash) (ethgo.Hash, error) {\n\tvar hash ethgo.Hash\n\terr := e.c.Call(\"eth_getStorageAt\", &hash, addr, slot, block.Location())\n\treturn hash, err\n}\n\n// BlockNumber returns the number of most recent block.\nfunc (e *Eth) BlockNumber() (uint64, error) {\n\tvar out string\n\tif err := e.c.Call(\"eth_blockNumber\", &out); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n\n// GetBlockByNumber returns information about a block by block number.\nfunc (e *Eth) GetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error) {\n\tvar b *ethgo.Block\n\tif err := e.c.Call(\"eth_getBlockByNumber\", &b, i.String(), full); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// GetBlockByHash returns information about a block by hash.\nfunc (e *Eth) GetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block, error) {\n\tvar b *ethgo.Block\n\tif err := e.c.Call(\"eth_getBlockByHash\", &b, hash, full); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\n// GetFilterChanges returns the filter changes for log filters\nfunc (e *Eth) GetFilterChanges(id string) ([]*ethgo.Log, error) {\n\tvar logs []*ethgo.Log\n\tif err := e.c.Call(\"eth_getFilterChanges\", &logs, id); err != nil {\n\t\treturn nil, err\n\t}\n\treturn logs, nil\n}\n\n// GetTransactionByHash returns a transaction by his hash\nfunc (e *Eth) GetTransactionByHash(hash ethgo.Hash) (*ethgo.Transaction, error) {\n\tvar txn *ethgo.Transaction\n\terr := e.c.Call(\"eth_getTransactionByHash\", &txn, hash)\n\treturn txn, err\n}\n\n// GetFilterChangesBlock returns the filter changes for block filters\nfunc (e *Eth) GetFilterChangesBlock(id string) ([]ethgo.Hash, error) {\n\tvar hashes []ethgo.Hash\n\tif err := e.c.Call(\"eth_getFilterChanges\", &hashes, id); err != nil {\n\t\treturn nil, err\n\t}\n\treturn hashes, nil\n}\n\n// NewFilter creates a new log filter\nfunc (e *Eth) NewFilter(filter *ethgo.LogFilter) (string, error) {\n\tvar id string\n\terr := e.c.Call(\"eth_newFilter\", &id, filter)\n\treturn id, err\n}\n\n// NewBlockFilter creates a new block filter\nfunc (e *Eth) NewBlockFilter() (string, error) {\n\tvar id string\n\terr := e.c.Call(\"eth_newBlockFilter\", &id, nil)\n\treturn id, err\n}\n\n// UninstallFilter uninstalls a filter\nfunc (e *Eth) UninstallFilter(id string) (bool, error) {\n\tvar res bool\n\terr := e.c.Call(\"eth_uninstallFilter\", &res, id)\n\treturn res, err\n}\n\n// SendRawTransaction sends a signed transaction in rlp format.\nfunc (e *Eth) SendRawTransaction(data []byte) (ethgo.Hash, error) {\n\tvar hash ethgo.Hash\n\thexData := \"0x\" + hex.EncodeToString(data)\n\terr := e.c.Call(\"eth_sendRawTransaction\", &hash, hexData)\n\treturn hash, err\n}\n\n// SendTransaction creates new message call transaction or a contract creation.\nfunc (e *Eth) SendTransaction(txn *ethgo.Transaction) (ethgo.Hash, error) {\n\tvar hash ethgo.Hash\n\terr := e.c.Call(\"eth_sendTransaction\", &hash, txn)\n\treturn hash, err\n}\n\n// GetTransactionReceipt returns the receipt of a transaction by transaction hash.\nfunc (e *Eth) GetTransactionReceipt(hash ethgo.Hash) (*ethgo.Receipt, error) {\n\tvar receipt *ethgo.Receipt\n\terr := e.c.Call(\"eth_getTransactionReceipt\", &receipt, hash)\n\treturn receipt, err\n}\n\n// GetNonce returns the nonce of the account\nfunc (e *Eth) GetNonce(addr ethgo.Address, blockNumber ethgo.BlockNumberOrHash) (uint64, error) {\n\tvar nonce string\n\tif err := e.c.Call(\"eth_getTransactionCount\", &nonce, addr, blockNumber.Location()); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(nonce)\n}\n\n// GetBalance returns the balance of the account of given address.\nfunc (e *Eth) GetBalance(addr ethgo.Address, blockNumber ethgo.BlockNumberOrHash) (*big.Int, error) {\n\tvar out string\n\tif err := e.c.Call(\"eth_getBalance\", &out, addr, blockNumber.Location()); err != nil {\n\t\treturn nil, err\n\t}\n\tb, ok := new(big.Int).SetString(out[2:], 16)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"failed to convert to big.int\")\n\t}\n\treturn b, nil\n}\n\n// GasPrice returns the current price per gas in wei.\nfunc (e *Eth) GasPrice() (uint64, error) {\n\tvar out string\n\tif err := e.c.Call(\"eth_gasPrice\", &out); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n\n// Call executes a new message call immediately without creating a transaction on the blockchain.\nfunc (e *Eth) Call(msg *ethgo.CallMsg, block ethgo.BlockNumber, override ...*ethgo.StateOverride) (string, error) {\n\tvar out string\n\tif len(override) == 1 && override[0] != nil {\n\t\tif err := e.c.Call(\"eth_call\", &out, msg, block.String(), override[0]); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t} else {\n\t\tif err := e.c.Call(\"eth_call\", &out, msg, block.String()); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn out, nil\n}\n\n// EstimateGasContract estimates the gas to deploy a contract\nfunc (e *Eth) EstimateGasContract(bin []byte) (uint64, error) {\n\tvar out string\n\tmsg := map[string]interface{}{\n\t\t\"data\": \"0x\" + hex.EncodeToString(bin),\n\t}\n\tif err := e.c.Call(\"eth_estimateGas\", &out, msg); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n\n// EstimateGas generates and returns an estimate of how much gas is necessary to allow the transaction to complete.\nfunc (e *Eth) EstimateGas(msg *ethgo.CallMsg) (uint64, error) {\n\tvar out string\n\tif err := e.c.Call(\"eth_estimateGas\", &out, msg); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n\n// GetLogs returns an array of all logs matching a given filter object\nfunc (e *Eth) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error) {\n\tvar out []*ethgo.Log\n\tif err := e.c.Call(\"eth_getLogs\", &out, filter); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// ChainID returns the id of the chain\nfunc (e *Eth) ChainID() (*big.Int, error) {\n\tvar out string\n\tif err := e.c.Call(\"eth_chainId\", &out); err != nil {\n\t\treturn nil, err\n\t}\n\treturn parseBigInt(out), nil\n}\n\n// FeeHistory is the result of the eth_feeHistory endpoint\ntype FeeHistory struct {\n\tOldestBlock  *big.Int     `json:\"oldestBlock\"`\n\tReward       [][]*big.Int `json:\"reward,omitempty\"`\n\tBaseFee      []*big.Int   `json:\"baseFeePerGas,omitempty\"`\n\tGasUsedRatio []float64    `json:\"gasUsedRatio\"`\n}\n\nfunc (f *FeeHistory) UnmarshalJSON(data []byte) error {\n\tvar raw struct {\n\t\tOldestBlock  *ArgBig     `json:\"oldestBlock\"`\n\t\tReward       [][]*ArgBig `json:\"reward,omitempty\"`\n\t\tBaseFee      []*ArgBig   `json:\"baseFeePerGas,omitempty\"`\n\t\tGasUsedRatio []float64   `json:\"gasUsedRatio\"`\n\t}\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn err\n\t}\n\tif raw.OldestBlock != nil {\n\t\tf.OldestBlock = raw.OldestBlock.Big()\n\t}\n\tif raw.Reward != nil {\n\t\tf.Reward = [][]*big.Int{}\n\t\tfor _, r := range raw.Reward {\n\t\t\telem := []*big.Int{}\n\t\t\tfor _, i := range r {\n\t\t\t\telem = append(elem, i.Big())\n\t\t\t}\n\t\t\tf.Reward = append(f.Reward, elem)\n\t\t}\n\t}\n\tif raw.BaseFee != nil {\n\t\tf.BaseFee = []*big.Int{}\n\t\tfor _, i := range raw.BaseFee {\n\t\t\tf.BaseFee = append(f.BaseFee, i.Big())\n\t\t}\n\t}\n\tf.GasUsedRatio = raw.GasUsedRatio\n\treturn nil\n}\n\n// FeeHistory returns base fee per gas and transaction effective priority fee\nfunc (e *Eth) FeeHistory(blockCount uint64, newestBlock ethgo.BlockNumber, rewardPercentiles []float64) (*FeeHistory, error) {\n\tvar out *FeeHistory\n\tif err := e.c.Call(\"eth_feeHistory\", &out, blockCount, newestBlock.String(), rewardPercentiles); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// MaxPriorityFeePerGas returns a fee per gas that is an estimate of how much you can pay as a priority fee, or 'tip',\n// to get a transaction included in the current block (EIP-1559).\nfunc (e *Eth) MaxPriorityFeePerGas() (*big.Int, error) {\n\tvar out string\n\tif err := e.c.Call(\"eth_maxPriorityFeePerGas\", &out); err != nil {\n\t\treturn big.NewInt(0), err\n\t}\n\n\treturn parseBigInt(out), nil\n}\n"
  },
  {
    "path": "jsonrpc/eth_test.go",
    "content": "package jsonrpc\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nvar (\n\taddr0 = ethgo.Address{0x1}\n\taddr1 = ethgo.Address{0x2}\n)\n\nfunc TestEthAccounts(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\t_, err := c.Eth().Accounts()\n\t\tassert.NoError(t, err)\n\t})\n}\n\nfunc TestEthBlockNumber(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\tnum, err := c.Eth().BlockNumber()\n\t\trequire.NoError(t, err)\n\n\t\tfor i := 0; i < 10; i++ {\n\t\t\trequire.NoError(t, s.ProcessBlock())\n\n\t\t\t// since it is concurrent, we cannot ensure sequential numbers\n\t\t\tnewNum, err := c.Eth().BlockNumber()\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.Greater(t, newNum, num)\n\n\t\t\tnum = newNum\n\t\t}\n\t})\n}\n\nfunc TestEthGetCode(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tcc := &testutil.Contract{}\n\tcc.AddEvent(testutil.NewEvent(\"A\").\n\t\tAdd(\"address\", true).\n\t\tAdd(\"address\", true))\n\n\tcc.EmitEvent(\"setA1\", \"A\", addr0.String(), addr1.String())\n\tcc.EmitEvent(\"setA2\", \"A\", addr1.String(), addr0.String())\n\n\t_, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tcode, err := c.Eth().GetCode(addr, ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.NotEqual(t, code, \"0x\")\n\n\tcode2, err := c.Eth().GetCode(addr, ethgo.BlockNumber(0))\n\tassert.NoError(t, err)\n\tassert.Equal(t, code2, \"0x\")\n}\n\nfunc TestEthGetBalance(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tbalance, err := c.Eth().GetBalance(s.Account(0), ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.NotEqual(t, balance, big.NewInt(0))\n\n\tbalance, err = c.Eth().GetBalance(ethgo.Address{}, ethgo.Latest)\n\tassert.NoError(t, err)\n\tassert.Equal(t, balance, big.NewInt(0))\n}\n\nfunc TestEthGetBlockByNumber(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tblock, err := c.Eth().GetBlockByNumber(0, true)\n\tassert.NoError(t, err)\n\tassert.Equal(t, block.Number, uint64(0))\n\n\t// query a non-sealed block block 1 has not been processed yet\n\t// it does not fail but returns nil\n\tlatest, err := c.Eth().BlockNumber()\n\trequire.NoError(t, err)\n\n\tblock, err = c.Eth().GetBlockByNumber(ethgo.BlockNumber(latest+10000), true)\n\tassert.NoError(t, err)\n\tassert.Nil(t, block)\n}\n\nfunc TestEthGetBlockByHash(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\t// get block 0 first by number\n\t\tblock, err := c.Eth().GetBlockByNumber(0, true)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, block.Number, uint64(0))\n\n\t\t// get block 0 by hash\n\t\tblock2, err := c.Eth().GetBlockByHash(block.Hash, true)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, block, block2)\n\t})\n}\n\nfunc TestEthGasPrice(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\t_, err := c.Eth().GasPrice()\n\t\tassert.NoError(t, err)\n\t})\n}\n\nfunc TestEthSendTransaction(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\ttxn := &ethgo.Transaction{\n\t\tFrom:     s.Account(0),\n\t\tGasPrice: testutil.DefaultGasPrice,\n\t\tGas:      testutil.DefaultGasLimit,\n\t\tTo:       &testutil.DummyAddr,\n\t\tValue:    big.NewInt(10),\n\t}\n\thash, err := c.Eth().SendTransaction(txn)\n\tassert.NoError(t, err)\n\n\tvar receipt *ethgo.Receipt\n\tfor {\n\t\treceipt, err = c.Eth().GetTransactionReceipt(hash)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif receipt != nil {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc TestEthEstimateGas(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tcc := &testutil.Contract{}\n\tcc.AddEvent(testutil.NewEvent(\"A\").Add(\"address\", true))\n\tcc.EmitEvent(\"setA\", \"A\", addr0.String())\n\n\t// estimate gas to deploy the contract\n\tsolcContract, err := cc.Compile()\n\tassert.NoError(t, err)\n\n\tinput, err := hex.DecodeString(solcContract.Bin)\n\tassert.NoError(t, err)\n\n\tgas, err := c.Eth().EstimateGasContract(input)\n\tassert.NoError(t, err)\n\tassert.Greater(t, gas, uint64(140000))\n\n\t_, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tmsg := &ethgo.CallMsg{\n\t\tFrom: s.Account(0),\n\t\tTo:   &addr,\n\t\tData: testutil.MethodSig(\"setA\"),\n\t}\n\n\tgas, err = c.Eth().EstimateGas(msg)\n\tassert.NoError(t, err)\n\tassert.NotEqual(t, gas, 0)\n}\n\nfunc TestEthGetLogs(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tcc := &testutil.Contract{}\n\tcc.AddEvent(testutil.NewEvent(\"A\").\n\t\tAdd(\"address\", true).\n\t\tAdd(\"address\", true))\n\n\tcc.EmitEvent(\"setA1\", \"A\", addr0.String(), addr1.String())\n\tcc.EmitEvent(\"setA2\", \"A\", addr1.String(), addr0.String())\n\n\t_, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tr, err := s.TxnTo(addr, \"setA2\")\n\trequire.NoError(t, err)\n\n\tfilter := &ethgo.LogFilter{\n\t\tBlockHash: &r.BlockHash,\n\t}\n\tlogs, err := c.Eth().GetLogs(filter)\n\tassert.NoError(t, err)\n\tassert.Len(t, logs, 1)\n\n\tlog := logs[0]\n\tassert.Len(t, log.Topics, 3)\n\tassert.Equal(t, log.Address, addr)\n\n\t// first topic is the signature of the event\n\tassert.Equal(t, log.Topics[0].String(), cc.GetEvent(\"A\").Sig())\n\n\t// topics have 32 bytes and the addr are 20 bytes, then, assert.Equal wont work.\n\t// this is a workaround until we build some helper function to test this better\n\tassert.True(t, bytes.HasSuffix(log.Topics[1][:], addr1[:]))\n\tassert.True(t, bytes.HasSuffix(log.Topics[2][:], addr0[:]))\n}\n\nfunc TestEthChainID(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\tnum, err := c.Eth().ChainID()\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, num.Uint64(), uint64(1337)) // chainid of geth-dev\n\t})\n}\n\nfunc TestEthCall(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\tcc := &testutil.Contract{}\n\n\t// add global variables\n\tcc.AddCallback(func() string {\n\t\treturn \"uint256 val = 1;\"\n\t})\n\n\t// add setter method\n\tcc.AddCallback(func() string {\n\t\treturn `function getValue() public returns (uint256) {\n\t\t\treturn val;\n\t\t}`\n\t})\n\n\t_, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\tinput := abi.MustNewMethod(\"function getValue() public returns (uint256)\").ID()\n\n\tresp, err := c.Eth().Call(&ethgo.CallMsg{To: &addr, Data: input}, ethgo.Latest)\n\trequire.NoError(t, err)\n\n\trequire.Equal(t, \"0x0000000000000000000000000000000000000000000000000000000000000001\", resp)\n\n\tnonce := uint64(1)\n\n\t// override the state\n\toverride := &ethgo.StateOverride{\n\t\taddr: ethgo.OverrideAccount{\n\t\t\tNonce:   &nonce,\n\t\t\tBalance: big.NewInt(1),\n\t\t\tStateDiff: &map[ethgo.Hash]ethgo.Hash{\n\t\t\t\t// storage slot 0 stores the 'val' uint256 value\n\t\t\t\t{0x0}: {0x3},\n\t\t\t},\n\t\t},\n\t}\n\n\tresp, err = c.Eth().Call(&ethgo.CallMsg{To: &addr, Data: input}, ethgo.Latest, override)\n\trequire.NoError(t, err)\n\n\trequire.Equal(t, \"0x0300000000000000000000000000000000000000000000000000000000000000\", resp)\n}\n\nfunc TestEthGetNonce(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\treceipt, err := s.ProcessBlockWithReceipt()\n\tassert.NoError(t, err)\n\n\t// query the balance with different options\n\tcases := []ethgo.BlockNumberOrHash{\n\t\tethgo.Latest,\n\t\treceipt.BlockHash,\n\t\tethgo.BlockNumber(receipt.BlockNumber),\n\t}\n\tfor _, ca := range cases {\n\t\tnum, err := c.Eth().GetNonce(s.Account(0), ca)\n\t\tassert.NoError(t, err)\n\t\tassert.NotEqual(t, num, uint64(0))\n\t}\n}\n\nfunc TestEthTransactionsInBlock(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\t// block 0 does not have transactions\n\t_, err := c.Eth().GetBlockByNumber(0, false)\n\tassert.NoError(t, err)\n\n\t// Process a block with a transaction\n\tassert.NoError(t, s.ProcessBlock())\n\n\tlatest, err := c.Eth().BlockNumber()\n\trequire.NoError(t, err)\n\n\tnum := ethgo.BlockNumber(latest)\n\n\t// get a non-full block\n\tblock0, err := c.Eth().GetBlockByNumber(num, false)\n\tassert.NoError(t, err)\n\n\tassert.NotEmpty(t, block0.TransactionsHashes, 1)\n\tassert.Empty(t, block0.Transactions, 0)\n\n\t// get a full block\n\tblock1, err := c.Eth().GetBlockByNumber(num, true)\n\tassert.NoError(t, err)\n\n\tassert.Empty(t, block1.TransactionsHashes, 0)\n\tassert.NotEmpty(t, block1.Transactions, 1)\n\n\tfor indx := range block0.TransactionsHashes {\n\t\tassert.Equal(t, block0.TransactionsHashes[indx], block1.Transactions[indx].Hash)\n\t}\n}\n\nfunc TestEthGetStorageAt(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tc, _ := NewClient(s.HTTPAddr())\n\n\tcc := &testutil.Contract{}\n\n\t// add global variables\n\tcc.AddCallback(func() string {\n\t\treturn \"uint256 val;\"\n\t})\n\n\t// add setter method\n\tcc.AddCallback(func() string {\n\t\treturn `function setValue() public payable {\n\t\t\tval = 10;\n\t\t}`\n\t})\n\n\t_, addr, err := s.DeployContract(cc)\n\trequire.NoError(t, err)\n\n\treceipt, err := s.TxnTo(addr, \"setValue\")\n\trequire.NoError(t, err)\n\n\tcases := []ethgo.BlockNumberOrHash{\n\t\tethgo.Latest,\n\t\treceipt.BlockHash,\n\t\tethgo.BlockNumber(receipt.BlockNumber),\n\t}\n\tfor _, ca := range cases {\n\t\tres, err := c.Eth().GetStorageAt(addr, ethgo.Hash{}, ca)\n\t\tassert.NoError(t, err)\n\t\tassert.True(t, strings.HasSuffix(res.String(), \"a\"))\n\t}\n}\n\nfunc TestEthFeeHistory(t *testing.T) {\n\tc, _ := NewClient(testutil.TestInfuraEndpoint(t))\n\n\tlastBlock, err := c.Eth().BlockNumber()\n\tassert.NoError(t, err)\n\n\tfee, err := c.Eth().FeeHistory(1, ethgo.BlockNumber(lastBlock), []float64{25, 75})\n\tassert.NoError(t, err)\n\tassert.NotNil(t, fee)\n}\n\nfunc TestEthMaxPriorityFeePerGas(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\tc, err := NewClient(s.HTTPAddr())\n\trequire.NoError(t, err)\n\n\tinitialMaxPriorityFee, err := c.Eth().MaxPriorityFeePerGas()\n\trequire.NoError(t, err)\n\n\t// wait for 2 blocks\n\trequire.NoError(t, s.ProcessBlock())\n\trequire.NoError(t, s.ProcessBlock())\n\n\ttxn := &ethgo.Transaction{\n\t\tTo:                   &testutil.DummyAddr,\n\t\tValue:                ethgo.Gwei(1),\n\t\tType:                 ethgo.TransactionDynamicFee,\n\t\tMaxPriorityFeePerGas: ethgo.Gwei(1),\n\t}\n\n\tlatestBlock, err := c.Eth().BlockNumber()\n\trequire.NoError(t, err)\n\n\tfeeHistory, err := c.Eth().FeeHistory(1, ethgo.BlockNumber(latestBlock), nil)\n\trequire.NoError(t, err)\n\n\tlatestBaseFee := feeHistory.BaseFee[len(feeHistory.BaseFee)-1]\n\ttxn.MaxFeePerGas = new(big.Int).Add(latestBaseFee, txn.MaxPriorityFeePerGas)\n\n\treceipt, err := s.SendTxn(txn)\n\trequire.NoError(t, err)\n\trequire.Equal(t, uint64(1), receipt.Status)\n\n\tnewMaxPriorityFee, err := c.Eth().MaxPriorityFeePerGas()\n\tt.Log(initialMaxPriorityFee)\n\tt.Log(newMaxPriorityFee)\n\trequire.NoError(t, err)\n\trequire.True(t, initialMaxPriorityFee.Cmp(newMaxPriorityFee) <= 0)\n}\n"
  },
  {
    "path": "jsonrpc/net.go",
    "content": "package jsonrpc\n\n// Net is the net namespace\ntype Net struct {\n\tc *Client\n}\n\n// Net returns the reference to the net namespace\nfunc (c *Client) Net() *Net {\n\treturn c.endpoints.n\n}\n\n// Version returns the current network id\nfunc (n *Net) Version() (uint64, error) {\n\tvar out string\n\tif err := n.c.Call(\"net_version\", &out); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n\n// Listening returns true if client is actively listening for network connections\nfunc (n *Net) Listening() (bool, error) {\n\tvar out bool\n\terr := n.c.Call(\"net_listening\", &out)\n\treturn out, err\n}\n\n// PeerCount returns number of peers currently connected to the client\nfunc (n *Net) PeerCount() (uint64, error) {\n\tvar out string\n\tif err := n.c.Call(\"net_peerCount\", &out); err != nil {\n\t\treturn 0, err\n\t}\n\treturn parseUint64orHex(out)\n}\n"
  },
  {
    "path": "jsonrpc/net_test.go",
    "content": "package jsonrpc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc TestNetVersion(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\t_, err := c.Net().Version()\n\t\tassert.NoError(t, err)\n\t})\n}\n\nfunc TestNetListening(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\tok, err := c.Net().Listening()\n\t\tassert.NoError(t, err)\n\t\tassert.True(t, ok)\n\t})\n}\n\nfunc TestNetPeerCount(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\tcount, err := c.Net().PeerCount()\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, count, uint64(0))\n\t})\n}\n"
  },
  {
    "path": "jsonrpc/subscribe.go",
    "content": "package jsonrpc\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/jsonrpc/transport\"\n)\n\n// SubscriptionEnabled returns true if the subscription endpoints are enabled\nfunc (c *Client) SubscriptionEnabled() bool {\n\t_, ok := c.transport.(transport.PubSubTransport)\n\treturn ok\n}\n\n// Subscribe starts a new subscription\nfunc (c *Client) Subscribe(method string, callback func(b []byte)) (func() error, error) {\n\tpub, ok := c.transport.(transport.PubSubTransport)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"transport does not support the subscribe method\")\n\t}\n\tclose, err := pub.Subscribe(method, callback)\n\treturn close, err\n}\n"
  },
  {
    "path": "jsonrpc/subscribe_test.go",
    "content": "package jsonrpc\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc TestSubscribeNewHead(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tif strings.HasPrefix(addr, \"http\") {\n\t\t\treturn\n\t\t}\n\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\tdata := make(chan []byte)\n\t\tcancel, err := c.Subscribe(\"newHeads\", func(b []byte) {\n\t\t\tdata <- b\n\t\t})\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tvar lastBlock *ethgo.Block\n\t\trecv := func(ok bool) {\n\t\t\tselect {\n\t\t\tcase buf := <-data:\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Fatal(\"unexpected value\")\n\t\t\t\t}\n\n\t\t\t\tvar block ethgo.Block\n\t\t\t\tif err := block.UnmarshalJSON(buf); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif lastBlock != nil {\n\t\t\t\t\tif lastBlock.Number+1 != block.Number {\n\t\t\t\t\t\tt.Fatalf(\"bad sequence %d %d\", lastBlock.Number, block.Number)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastBlock = &block\n\n\t\t\tcase <-time.After(1 * time.Second):\n\t\t\t\tif ok {\n\t\t\t\t\tt.Fatal(\"timeout for new head\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.ProcessBlock()\n\t\trecv(true)\n\n\t\ts.ProcessBlock()\n\t\trecv(true)\n\n\t\tassert.NoError(t, cancel())\n\n\t\ts.ProcessBlock()\n\t\trecv(false)\n\n\t\t// subscription already closed\n\t\tassert.Error(t, cancel())\n\t})\n}\n"
  },
  {
    "path": "jsonrpc/transport/http.go",
    "content": "package transport\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/jsonrpc/codec\"\n\t\"github.com/valyala/fasthttp\"\n)\n\n// HTTP is an http transport\ntype HTTP struct {\n\taddr    string\n\tclient  *fasthttp.Client\n\theaders map[string]string\n}\n\nfunc newHTTP(addr string, headers map[string]string) *HTTP {\n\treturn &HTTP{\n\t\taddr: addr,\n\t\tclient: &fasthttp.Client{\n\t\t\tDialDualStack: true,\n\t\t},\n\t\theaders: headers,\n\t}\n}\n\n// Close implements the transport interface\nfunc (h *HTTP) Close() error {\n\treturn nil\n}\n\n// Call implements the transport interface\nfunc (h *HTTP) Call(method string, out interface{}, params ...interface{}) error {\n\t// Encode json-rpc request\n\trequest := codec.Request{\n\t\tJsonRPC: \"2.0\",\n\t\tMethod:  method,\n\t}\n\tif len(params) > 0 {\n\t\tdata, err := json.Marshal(params)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trequest.Params = data\n\t} else {\n\t\trequest.Params = []byte{'[', ']'}\n\t}\n\traw, err := json.Marshal(request)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treq := fasthttp.AcquireRequest()\n\tres := fasthttp.AcquireResponse()\n\n\tdefer fasthttp.ReleaseRequest(req)\n\tdefer fasthttp.ReleaseResponse(res)\n\n\treq.SetRequestURI(h.addr)\n\treq.Header.SetMethod(\"POST\")\n\treq.Header.SetContentType(\"application/json\")\n\tfor k, v := range h.headers {\n\t\treq.Header.Add(k, v)\n\t}\n\treq.SetBody(raw)\n\n\tif err := h.client.Do(req, res); err != nil {\n\t\treturn err\n\t}\n\n\tif sc := res.StatusCode(); sc != fasthttp.StatusOK {\n\t\treturn fmt.Errorf(\"status code is %d. response = %s\", sc, string(res.Body()))\n\t}\n\n\t// Decode json-rpc response\n\tvar response codec.Response\n\tif err := json.Unmarshal(res.Body(), &response); err != nil {\n\t\treturn err\n\t}\n\tif response.Error != nil {\n\t\treturn response.Error\n\t}\n\n\tif err := json.Unmarshal(response.Result, out); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// SetMaxConnsPerHost sets the maximum number of connections that can be established with a host\nfunc (h *HTTP) SetMaxConnsPerHost(count int) {\n\th.client.MaxConnsPerHost = count\n}\n"
  },
  {
    "path": "jsonrpc/transport/ipc.go",
    "content": "package transport\n\nimport (\n\t\"encoding/json\"\n\t\"net\"\n)\n\nfunc newIPC(addr string) (Transport, error) {\n\tconn, err := net.Dial(\"unix\", addr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcodec := &ipcCodec{\n\t\tbuf:  json.RawMessage{},\n\t\tconn: conn,\n\t\tdec:  json.NewDecoder(conn),\n\t}\n\n\treturn newStream(codec)\n}\n\ntype ipcCodec struct {\n\tbuf  json.RawMessage\n\tconn net.Conn\n\tdec  *json.Decoder\n}\n\nfunc (i *ipcCodec) Close() error {\n\treturn i.conn.Close()\n}\n\nfunc (i *ipcCodec) Read(b []byte) ([]byte, error) {\n\ti.buf = i.buf[:0]\n\tif err := i.dec.Decode(&i.buf); err != nil {\n\t\treturn nil, err\n\t}\n\tb = append(b, i.buf...)\n\treturn b, nil\n}\n\nfunc (i *ipcCodec) Write(b []byte) error {\n\t_, err := i.conn.Write(b)\n\treturn err\n}\n"
  },
  {
    "path": "jsonrpc/transport/transport.go",
    "content": "package transport\n\nimport (\n\t\"os\"\n\t\"strings\"\n)\n\n// Transport is an inteface for transport methods to send jsonrpc requests\ntype Transport interface {\n\t// Call makes a jsonrpc request\n\tCall(method string, out interface{}, params ...interface{}) error\n\n\t// SetMaxConnsPerHost sets the maximum number of connections that can be established with a host\n\tSetMaxConnsPerHost(count int)\n\n\t// Close closes the transport connection if necessary\n\tClose() error\n}\n\n// PubSubTransport is a transport that allows subscriptions\ntype PubSubTransport interface {\n\t// Subscribe starts a subscription to a new event\n\tSubscribe(method string, callback func(b []byte)) (func() error, error)\n}\n\nconst (\n\twsPrefix  = \"ws://\"\n\twssPrefix = \"wss://\"\n)\n\n// NewTransport creates a new transport object\nfunc NewTransport(url string, headers map[string]string) (Transport, error) {\n\tif strings.HasPrefix(url, wsPrefix) || strings.HasPrefix(url, wssPrefix) {\n\t\tt, err := newWebsocket(url, headers)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn t, nil\n\t}\n\tif _, err := os.Stat(url); err == nil {\n\t\t// path exists, it could be an ipc path\n\t\tt, err := newIPC(url)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn t, nil\n\t}\n\treturn newHTTP(url, headers), nil\n}\n"
  },
  {
    "path": "jsonrpc/transport/websocket.go",
    "content": "package transport\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/gorilla/websocket\"\n\t\"github.com/umbracle/ethgo/jsonrpc/codec\"\n)\n\nfunc newWebsocket(url string, headers map[string]string) (Transport, error) {\n\twsHeaders := http.Header{}\n\tfor k, v := range headers {\n\t\twsHeaders.Add(k, v)\n\t}\n\twsConn, _, err := websocket.DefaultDialer.Dial(url, wsHeaders)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcodec := &websocketCodec{\n\t\tconn: wsConn,\n\t}\n\treturn newStream(codec)\n}\n\n// ErrTimeout happens when the websocket requests times out\nvar ErrTimeout = fmt.Errorf(\"ws timeout\")\n\ntype ackMessage struct {\n\tbuf []byte\n\terr error\n}\n\ntype callback func(b []byte, err error)\n\ntype stream struct {\n\tseq   uint64\n\tcodec Codec\n\n\t// call handlers\n\thandlerLock sync.Mutex\n\thandler     map[uint64]callback\n\n\t// subscriptions\n\tsubsLock sync.Mutex\n\tsubs     map[string]func(b []byte)\n\n\tcloseCh chan struct{}\n\ttimer   *time.Timer\n}\n\nfunc newStream(codec Codec) (*stream, error) {\n\tw := &stream{\n\t\tcodec:   codec,\n\t\tcloseCh: make(chan struct{}),\n\t\thandler: map[uint64]callback{},\n\t\tsubs:    map[string]func(b []byte){},\n\t}\n\n\tgo w.listen()\n\treturn w, nil\n}\n\n// Close implements the the transport interface\nfunc (s *stream) Close() error {\n\tclose(s.closeCh)\n\treturn s.codec.Close()\n}\n\nfunc (s *stream) incSeq() uint64 {\n\treturn atomic.AddUint64(&s.seq, 1)\n}\n\nfunc (s *stream) isClosed() bool {\n\tselect {\n\tcase <-s.closeCh:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (s *stream) listen() {\n\tbuf := []byte{}\n\n\tfor {\n\t\tvar err error\n\t\tbuf, err = s.codec.Read(buf[:0])\n\t\tif err != nil {\n\t\t\tif !s.isClosed() {\n\t\t\t\t// log error\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tvar resp codec.Response\n\t\tif err = json.Unmarshal(buf, &resp); err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tif resp.ID != 0 {\n\t\t\tgo s.handleMsg(resp)\n\t\t} else {\n\t\t\t// handle subscription\n\t\t\tvar respSub codec.Request\n\t\t\tif err = json.Unmarshal(buf, &respSub); err != nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif respSub.Method == \"eth_subscription\" {\n\t\t\t\tgo s.handleSubscription(respSub)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (s *stream) handleSubscription(response codec.Request) {\n\tvar sub codec.Subscription\n\tif err := json.Unmarshal(response.Params, &sub); err != nil {\n\t\tpanic(err)\n\t}\n\n\ts.subsLock.Lock()\n\tcallback, ok := s.subs[sub.ID]\n\ts.subsLock.Unlock()\n\n\tif !ok {\n\t\treturn\n\t}\n\n\t// call the callback function\n\tcallback(sub.Result)\n}\n\nfunc (s *stream) handleMsg(response codec.Response) {\n\ts.handlerLock.Lock()\n\tcallback, ok := s.handler[response.ID]\n\tif !ok {\n\t\ts.handlerLock.Unlock()\n\t\treturn\n\t}\n\n\t// delete handler\n\tdelete(s.handler, response.ID)\n\ts.handlerLock.Unlock()\n\n\tif response.Error != nil {\n\t\tcallback(nil, response.Error)\n\t} else {\n\t\tcallback(response.Result, nil)\n\t}\n}\n\nfunc (s *stream) setHandler(id uint64, ack chan *ackMessage) {\n\tcallback := func(b []byte, err error) {\n\t\tselect {\n\t\tcase ack <- &ackMessage{b, err}:\n\t\tdefault:\n\t\t}\n\t}\n\n\ts.handlerLock.Lock()\n\ts.handler[id] = callback\n\ts.handlerLock.Unlock()\n\n\ts.timer = time.AfterFunc(15*time.Second, func() {\n\t\ts.handlerLock.Lock()\n\t\tdelete(s.handler, id)\n\t\ts.handlerLock.Unlock()\n\n\t\tselect {\n\t\tcase ack <- &ackMessage{nil, ErrTimeout}:\n\t\tdefault:\n\t\t}\n\t})\n}\n\n// Call implements the transport interface\nfunc (s *stream) Call(method string, out interface{}, params ...interface{}) error {\n\tseq := s.incSeq()\n\trequest := codec.Request{\n\t\tJsonRPC: \"2.0\",\n\t\tID:      seq,\n\t\tMethod:  method,\n\t}\n\tif len(params) > 0 {\n\t\tdata, err := json.Marshal(params)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trequest.Params = data\n\t}\n\n\tack := make(chan *ackMessage)\n\ts.setHandler(seq, ack)\n\n\traw, err := json.Marshal(request)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := s.codec.Write(raw); err != nil {\n\t\treturn err\n\t}\n\n\tresp := <-ack\n\tif resp.err != nil {\n\t\treturn resp.err\n\t}\n\tif err := json.Unmarshal(resp.buf, out); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (s *stream) unsubscribe(id string) error {\n\ts.subsLock.Lock()\n\tdefer s.subsLock.Unlock()\n\n\tif _, ok := s.subs[id]; !ok {\n\t\treturn fmt.Errorf(\"subscription %s not found\", id)\n\t}\n\tdelete(s.subs, id)\n\n\tvar result bool\n\tif err := s.Call(\"eth_unsubscribe\", &result, id); err != nil {\n\t\treturn err\n\t}\n\tif !result {\n\t\treturn fmt.Errorf(\"failed to unsubscribe\")\n\t}\n\treturn nil\n}\n\nfunc (s *stream) setSubscription(id string, callback func(b []byte)) {\n\ts.subsLock.Lock()\n\tdefer s.subsLock.Unlock()\n\n\ts.subs[id] = callback\n}\n\n// Subscribe implements the PubSubTransport interface\nfunc (s *stream) Subscribe(method string, callback func(b []byte)) (func() error, error) {\n\tvar out string\n\tif err := s.Call(\"eth_subscribe\", &out, method); err != nil {\n\t\treturn nil, err\n\t}\n\n\ts.setSubscription(out, callback)\n\tcancel := func() error {\n\t\treturn s.unsubscribe(out)\n\t}\n\treturn cancel, nil\n}\n\n// SetMaxConnsPerHost implements the transport interface\nfunc (s *stream) SetMaxConnsPerHost(count int) {\n}\n\ntype websocketCodec struct {\n\tconn *websocket.Conn\n}\n\nfunc (w *websocketCodec) Close() error {\n\treturn w.conn.Close()\n}\n\nfunc (w *websocketCodec) Write(b []byte) error {\n\treturn w.conn.WriteMessage(websocket.TextMessage, b)\n}\n\nfunc (w *websocketCodec) Read(b []byte) ([]byte, error) {\n\t_, buf, err := w.conn.ReadMessage()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tb = append(b, buf...)\n\treturn b, nil\n}\n\n// Codec is the codec to write and read messages\ntype Codec interface {\n\tRead([]byte) ([]byte, error)\n\tWrite([]byte) error\n\tClose() error\n}\n"
  },
  {
    "path": "jsonrpc/util.go",
    "content": "package jsonrpc\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype ArgBig big.Int\n\nfunc (a *ArgBig) UnmarshalText(input []byte) error {\n\tbuf, err := parseHexBytes(string(input))\n\tif err != nil {\n\t\treturn err\n\t}\n\tb := new(big.Int)\n\tb.SetBytes(buf)\n\t*a = ArgBig(*b)\n\treturn nil\n}\n\nfunc (a *ArgBig) Big() *big.Int {\n\tb := big.Int(*a)\n\treturn &b\n}\n\nfunc encodeUintToHex(i uint64) string {\n\treturn fmt.Sprintf(\"0x%x\", i)\n}\n\nfunc parseBigInt(str string) *big.Int {\n\tstr = strings.TrimPrefix(str, \"0x\")\n\tnum := new(big.Int)\n\tnum.SetString(str, 16)\n\treturn num\n}\n\nfunc parseUint64orHex(str string) (uint64, error) {\n\tbase := 10\n\tif strings.HasPrefix(str, \"0x\") {\n\t\tstr = str[2:]\n\t\tbase = 16\n\t}\n\treturn strconv.ParseUint(str, base, 64)\n}\n\nfunc encodeToHex(b []byte) string {\n\treturn \"0x\" + hex.EncodeToString(b)\n}\n\nfunc parseHexBytes(str string) ([]byte, error) {\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn nil, fmt.Errorf(\"it does not have 0x prefix\")\n\t}\n\tstr = strings.TrimPrefix(str, \"0x\")\n\tif len(str)%2 != 0 {\n\t\tstr = \"0\" + str\n\t}\n\tbuf, err := hex.DecodeString(str)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn buf, nil\n}\n"
  },
  {
    "path": "jsonrpc/web3.go",
    "content": "package jsonrpc\n\n// Web3 is the web3 namespace\ntype Web3 struct {\n\tc *Client\n}\n\n// Web3 returns the reference to the web3 namespace\nfunc (c *Client) Web3() *Web3 {\n\treturn c.endpoints.w\n}\n\n// ClientVersion returns the current client version\nfunc (w *Web3) ClientVersion() (string, error) {\n\tvar out string\n\terr := w.c.Call(\"web3_clientVersion\", &out)\n\treturn out, err\n}\n\n// Sha3 returns Keccak-256 (not the standardized SHA3-256) of the given data\nfunc (w *Web3) Sha3(val []byte) ([]byte, error) {\n\tvar out string\n\tif err := w.c.Call(\"web3_sha3\", &out, encodeToHex(val)); err != nil {\n\t\treturn nil, err\n\t}\n\treturn parseHexBytes(out)\n}\n"
  },
  {
    "path": "jsonrpc/web3_test.go",
    "content": "package jsonrpc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo/testutil\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\nfunc TestWeb3ClientVersion(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\t_, err := c.Web3().ClientVersion()\n\t\tassert.NoError(t, err)\n\t})\n}\n\nfunc TestWeb3Sha3(t *testing.T) {\n\ttestutil.MultiAddr(t, func(s *testutil.TestServer, addr string) {\n\t\tc, _ := NewClient(addr)\n\t\tdefer c.Close()\n\n\t\tsrc := []byte{0x1, 0x2, 0x3}\n\n\t\tfound, err := c.Web3().Sha3(src)\n\t\tassert.NoError(t, err)\n\n\t\tk := sha3.NewLegacyKeccak256()\n\t\tk.Write(src)\n\t\texpected := k.Sum(nil)\n\n\t\tassert.Equal(t, expected, found)\n\t})\n}\n"
  },
  {
    "path": "keccak.go",
    "content": "package ethgo\n\nimport \"golang.org/x/crypto/sha3\"\n\n// Keccak256 calculates the Keccak256\nfunc Keccak256(v ...[]byte) []byte {\n\th := sha3.NewLegacyKeccak256()\n\tfor _, i := range v {\n\t\th.Write(i)\n\t}\n\treturn h.Sum(nil)\n}\n"
  },
  {
    "path": "keystore/utils.go",
    "content": "package keystore\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/crypto/pbkdf2\"\n\t\"golang.org/x/crypto/scrypt\"\n)\n\nfunc getRand(size int) []byte {\n\tbuf := make([]byte, size)\n\trand.Read(buf)\n\treturn buf\n}\n\ntype hexString []byte\n\nfunc (h hexString) MarshalJSON() ([]byte, error) {\n\tstr := \"\\\"\" + hex.EncodeToString(h) + \"\\\"\"\n\treturn []byte(str), nil\n}\n\nfunc (h *hexString) UnmarshalJSON(data []byte) error {\n\traw := string(data)\n\traw = strings.Trim(raw, \"\\\"\")\n\n\tdata, err := hex.DecodeString(raw)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*h = data\n\treturn nil\n}\n\nfunc aesCTR(key, cipherText, iv []byte) ([]byte, error) {\n\tblock, err := aes.NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstream := cipher.NewCTR(block, iv)\n\n\tdst := make([]byte, len(cipherText))\n\tstream.XORKeyStream(dst, cipherText)\n\n\treturn dst, nil\n}\n\ntype pbkdf2Params struct {\n\tDklen int       `json:\"dklen\"`\n\tSalt  hexString `json:\"salt\"`\n\tC     int       `json:\"c\"`\n\tPrf   string    `json:\"prf\"`\n}\n\nfunc (p *pbkdf2Params) Key(password []byte) []byte {\n\treturn pbkdf2.Key(password, p.Salt, p.C, p.Dklen, sha256.New)\n}\n\ntype scryptParams struct {\n\tDklen int       `json:\"dklen\"`\n\tSalt  hexString `json:\"salt\"`\n\tN     int       `json:\"n\"`\n\tP     int       `json:\"p\"`\n\tR     int       `json:\"r\"`\n}\n\nfunc (s *scryptParams) Key(password []byte) ([]byte, error) {\n\treturn scrypt.Key(password, s.Salt, s.N, s.R, s.P, s.Dklen)\n}\n\nfunc applyKdf(fn string, password, paramsRaw []byte) ([]byte, error) {\n\tvar key []byte\n\n\tif fn == \"pbkdf2\" {\n\t\tvar params pbkdf2Params\n\t\tif err := json.Unmarshal(paramsRaw, &params); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif params.Prf != \"hmac-sha256\" {\n\t\t\treturn nil, fmt.Errorf(\"not found\")\n\t\t}\n\t\tkey = params.Key(password)\n\t} else if fn == \"scrypt\" {\n\t\tvar params scryptParams\n\t\terr := json.Unmarshal(paramsRaw, &params)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tkey, err = params.Key(password)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\treturn nil, fmt.Errorf(\"kdf '%s' not supported\", fn)\n\t}\n\treturn key, nil\n}\n"
  },
  {
    "path": "keystore/v3.go",
    "content": "package keystore\n\nimport (\n\t\"bytes\"\n\t\"crypto/aes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// EncryptV3 encrypts data in v3 format\nfunc EncryptV3(content []byte, password string, customScrypt ...int) ([]byte, error) {\n\n\t// default scrypt values\n\tscryptN, scryptP := 1<<18, 1\n\n\tif len(customScrypt) >= 1 {\n\t\tscryptN = customScrypt[0]\n\t}\n\tif len(customScrypt) >= 2 {\n\t\tscryptP = customScrypt[1]\n\t}\n\n\tiv := getRand(aes.BlockSize)\n\n\tscrypt := scryptParams{\n\t\tN:     scryptN,\n\t\tR:     8,\n\t\tP:     scryptP,\n\t\tDklen: 32,\n\t\tSalt:  hexString(getRand(32)),\n\t}\n\tkdf, err := scrypt.Key([]byte(password))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcipherText, err := aesCTR(kdf[:16], content, iv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// generate mac\n\tmac := ethgo.Keccak256(kdf[16:32], cipherText)\n\n\tv3 := &v3Encoding{\n\t\tVersion: 3,\n\t\tCrypto: &cryptoEncoding{\n\t\t\tCipher:     \"aes-128-ctr\",\n\t\t\tCipherText: hexString(cipherText),\n\t\t\tCipherParams: struct{ IV hexString }{\n\t\t\t\tIV: hexString(iv),\n\t\t\t},\n\t\t\tKDF:       \"scrypt\",\n\t\t\tKDFParams: scrypt,\n\t\t\tMac:       hexString(mac),\n\t\t},\n\t}\n\n\tencrypted, err := v3.Marshal()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn encrypted, nil\n}\n\n// DecryptV3 decodes bytes in the v3 keystore format\nfunc DecryptV3(content []byte, password string) ([]byte, error) {\n\tencoding := v3Encoding{}\n\tif err := encoding.Unmarshal(content); err != nil {\n\t\treturn nil, err\n\t}\n\tif encoding.Version != 3 {\n\t\treturn nil, fmt.Errorf(\"only version 3 supported\")\n\t}\n\tif encoding.Crypto.Cipher != \"aes-128-ctr\" {\n\t\treturn nil, fmt.Errorf(\"cipher %s not supported\", encoding.Crypto.Cipher)\n\t}\n\n\t// decode the kdf\n\tkdf, err := applyKdf(encoding.Crypto.KDF, []byte(password), encoding.Crypto.KDFParamsRaw)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// validate mac\n\tmac := ethgo.Keccak256(kdf[16:32], encoding.Crypto.CipherText)\n\tif !bytes.Equal(mac, encoding.Crypto.Mac) {\n\t\treturn nil, fmt.Errorf(\"incorrect mac\")\n\t}\n\n\tdst, err := aesCTR(kdf[:16], encoding.Crypto.CipherText, encoding.Crypto.CipherParams.IV)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn dst, nil\n}\n\ntype v3Encoding struct {\n\tID      string          `json:\"id\"`\n\tVersion int64           `json:\"version\"`\n\tCrypto  *cryptoEncoding `json:\"crypto\"`\n}\n\nfunc (j *v3Encoding) Marshal() ([]byte, error) {\n\tparams, err := json.Marshal(j.Crypto.KDFParams)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tj.Crypto.KDFParamsRaw = json.RawMessage(params)\n\treturn json.Marshal(j)\n}\n\nfunc (j *v3Encoding) Unmarshal(data []byte) error {\n\treturn json.Unmarshal(data, j)\n}\n\ntype cryptoEncoding struct {\n\tCipher       string `json:\"cipher\"`\n\tCipherParams struct {\n\t\tIV hexString\n\t} `json:\"cipherparams\"`\n\tCipherText   hexString `json:\"ciphertext\"`\n\tKDF          string    `json:\"kdf\"`\n\tKDFParams    interface{}\n\tKDFParamsRaw json.RawMessage `json:\"kdfparams\"`\n\tMac          hexString       `json:\"mac\"`\n}\n"
  },
  {
    "path": "keystore/v3_test.go",
    "content": "package keystore\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestV3_EncodeDecode(t *testing.T) {\n\tdata := []byte{0x1, 0x2}\n\tpassword := \"abcd\"\n\n\tencrypted, err := EncryptV3(data, password)\n\tassert.NoError(t, err)\n\n\tfound, err := DecryptV3(encrypted, password)\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, data, found)\n}\n"
  },
  {
    "path": "keystore/v4.go",
    "content": "package keystore\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/text/unicode/norm\"\n)\n\nfunc EncryptV4(content []byte, password string) ([]byte, error) {\n\tpassword = normalizePassword(password)\n\n\t// decryption key\n\tscrypt := scryptParams{\n\t\tN:     1 << 18,\n\t\tR:     8,\n\t\tP:     1,\n\t\tDklen: 32,\n\t\tSalt:  hexString(getRand(32)),\n\t}\n\tkey, err := scrypt.Key([]byte(password))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// decrypt\n\tiv := getRand(16)\n\tcipherText, err := aesCTR(key[:16], content, iv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// checksum\n\thash := sha256.New()\n\thash.Write(key[16:32])\n\thash.Write(cipherText)\n\n\tchecksum := hash.Sum(nil)\n\n\tkdfParams, err := json.Marshal(scrypt)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcipherParams, err := json.Marshal(&cipherParams{Iv: hexString(iv)})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tencoding := &v4Encoding{\n\t\tVersion: 4,\n\t\tCrypto: &v4crypto{\n\t\t\tKdf: &v4Module{\n\t\t\t\tFunction: \"scrypt\",\n\t\t\t\tParams:   kdfParams,\n\t\t\t},\n\t\t\tCipher: &v4Module{\n\t\t\t\tFunction: \"aes-128-ctr\",\n\t\t\t\tParams:   cipherParams,\n\t\t\t\tMessage:  hexString(cipherText),\n\t\t\t},\n\t\t\tChecksum: &v4Module{\n\t\t\t\tFunction: \"sha256\",\n\t\t\t\tMessage:  hexString(checksum),\n\t\t\t},\n\t\t},\n\t}\n\treturn encoding.Marshal()\n}\n\ntype cipherParams struct {\n\tIv hexString `json:\"iv\"`\n}\n\nfunc DecryptV4(content []byte, password string) ([]byte, error) {\n\tencoding := v4Encoding{}\n\tif err := encoding.Unmarshal(content); err != nil {\n\t\treturn nil, err\n\t}\n\tif encoding.Version != 4 {\n\t\treturn nil, fmt.Errorf(\"only version 4 supported\")\n\t}\n\n\tpassword = normalizePassword(password)\n\n\t// decryption key\n\tkey, err := applyKdf(encoding.Crypto.Kdf.Function, []byte(password), encoding.Crypto.Kdf.Params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// checksum\n\thash := sha256.New()\n\thash.Write(key[16:32])\n\thash.Write(encoding.Crypto.Cipher.Message)\n\n\tchecksum := hash.Sum(nil)\n\tif !bytes.Equal(checksum, encoding.Crypto.Checksum.Message) {\n\t\treturn nil, fmt.Errorf(\"bad checksum\")\n\t}\n\n\t// decrypt\n\tvar msg []byte\n\tif encoding.Crypto.Cipher.Function == \"aes-128-ctr\" {\n\t\tvar params cipherParams\n\t\tif err := json.Unmarshal(encoding.Crypto.Cipher.Params, &params); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tres, err := aesCTR(key[:16], encoding.Crypto.Cipher.Message, params.Iv)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tmsg = res\n\t} else {\n\t\treturn nil, fmt.Errorf(\"cipher '%s' not supported\", encoding.Crypto.Cipher.Function)\n\t}\n\treturn msg, nil\n}\n\ntype v4Encoding struct {\n\tCrypto      *v4crypto `json:\"crypto\"`\n\tDescription string    `json:\"description\"`\n\tPubKey      hexString `json:\"pubkey\"`\n\tPath        string    `json:\"path\"`\n\tVersion     int       `json:\"version\"`\n\tUuid        string    `json:\"uuid\"`\n}\n\nfunc (j *v4Encoding) Marshal() ([]byte, error) {\n\treturn json.Marshal(j)\n}\n\nfunc (j *v4Encoding) Unmarshal(data []byte) error {\n\treturn json.Unmarshal(data, j)\n}\n\ntype v4crypto struct {\n\tKdf      *v4Module `json:\"kdf\"`\n\tChecksum *v4Module `json:\"checksum\"`\n\tCipher   *v4Module `json:\"cipher\"`\n}\n\ntype v4Module struct {\n\tFunction string          `json:\"function\"`\n\tParams   json.RawMessage `json:\"params\"`\n\tMessage  hexString       `json:\"message\"`\n}\n\n// normalizePassword normalizes the password following the next rules\n// https://eips.ethereum.org/EIPS/eip-2335#password-requirements\nfunc normalizePassword(password string) string {\n\tstr := norm.NFKD.String(password)\n\n\tskip := func(i byte) bool {\n\t\t// skip runes in the range 0x00 - 0x1F, 0x80 - 0x9F and 0x7F\n\t\tif i == 0x7F {\n\t\t\treturn true\n\t\t}\n\t\tif 0x00 <= i && i <= 0x1F {\n\t\t\treturn true\n\t\t}\n\t\tif 0x80 <= i && i <= 0x9F {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\tnormalized := strings.Builder{}\n\tfor _, r := range str {\n\t\telem := string(r)\n\t\tif len(elem) == 1 {\n\t\t\tif skip(elem[0]) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tnormalized.WriteRune(r)\n\t}\n\treturn normalized.String()\n}\n"
  },
  {
    "path": "keystore/v4_test.go",
    "content": "package keystore\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestV4_EncodeDecode(t *testing.T) {\n\tdata := []byte{0x1, 0x2}\n\tpassword := \"abcd\"\n\n\tencrypted, err := EncryptV4(data, password)\n\tassert.NoError(t, err)\n\n\tfound, err := DecryptV4(encrypted, password)\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, data, found)\n}\n\nfunc TestV4_NormalizePassword(t *testing.T) {\n\tcases := []struct {\n\t\tinput  string\n\t\toutput string\n\t}{\n\t\t{\n\t\t\t\"𝔱𝔢𝔰𝔱𝔭𝔞𝔰𝔰𝔴𝔬𝔯𝔡🔑\",\n\t\t\t\"testpassword🔑\",\n\t\t},\n\t\t{\n\t\t\tstring([]byte{\n\t\t\t\t0x00, 0x1F,\n\t\t\t\t0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64,\n\t\t\t}),\n\t\t\t\"password\",\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tfound := normalizePassword(c.input)\n\t\tassert.Equal(t, c.output, found)\n\t}\n}\n"
  },
  {
    "path": "networks.go",
    "content": "package ethgo\n\n// Network is a chain id\ntype Network uint64\n\nconst (\n\t// Mainnet is the mainnet network\n\tMainnet Network = 1\n\n\t// Ropsten is the POW testnet\n\tRopsten Network = 3\n\n\t// Rinkeby is a POW testnet\n\tRinkeby Network = 4\n\n\t// Goerli is the Clique testnet\n\tGoerli Network = 5\n)\n"
  },
  {
    "path": "scripts/build-artifacts.sh",
    "content": "#!/usr/bin/env bash\n\nset -o errexit\ncd cmd\n\necho \"--> Build ENS\"\n\nENS_ARTIFACTS=../builtin/ens/artifacts\ngo run main.go abigen --source ${ENS_ARTIFACTS}/ENS.abi,${ENS_ARTIFACTS}/Resolver.abi --output ../builtin/ens --package ens\n\necho \"--> Build ERC20\"\n\nERC20_ARTIFACTS=../builtin/erc20/artifacts\ngo run main.go abigen --source ${ERC20_ARTIFACTS}/ERC20.abi --output ../builtin/erc20 --package erc20\n\necho \"--> Build Testdata\"\ngo run main.go abigen --source ./abigen/testdata/testdata.abi --output ./abigen/testdata --package testdata\n"
  },
  {
    "path": "scripts/setup-ci.sh",
    "content": "#!/usr/bin/env bash\n\n# set -o errexit\n\ninstall_solidity() {\n    VERSION=\"0.5.5\"\n    DOWNLOAD=https://github.com/ethereum/solidity/releases/download/v${VERSION}/solc-static-linux\n\n    curl -L $DOWNLOAD > /tmp/solc\n    chmod +x /tmp/solc\n    mv /tmp/solc /usr/local/bin/solc\n}\n\ninstall_solidity\n"
  },
  {
    "path": "scripts/setup-geth.sh",
    "content": "#!/bin/bash\n\n# Start geth test server\ndocker run --name geth-test -d -p 8545:8545 -p 8546:8546 ethereum/client-go:v1.10.15 \\\n    --dev \\\n    --datadir /eth1data \\\n    --ipcpath /eth1data/geth.ipc \\\n    --http --http.addr 0.0.0.0  --http.vhosts=* --http.api eth,net,web3,debug \\\n    --ws --ws.addr 0.0.0.0 \\\n    --verbosity 4\n\n# Wait for geth to be running\nwhile ! nc -z localhost 8545; do   \n  sleep 0.1 # wait for 1/10 of the second before check again\ndone\n"
  },
  {
    "path": "signing/eip712.go",
    "content": "package signing\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\ntype EIP712MessageBuilder[T any] struct {\n\tTypes       map[string][]*EIP712Type\n\tPrimaryType string\n\tDomain      *EIP712Domain\n}\n\nfunc (e *EIP712MessageBuilder[T]) GetEncodedType() string {\n\treturn encodeType(e.PrimaryType, e.Types)\n}\n\nfunc NewEIP712MessageBuilder[T any](domain *EIP712Domain) *EIP712MessageBuilder[T] {\n\tvar t T\n\ttypes := map[string][]*EIP712Type{}\n\tprimaryType := decodeStructType(reflect.ValueOf(t).Type(), &types)\n\n\tbuilder := &EIP712MessageBuilder[T]{\n\t\tTypes:       types,\n\t\tPrimaryType: primaryType,\n\t\tDomain:      domain,\n\t}\n\treturn builder\n}\n\nfunc decodeStructType(typ reflect.Type, result *map[string][]*EIP712Type) string {\n\tif typ.Kind() != reflect.Struct {\n\t\tpanic(fmt.Sprintf(\"struct expected but found %s\", typ.Kind()))\n\t}\n\n\tname := typ.Name()\n\n\ttypes := []*EIP712Type{}\n\tfor i := 0; i < typ.NumField(); i++ {\n\t\tfield := typ.Field(i)\n\t\tfieldName := field.Name\n\n\t\t// use a tag as a name (if any)\n\t\tif tagVal := field.Tag.Get(\"eip712\"); tagVal != \"\" {\n\t\t\tfieldName = tagVal\n\t\t}\n\n\t\tfieldType := decodeTypes(field.Type, result)\n\n\t\ttypes = append(types, &EIP712Type{\n\t\t\tType: fieldType,\n\t\t\tName: fieldName,\n\t\t})\n\t}\n\n\t(*result)[name] = types\n\treturn name\n}\n\nfunc isByteSlice(t reflect.Type) bool {\n\treturn t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8\n}\n\nfunc isByteArray(t reflect.Type) bool {\n\treturn t.Kind() == reflect.Array && t.Elem().Kind() == reflect.Uint8\n}\n\nvar (\n\taddressT = reflect.TypeOf(ethgo.Address{})\n\tbigIntT  = reflect.TypeOf(new(big.Int))\n)\n\nfunc decodeTypes(val reflect.Type, result *map[string][]*EIP712Type) string {\n\tif val == addressT {\n\t\treturn \"address\"\n\t}\n\tif val == bigIntT {\n\t\treturn \"uint256\"\n\t}\n\n\tswitch val.Kind() {\n\tcase reflect.Array:\n\t\tif val.Elem().Kind() == reflect.Uint8 {\n\t\t\t// [x]byte\n\t\t\treturn fmt.Sprintf(\"[%d]byte\", val.Len())\n\t\t}\n\t\treturn fmt.Sprintf(\"%s[%d]\", decodeTypes(val.Elem(), result), val.Len())\n\n\tcase reflect.Slice:\n\t\tif val.Elem().Kind() == reflect.Uint8 {\n\t\t\t// []byte\n\t\t\treturn \"bytes\"\n\t\t}\n\t\treturn decodeTypes(val.Elem(), result) + \"[]\"\n\n\tcase reflect.Struct:\n\t\treturn decodeStructType(val, result)\n\n\tcase reflect.String:\n\t\treturn \"string\"\n\n\tcase reflect.Uint8:\n\t\treturn \"uint8\"\n\n\tcase reflect.Uint16:\n\t\treturn \"uint16\"\n\n\tcase reflect.Uint32:\n\t\treturn \"uint32\"\n\n\tcase reflect.Uint64:\n\t\treturn \"uint64\"\n\n\tcase reflect.Ptr:\n\t\treturn decodeTypes(val.Elem(), result)\n\n\tdefault:\n\t}\n\n\tpanic(fmt.Sprintf(\"type %s not found\", val.Kind()))\n}\n\nfunc (e *EIP712MessageBuilder[T]) Build(obj *T) *EIP712TypedData {\n\tmessage := structToMap(reflect.ValueOf(obj))\n\n\tres := &EIP712TypedData{\n\t\tTypes:       e.Types,\n\t\tPrimaryType: e.PrimaryType,\n\t\tMessage:     message,\n\t\tDomain:      e.Domain,\n\t}\n\treturn res\n}\n\nfunc structToMap(v reflect.Value) map[string]interface{} {\n\tif v.Kind() == reflect.Ptr {\n\t\tv = v.Elem()\n\t}\n\n\ttyp := v.Type()\n\tresult := make(map[string]interface{})\n\n\tfor i := 0; i < typ.NumField(); i++ {\n\t\tfield := typ.Field(i)\n\t\tfieldValue := v.Field(i)\n\n\t\tfieldName := field.Name\n\t\t// use a tag as a name (if any)\n\t\tif tagVal := field.Tag.Get(\"eip712\"); tagVal != \"\" {\n\t\t\tfieldName = tagVal\n\t\t}\n\n\t\tif field.Type == bigIntT {\n\t\t\tresult[fieldName] = fieldValue.Interface()\n\t\t\tcontinue\n\t\t}\n\n\t\tif fieldValue.Kind() == reflect.Ptr {\n\t\t\tfieldValue = fieldValue.Elem()\n\t\t}\n\n\t\tif fieldValue.Kind() == reflect.Struct {\n\t\t\t// the field is a struct, handle recursively as another map\n\t\t\tresult[fieldName] = structToMap(fieldValue)\n\n\t\t} else if fieldValue.Kind() == reflect.Slice || fieldValue.Kind() == reflect.Array {\n\t\t\tif field.Type.Elem().Kind() == reflect.Uint8 {\n\t\t\t\t// []byte return as it is\n\t\t\t\tresult[fieldName] = fieldValue.Interface()\n\t\t\t} else {\n\t\t\t\t// the field is an slice, return a list of interfaces\n\t\t\t\tvar arr []interface{}\n\t\t\t\tfor j := 0; j < fieldValue.Len(); j++ {\n\t\t\t\t\tarr = append(arr, structToMap(fieldValue.Index(j)))\n\t\t\t\t}\n\n\t\t\t\tif fieldValue.Kind() == reflect.Array {\n\t\t\t\t\t// conver to array\n\t\t\t\t\tresult[fieldName] = sliceToArray(arr)\n\t\t\t\t} else {\n\t\t\t\t\tresult[fieldName] = arr\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\t\t\t// primary field, return its interface form\n\t\t\tresult[fieldName] = fieldValue.Interface()\n\t\t}\n\t}\n\n\treturn result\n}\n\nfunc sliceToArray(slice interface{}) interface{} {\n\tsliceValue := reflect.ValueOf(slice)\n\telemType := sliceValue.Type().Elem()\n\tlength := sliceValue.Len()\n\n\t// Create a new slice with the same length and capacity as the original slice\n\tnewSlice := reflect.MakeSlice(reflect.SliceOf(elemType), length, length)\n\n\t// Copy the elements from the original slice to the new slice\n\treflect.Copy(newSlice, sliceValue)\n\n\t// Convert the new slice to an array\n\tarrayType := reflect.ArrayOf(length, elemType)\n\tarrayValue := reflect.New(arrayType).Elem()\n\treflect.Copy(arrayValue, newSlice)\n\n\t// Return the array value as an interface{}\n\treturn arrayValue.Interface()\n}\n\ntype EIP712Type struct {\n\tName string\n\tType string\n}\n\ntype EIP712TypedData struct {\n\tTypes       map[string][]*EIP712Type `json:\"types\"`\n\tPrimaryType string                   `json:\"primaryType\"`\n\tDomain      *EIP712Domain            `json:\"domain\"`\n\tMessage     map[string]interface{}   `json:\"message\"`\n}\n\nfunc (t *EIP712TypedData) Hash() ([]byte, error) {\n\ta, err := t.Domain.hashStruct()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tb, err := hashStruct(t.PrimaryType, t.Types, t.Message)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tres := []byte{}\n\tres = append(res, 0x19, 0x1)\n\tres = append(res, a...)\n\tres = append(res, b...)\n\n\treturn ethgo.Keccak256(res), nil\n}\n\ntype EIP712Domain struct {\n\tName              string   `json:\"name\"`\n\tVersion           string   `json:\"version\"`\n\tVerifyingContract string   `json:\"verifyingContract\"`\n\tChainId           *big.Int `json:\"chainId\"`\n\tSalt              []byte   `json:\"salt\"`\n}\n\nfunc hashStruct(primary string, types map[string][]*EIP712Type, data map[string]interface{}) ([]byte, error) {\n\ta1 := encodeType(primary, types)\n\n\ta2, err := encodeData(primary, types, data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttypeHash := ethgo.Keccak256([]byte(a1))\n\n\tinput := []byte{}\n\tinput = append(input, typeHash...)\n\tinput = append(input, a2...)\n\n\tresult := ethgo.Keccak256(input)\n\treturn result, nil\n}\n\nfunc (e *EIP712Domain) hashStruct() ([]byte, error) {\n\ta1, a2 := e.getObjs()\n\n\treturn hashStruct(\"EIP712Domain\", map[string][]*EIP712Type{\"EIP712Domain\": a1}, a2)\n}\n\nfunc (e *EIP712Domain) getObjs() ([]*EIP712Type, map[string]interface{}) {\n\tvar types []*EIP712Type\n\tdata := map[string]interface{}{}\n\n\taddType := func(name, typ string) {\n\t\ttypes = append(types, &EIP712Type{Name: name, Type: typ})\n\t}\n\n\tif len(e.Name) != 0 {\n\t\taddType(\"name\", \"string\")\n\t\tdata[\"name\"] = e.Name\n\t}\n\tif len(e.Version) != 0 {\n\t\taddType(\"version\", \"string\")\n\t\tdata[\"version\"] = e.Version\n\t}\n\tif e.ChainId != nil {\n\t\taddType(\"chainId\", \"uint256\")\n\t\tdata[\"chainId\"] = e.ChainId\n\t}\n\tif len(e.VerifyingContract) != 0 {\n\t\taddType(\"verifyingContract\", \"address\")\n\t\tdata[\"verifyingContract\"] = e.VerifyingContract\n\t}\n\tif len(e.Salt) != 0 {\n\t\taddType(\"salt\", \"bytes32\")\n\t\tdata[\"salt\"] = e.Salt\n\t}\n\n\treturn types, data\n}\n\nfunc encodeData(primary string, types map[string][]*EIP712Type, data map[string]interface{}) ([]byte, error) {\n\tfields := types[primary]\n\n\tresult := []byte{}\n\tfor _, field := range fields {\n\t\tval, ok := data[field.Name]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"field '%s' not found\", field.Name)\n\t\t}\n\n\t\tres, err := encodeItem(field.Type, types, val)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult = append(result, res...)\n\t}\n\n\treturn result, nil\n}\n\nfunc encodeItem(typ string, types map[string][]*EIP712Type, val interface{}) ([]byte, error) {\n\tvar res []byte\n\n\t// handle array\n\tif typ[len(typ)-1:] == \"]\" {\n\t\tsubType := typ[:strings.LastIndex(typ, \"[\")]\n\n\t\tvar subElem []byte\n\t\tv := reflect.ValueOf(val)\n\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\telemRes, err := encodeItem(subType, types, v.Index(i).Interface())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsubElem = append(subElem, elemRes...)\n\t\t}\n\t\tres = ethgo.Keccak256(subElem)\n\n\t} else if _, ok := types[typ]; ok {\n\t\t// if the item is a struct, handle it\n\t\tvar err error\n\t\tif res, err = hashStruct(typ, types, val.(map[string]interface{})); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else if typ == \"string\" {\n\t\t// dynamic string type\n\t\tvalStr, ok := val.(string)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"string type not found\")\n\t\t}\n\t\tres = ethgo.Keccak256([]byte(valStr))\n\t} else if typ == \"bytes\" {\n\t\t// dynamic length bytes, it can be either a string or []byte\n\t\tif valStr, ok := val.(string); ok {\n\t\t\t// the string must start with 0x\n\t\t\tvalBytes, err := decodeHexString(valStr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tres = ethgo.Keccak256(valBytes)\n\t\t} else if valBytes, ok := val.([]byte); ok {\n\t\t\tres = ethgo.Keccak256(valBytes)\n\t\t}\n\t} else {\n\t\t// encode basic item\n\t\ttyp, err := abi.NewType(typ)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tres, err = abi.Encode(val, typ)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn res, nil\n}\n\nfunc getDependencies(primary string, types map[string][]*EIP712Type) []string {\n\t// two types cannot be encoded twice\n\tvisited := map[string]struct{}{}\n\n\t// a queue of the types to encode\n\tparseTypes := []string{\n\t\tprimary,\n\t}\n\n\tdeps := sort.StringSlice{}\n\n\tfor len(parseTypes) != 0 {\n\t\tvar typ string\n\t\ttyp, parseTypes = parseTypes[0], parseTypes[1:]\n\n\t\tfor _, field := range types[typ] {\n\t\t\ttyp := field.Type\n\n\t\t\t// remove any array items from the name (i.e. Struct[][3])\n\t\t\tif indx := strings.Index(typ, \"[\"); indx != -1 {\n\t\t\t\ttyp = typ[:indx]\n\t\t\t}\n\n\t\t\tif _, ok := types[typ]; ok {\n\t\t\t\tif _, ok := visited[typ]; !ok {\n\t\t\t\t\t// its a type and not visited yet\n\t\t\t\t\tdeps = append(deps, typ)\n\t\t\t\t\tparseTypes = append(parseTypes, typ)\n\t\t\t\t\tvisited[typ] = struct{}{}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdeps.Sort()\n\n\t// the primary is always the first field\n\tres := []string{primary}\n\tres = append(res, deps...)\n\n\treturn res\n}\n\nfunc encodeType(primary string, types map[string][]*EIP712Type) string {\n\tdeps := getDependencies(primary, types)\n\n\tencodedType := \"\"\n\tfor _, dep := range deps {\n\t\tstrFields := []string{}\n\t\tfor _, field := range types[dep] {\n\t\t\tstrFields = append(strFields, field.Type+\" \"+field.Name)\n\t\t}\n\t\tencodedType += fmt.Sprintf(\"%s(%s)\", dep, strings.Join(strFields, \",\"))\n\t}\n\n\treturn encodedType\n}\n\nfunc decodeHexString(str string) ([]byte, error) {\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn nil, fmt.Errorf(\"0x prefix not found\")\n\t}\n\tbuf, err := hex.DecodeString(str[2:])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn buf, nil\n}\n"
  },
  {
    "path": "signing/eip712_test.go",
    "content": "package signing\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n)\n\ntype Message struct {\n\tA    uint64      `eip712:\"a\"`\n\tC    *big.Int    `eip712:\"c\"`\n\tMsg1 *Message2   `eip712:\"msg1\"`\n\tMsg2 []Message2  `eip712:\"msg2\"`\n\tMsg3 [3]Message2 `eip712:\"msg3\"`\n}\n\ntype Message2 struct {\n\tB    uint64        `eip712:\"b\"`\n\tAddr ethgo.Address `eip712:\"addr\"`\n}\n\nfunc TestBuildMessage_Encode(t *testing.T) {\n\tdomain := &EIP712Domain{\n\t\tName: \"name1\",\n\t}\n\n\tb := NewEIP712MessageBuilder[Message](domain)\n\trequire.Equal(t, \"Message(uint64 a,uint256 c,Message2 msg1,Message2[] msg2,Message2[3] msg3)Message2(uint64 b,address addr)\", b.GetEncodedType())\n\n\tmsg := &Message{\n\t\tC:    big.NewInt(1),\n\t\tMsg1: &Message2{},\n\t\tMsg2: []Message2{\n\t\t\t{B: 1},\n\t\t},\n\t}\n\ttypedMsg := b.Build(msg)\n\n\t_, ok := typedMsg.Message[\"msg1\"].(interface{})\n\trequire.True(t, ok)\n\n\t_, ok = typedMsg.Message[\"msg2\"].([]interface{})\n\trequire.True(t, ok)\n\n\t_, ok = typedMsg.Message[\"msg3\"].([3]interface{})\n\trequire.True(t, ok)\n\n\t_, err := typedMsg.Hash()\n\trequire.NoError(t, err)\n}\n\nfunc TestBuildMessage_BasicTypes(t *testing.T) {\n\tdomain := &EIP712Domain{\n\t\tName: \"name1\",\n\t}\n\n\ttype Message struct {\n\t\tA uint64\n\t\tB uint32\n\t\tC uint16\n\t\tD uint8\n\t\tE [32]byte\n\t\tF string\n\t}\n\n\tb := NewEIP712MessageBuilder[Message](domain)\n\trequire.Equal(t, \"Message(uint64 A,uint32 B,uint16 C,uint8 D,[32]byte E,string F)\", b.GetEncodedType())\n}\n"
  },
  {
    "path": "structs.go",
    "content": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar (\n\t// ZeroAddress is an address of all zeros\n\tZeroAddress = Address{}\n\n\t// ZeroHash is a hash of all zeros\n\tZeroHash = Hash{}\n)\n\n// Address is an Ethereum address\ntype Address [20]byte\n\n// HexToAddress converts an hex string value to an address object\nfunc HexToAddress(str string) Address {\n\ta := Address{}\n\ta.UnmarshalText(completeHex(str, 20))\n\treturn a\n}\n\n// BytesToAddress converts bytes to an address object\nfunc BytesToAddress(b []byte) Address {\n\tvar a Address\n\n\tsize := len(b)\n\tmin := min(size, 20)\n\n\tcopy(a[20-min:], b[len(b)-min:])\n\treturn a\n}\n\n// Address implements the ethgo.Key interface Address method.\nfunc (a Address) Address() Address {\n\treturn a\n}\n\n// Sign implements the ethgo.Key interface Sign method.\nfunc (a Address) Sign(hash []byte) ([]byte, error) {\n\tpanic(\"an address cannot sign messages\")\n}\n\n// UnmarshalText implements the unmarshal interface\nfunc (a *Address) UnmarshalText(b []byte) error {\n\treturn unmarshalTextByte(a[:], b, 20)\n}\n\n// MarshalText implements the marshal interface\nfunc (a Address) MarshalText() ([]byte, error) {\n\treturn []byte(a.String()), nil\n}\n\n// Bytes returns the bytes of the Address\nfunc (a Address) Bytes() []byte {\n\treturn a[:]\n}\n\nfunc (a Address) String() string {\n\treturn a.checksumEncode()\n}\n\nfunc (a Address) checksumEncode() string {\n\taddress := strings.ToLower(hex.EncodeToString(a[:]))\n\thash := hex.EncodeToString(Keccak256([]byte(address)))\n\n\tret := \"0x\"\n\tfor i := 0; i < len(address); i++ {\n\t\tcharacter := string(address[i])\n\n\t\tnum, _ := strconv.ParseInt(string(hash[i]), 16, 64)\n\t\tif num > 7 {\n\t\t\tret += strings.ToUpper(character)\n\t\t} else {\n\t\t\tret += character\n\t\t}\n\t}\n\n\treturn ret\n}\n\n// Hash is an Ethereum hash\ntype Hash [32]byte\n\n// HexToHash converts an hex string value to a hash object\nfunc HexToHash(str string) Hash {\n\th := Hash{}\n\th.UnmarshalText(completeHex(str, 32))\n\treturn h\n}\n\n// BytesToHash converts bytes to a hash object\nfunc BytesToHash(b []byte) Hash {\n\tvar h Hash\n\n\tsize := len(b)\n\tmin := min(size, 32)\n\n\tcopy(h[32-min:], b[len(b)-min:])\n\treturn h\n}\n\n// UnmarshalText implements the unmarshal interface\nfunc (h *Hash) UnmarshalText(b []byte) error {\n\treturn unmarshalTextByte(h[:], b, 32)\n}\n\n// MarshalText implements the marshal interface\nfunc (h Hash) MarshalText() ([]byte, error) {\n\treturn []byte(h.String()), nil\n}\n\n// Bytes returns the bytes of the Hash\nfunc (h Hash) Bytes() []byte {\n\treturn h[:]\n}\n\nfunc (h Hash) String() string {\n\treturn \"0x\" + hex.EncodeToString(h[:])\n}\n\nfunc (h Hash) Location() string {\n\treturn h.String()\n}\n\ntype Block struct {\n\tNumber             uint64\n\tHash               Hash\n\tParentHash         Hash\n\tSha3Uncles         Hash\n\tTransactionsRoot   Hash\n\tStateRoot          Hash\n\tReceiptsRoot       Hash\n\tMiner              Address\n\tDifficulty         *big.Int\n\tExtraData          []byte\n\tGasLimit           uint64\n\tGasUsed            uint64\n\tTimestamp          uint64\n\tMixHash            Hash\n\tNonce              [8]byte\n\tTransactions       []*Transaction\n\tTransactionsHashes []Hash\n\tUncles             []Hash\n\tBaseFee            *big.Int\n}\n\nfunc (b *Block) Copy() *Block {\n\tbb := new(Block)\n\t*bb = *b\n\tif b.Difficulty != nil {\n\t\tbb.Difficulty = new(big.Int).Set(b.Difficulty)\n\t}\n\tbb.ExtraData = append(bb.ExtraData[:0], b.ExtraData...)\n\tbb.Transactions = make([]*Transaction, len(b.Transactions))\n\tfor indx, txn := range b.Transactions {\n\t\tbb.Transactions[indx] = txn.Copy()\n\t}\n\treturn bb\n}\n\ntype TransactionType uint8\n\nconst (\n\tTransactionLegacy TransactionType = 0\n\t// eip-2930\n\tTransactionAccessList TransactionType = 1\n\t// eip-1559\n\tTransactionDynamicFee TransactionType = 2\n)\n\ntype Transaction struct {\n\tType TransactionType\n\n\t// legacy values\n\tHash     Hash\n\tFrom     Address\n\tTo       *Address\n\tInput    []byte\n\tGasPrice uint64\n\tGas      uint64\n\tValue    *big.Int\n\tNonce    uint64\n\tV        []byte\n\tR        []byte\n\tS        []byte\n\n\t// jsonrpc values\n\tBlockHash   Hash\n\tBlockNumber uint64\n\tTxnIndex    uint64\n\n\t// eip-2930 values\n\tChainID    *big.Int\n\tAccessList AccessList\n\n\t// eip-1559 values\n\tMaxPriorityFeePerGas *big.Int\n\tMaxFeePerGas         *big.Int\n}\n\nfunc (t *Transaction) Copy() *Transaction {\n\ttt := new(Transaction)\n\t*tt = *t\n\tif t.To != nil {\n\t\tto := Address(*t.To)\n\t\ttt.To = &to\n\t}\n\ttt.Input = append(tt.Input[:0], t.Input...)\n\tif t.Value != nil {\n\t\ttt.Value = new(big.Int).Set(t.Value)\n\t}\n\ttt.V = append(tt.V[:0], t.V...)\n\ttt.R = append(tt.R[:0], t.R...)\n\ttt.S = append(tt.S[:0], t.S...)\n\tif t.ChainID != nil {\n\t\ttt.ChainID = new(big.Int).Set(t.ChainID)\n\t}\n\tif t.MaxPriorityFeePerGas != nil {\n\t\ttt.MaxPriorityFeePerGas = new(big.Int).Set(t.MaxPriorityFeePerGas)\n\t}\n\tif t.MaxFeePerGas != nil {\n\t\ttt.MaxFeePerGas = new(big.Int).Set(t.MaxFeePerGas)\n\t}\n\ttt.AccessList = t.AccessList.Copy()\n\treturn tt\n}\n\ntype AccessEntry struct {\n\tAddress Address `json:\"address\"`\n\tStorage []Hash  `json:\"storageKeys\"`\n}\n\ntype AccessList []AccessEntry\n\nfunc (a *AccessList) Copy() AccessList {\n\taa := AccessList{}\n\tfor _, i := range *a {\n\t\tentry := AccessEntry{\n\t\t\tAddress: i.Address,\n\t\t\tStorage: []Hash{},\n\t\t}\n\t\tentry.Storage = append(entry.Storage, i.Storage...)\n\t\taa = append(aa, entry)\n\t}\n\treturn aa\n}\n\ntype CallMsg struct {\n\tFrom     Address\n\tTo       *Address\n\tData     []byte\n\tGasPrice uint64\n\tGas      *big.Int\n\tValue    *big.Int\n}\n\ntype LogFilter struct {\n\tAddress   []Address\n\tTopics    [][]*Hash\n\tBlockHash *Hash\n\tFrom      *BlockNumber\n\tTo        *BlockNumber\n}\n\nfunc (l *LogFilter) SetFromUint64(num uint64) {\n\tb := BlockNumber(num)\n\tl.From = &b\n}\n\nfunc (l *LogFilter) SetToUint64(num uint64) {\n\tb := BlockNumber(num)\n\tl.To = &b\n}\n\nfunc (l *LogFilter) SetTo(b BlockNumber) {\n\tl.To = &b\n}\n\ntype Receipt struct {\n\tTransactionHash   Hash\n\tTransactionIndex  uint64\n\tContractAddress   Address\n\tBlockHash         Hash\n\tFrom              Address\n\tBlockNumber       uint64\n\tGasUsed           uint64\n\tCumulativeGasUsed uint64\n\tLogsBloom         []byte\n\tLogs              []*Log\n\tStatus            uint64\n\tTo                *Address\n}\n\nfunc (r *Receipt) Copy() *Receipt {\n\trr := new(Receipt)\n\t*rr = *r\n\trr.LogsBloom = append(rr.LogsBloom[:0], r.LogsBloom...)\n\trr.Logs = make([]*Log, len(r.Logs))\n\tfor indx, log := range r.Logs {\n\t\trr.Logs[indx] = log.Copy()\n\t}\n\treturn rr\n}\n\ntype Log struct {\n\tRemoved          bool\n\tLogIndex         uint64\n\tTransactionIndex uint64\n\tTransactionHash  Hash\n\tBlockHash        Hash\n\tBlockNumber      uint64\n\tAddress          Address\n\tTopics           []Hash\n\tData             []byte\n}\n\nfunc (l *Log) Copy() *Log {\n\tll := new(Log)\n\t*ll = *l\n\tll.Data = append(ll.Data[:0], l.Data...)\n\treturn ll\n}\n\ntype BlockNumber int\n\nconst (\n\tLatest   BlockNumber = -1\n\tEarliest BlockNumber = -2\n\tPending  BlockNumber = -3\n)\n\nfunc (b BlockNumber) Location() string {\n\treturn b.String()\n}\n\nfunc (b BlockNumber) String() string {\n\tswitch b {\n\tcase Latest:\n\t\treturn \"latest\"\n\tcase Earliest:\n\t\treturn \"earliest\"\n\tcase Pending:\n\t\treturn \"pending\"\n\t}\n\tif b < 0 {\n\t\tpanic(\"internal. blocknumber is negative\")\n\t}\n\treturn fmt.Sprintf(\"0x%x\", uint64(b))\n}\n\nfunc EncodeBlock(block ...BlockNumber) BlockNumber {\n\tif len(block) != 1 {\n\t\treturn Latest\n\t}\n\treturn block[0]\n}\n\ntype BlockNumberOrHash interface {\n\tLocation() string\n}\n\nfunc min(i, j int) int {\n\tif i < j {\n\t\treturn i\n\t}\n\treturn j\n}\n\ntype Key interface {\n\tAddress() Address\n\tSign(hash []byte) ([]byte, error)\n}\n\nfunc completeHex(str string, num int) []byte {\n\tnum = num * 2\n\tstr = strings.TrimPrefix(str, \"0x\")\n\n\tsize := len(str)\n\tif size < num {\n\t\tfor i := size; i < num; i++ {\n\t\t\tstr = \"0\" + str\n\t\t}\n\t} else {\n\t\tdiff := size - num\n\t\tstr = str[diff:]\n\t}\n\treturn []byte(\"0x\" + str)\n}\n\ntype OverrideAccount struct {\n\tNonce     *uint64\n\tCode      *[]byte\n\tBalance   *big.Int\n\tState     *map[Hash]Hash\n\tStateDiff *map[Hash]Hash\n}\n\ntype StateOverride map[Address]OverrideAccount\n"
  },
  {
    "path": "structs_encoding_test.go",
    "content": "package ethgo\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc compactJSON(s string) string {\n\tbuffer := new(bytes.Buffer)\n\tif err := json.Compact(buffer, []byte(s)); err != nil {\n\t\tpanic(err)\n\t}\n\treturn buffer.String()\n}\n\nfunc TestDecodeL2Block(t *testing.T) {\n\tc := readTestsuite(t, \"./testsuite/arbitrum-block-full.json\")\n\n\tblock := new(Block)\n\trequire.NoError(t, block.UnmarshalJSON(c[0].content))\n\n\tfor _, txn := range block.Transactions {\n\t\trequire.NotEqual(t, txn.Type, 0)\n\t}\n}\n\nfunc TestEncodingJSON_Block(t *testing.T) {\n\tfor _, c := range readTestsuite(t, \"./testsuite/block-*.json\") {\n\t\tcontent := []byte(compactJSON(string(c.content)))\n\t\ttxn := new(Block)\n\n\t\t// unmarshal\n\t\terr := txn.UnmarshalJSON(content)\n\t\tassert.NoError(t, err)\n\n\t\t// marshal back\n\t\tres2, err := txn.MarshalJSON()\n\t\tassert.NoError(t, err)\n\n\t\tassert.Equal(t, content, res2)\n\t}\n}\n\nfunc TestEncodingJSON_Transaction(t *testing.T) {\n\tfor _, c := range readTestsuite(t, \"./testsuite/transaction-*.json\") {\n\t\tcontent := []byte(compactJSON(string(c.content)))\n\t\ttxn := new(Transaction)\n\n\t\t// unmarshal\n\t\terr := txn.UnmarshalJSON(content)\n\t\tassert.NoError(t, err)\n\n\t\tif c.name == \"testsuite/transaction-eip1559-notype.json\" {\n\t\t\tcontinue\n\t\t}\n\n\t\t// marshal back\n\t\tres2, err := txn.MarshalJSON()\n\t\tassert.NoError(t, err)\n\n\t\tassert.Equal(t, content, res2)\n\t}\n}\n\ntype testFile struct {\n\tname    string\n\tcontent []byte\n}\n\nfunc readTestsuite(t *testing.T, pattern string) (res []*testFile) {\n\tfiles, err := filepath.Glob(pattern)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(files) == 0 {\n\t\tt.Fatal(\"no test files found\")\n\t}\n\tfor _, f := range files {\n\t\tdata, err := ioutil.ReadFile(f)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tres = append(res, &testFile{\n\t\t\tname:    f,\n\t\t\tcontent: data,\n\t\t})\n\t}\n\treturn\n}\n"
  },
  {
    "path": "structs_marshal.go",
    "content": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/valyala/fastjson\"\n)\n\nvar defaultArena fastjson.ArenaPool\n\n// MarshalJSON implements the marshal interface\nfunc (l *Log) MarshalJSON() ([]byte, error) {\n\ta := defaultArena.Get()\n\tdefer a.Reset()\n\n\to := a.NewObject()\n\tif l.Removed {\n\t\to.Set(\"removed\", a.NewTrue())\n\t} else {\n\t\to.Set(\"removed\", a.NewFalse())\n\t}\n\to.Set(\"logIndex\", a.NewString(fmt.Sprintf(\"0x%x\", l.LogIndex)))\n\to.Set(\"transactionIndex\", a.NewString(fmt.Sprintf(\"0x%x\", l.TransactionIndex)))\n\to.Set(\"transactionHash\", a.NewString(l.TransactionHash.String()))\n\to.Set(\"blockHash\", a.NewString(l.BlockHash.String()))\n\to.Set(\"blockNumber\", a.NewString(fmt.Sprintf(\"0x%x\", l.BlockNumber)))\n\to.Set(\"address\", a.NewString(l.Address.String()))\n\to.Set(\"data\", a.NewString(\"0x\"+hex.EncodeToString(l.Data)))\n\n\tvv := a.NewArray()\n\tfor indx, topic := range l.Topics {\n\t\tvv.SetArrayItem(indx, a.NewString(topic.String()))\n\t}\n\to.Set(\"topics\", vv)\n\n\tres := o.MarshalTo(nil)\n\tdefaultArena.Put(a)\n\treturn res, nil\n}\n\n// MarshalJSON implements the marshal interface\nfunc (t *Block) MarshalJSON() ([]byte, error) {\n\tif t.Difficulty == nil {\n\t\tt.Difficulty = new(big.Int)\n\t}\n\n\ta := defaultArena.Get()\n\tdefer a.Reset()\n\n\to := a.NewObject()\n\to.Set(\"number\", a.NewString(fmt.Sprintf(\"0x%x\", t.Number)))\n\to.Set(\"hash\", a.NewString(t.Hash.String()))\n\to.Set(\"parentHash\", a.NewString(t.ParentHash.String()))\n\to.Set(\"sha3Uncles\", a.NewString(t.Sha3Uncles.String()))\n\to.Set(\"transactionsRoot\", a.NewString(t.TransactionsRoot.String()))\n\to.Set(\"stateRoot\", a.NewString(t.StateRoot.String()))\n\to.Set(\"receiptsRoot\", a.NewString(t.ReceiptsRoot.String()))\n\to.Set(\"miner\", a.NewString(t.Miner.String()))\n\to.Set(\"gasLimit\", a.NewString(fmt.Sprintf(\"0x%x\", t.GasLimit)))\n\to.Set(\"gasUsed\", a.NewString(fmt.Sprintf(\"0x%x\", t.GasUsed)))\n\to.Set(\"timestamp\", a.NewString(fmt.Sprintf(\"0x%x\", t.Timestamp)))\n\to.Set(\"difficulty\", a.NewString(fmt.Sprintf(\"0x%x\", t.Difficulty)))\n\to.Set(\"extraData\", a.NewString(\"0x\"+hex.EncodeToString(t.ExtraData)))\n\to.Set(\"mixHash\", a.NewString(\"0x\"+hex.EncodeToString(t.MixHash[:])))\n\to.Set(\"nonce\", a.NewString(\"0x\"+hex.EncodeToString(t.Nonce[:])))\n\n\tif t.BaseFee != nil {\n\t\to.Set(\"baseFee\", a.NewString(fmt.Sprintf(\"0x%x\", t.BaseFee)))\n\t}\n\n\t// uncles\n\tif len(t.Uncles) != 0 {\n\t\tuncles := a.NewArray()\n\t\tfor indx, uncle := range t.Uncles {\n\t\t\tuncles.SetArrayItem(indx, a.NewString(uncle.String()))\n\t\t}\n\t\to.Set(\"uncles\", uncles)\n\t}\n\n\t// transactions\n\tif len(t.TransactionsHashes) != 0 {\n\t\ttxns := a.NewArray()\n\t\tfor indx, txn := range t.TransactionsHashes {\n\t\t\ttxns.SetArrayItem(indx, a.NewString(txn.String()))\n\t\t}\n\t\to.Set(\"transactions\", txns)\n\t}\n\tif len(t.Transactions) != 0 {\n\t\ttxns := a.NewArray()\n\t\tfor indx, txn := range t.Transactions {\n\t\t\ttxns.SetArrayItem(indx, txn.marshalJSON(a))\n\t\t}\n\t\to.Set(\"transactions\", txns)\n\t}\n\n\tres := o.MarshalTo(nil)\n\tdefaultArena.Put(a)\n\treturn res, nil\n}\n\n// MarshalJSON implements the Marshal interface.\nfunc (t *Transaction) MarshalJSON() ([]byte, error) {\n\ta := defaultArena.Get()\n\tdefer a.Reset()\n\n\tv := t.marshalJSON(a)\n\tres := v.MarshalTo(nil)\n\tdefaultArena.Put(a)\n\treturn res, nil\n}\n\nfunc (t *Transaction) marshalJSON(a *fastjson.Arena) *fastjson.Value {\n\to := a.NewObject()\n\to.Set(\"type\", a.NewString(fmt.Sprintf(\"0x%x\", t.Type)))\n\to.Set(\"hash\", a.NewString(t.Hash.String()))\n\to.Set(\"from\", a.NewString(t.From.String()))\n\tif len(t.Input) != 0 {\n\t\to.Set(\"input\", a.NewString(\"0x\"+hex.EncodeToString(t.Input)))\n\t}\n\tif t.Value != nil {\n\t\to.Set(\"value\", a.NewString(fmt.Sprintf(\"0x%x\", t.Value)))\n\t}\n\tif t.Type == TransactionDynamicFee {\n\t\tif t.MaxPriorityFeePerGas != nil {\n\t\t\to.Set(\"maxPriorityFeePerGas\", a.NewString(fmt.Sprintf(\"0x%x\", t.MaxPriorityFeePerGas)))\n\t\t}\n\t\tif t.MaxFeePerGas != nil {\n\t\t\to.Set(\"maxFeePerGas\", a.NewString(fmt.Sprintf(\"0x%x\", t.MaxFeePerGas)))\n\t\t}\n\t} else {\n\t\to.Set(\"gasPrice\", a.NewString(fmt.Sprintf(\"0x%x\", t.GasPrice)))\n\t}\n\t// gas limit fields\n\tif t.Gas != 0 {\n\t\to.Set(\"gas\", a.NewString(fmt.Sprintf(\"0x%x\", t.Gas)))\n\t}\n\n\tif t.Nonce != 0 {\n\t\t// we can remove this once we include support for custom nonces\n\t\to.Set(\"nonce\", a.NewString(fmt.Sprintf(\"0x%x\", t.Nonce)))\n\t}\n\tif t.To == nil {\n\t\to.Set(\"to\", a.NewNull())\n\t} else {\n\t\to.Set(\"to\", a.NewString(t.To.String()))\n\t}\n\to.Set(\"v\", a.NewString(\"0x\"+hex.EncodeToString(t.V)))\n\to.Set(\"r\", a.NewString(\"0x\"+hex.EncodeToString(t.R)))\n\to.Set(\"s\", a.NewString(\"0x\"+hex.EncodeToString(t.S)))\n\n\tif t.BlockHash == ZeroHash {\n\t\t// The transaction is a pending transaction\n\t\to.Set(\"blockHash\", a.NewNull())\n\t\to.Set(\"blockNumber\", a.NewNull())\n\t\to.Set(\"transactionIndex\", a.NewNull())\n\t} else {\n\t\t// The transaction has valid metadata fields, fill them\n\t\to.Set(\"blockHash\", a.NewString(t.BlockHash.String()))\n\t\to.Set(\"blockNumber\", a.NewString(fmt.Sprintf(\"0x%x\", t.BlockNumber)))\n\t\to.Set(\"transactionIndex\", a.NewString(fmt.Sprintf(\"0x%x\", t.TxnIndex)))\n\t}\n\n\tif t.ChainID != nil {\n\t\to.Set(\"chainId\", a.NewString(fmt.Sprintf(\"0x%x\", t.ChainID)))\n\t}\n\tif t.AccessList != nil {\n\t\to.Set(\"accessList\", t.AccessList.marshalJSON(a))\n\t}\n\treturn o\n}\n\nfunc (t *AccessList) marshalJSON(a *fastjson.Arena) *fastjson.Value {\n\tarr := a.NewArray()\n\tfor indx, elem := range *t {\n\t\tarrElem := a.NewObject()\n\t\tarrElem.Set(\"address\", a.NewString(elem.Address.String()))\n\n\t\tstrg := a.NewArray()\n\t\tfor subIndx, elem := range elem.Storage {\n\t\t\tstrg.SetArrayItem(subIndx, a.NewString(elem.String()))\n\t\t}\n\t\tarrElem.Set(\"storageKeys\", strg)\n\t\tarr.SetArrayItem(indx, arrElem)\n\t}\n\treturn arr\n}\n\n// MarshalJSON implements the Marshal interface.\nfunc (c *CallMsg) MarshalJSON() ([]byte, error) {\n\ta := defaultArena.Get()\n\tdefer a.Reset()\n\n\to := a.NewObject()\n\to.Set(\"from\", a.NewString(c.From.String()))\n\tif c.To != nil {\n\t\to.Set(\"to\", a.NewString(c.To.String()))\n\t}\n\tif len(c.Data) != 0 {\n\t\to.Set(\"data\", a.NewString(\"0x\"+hex.EncodeToString(c.Data)))\n\t}\n\tif c.GasPrice != 0 {\n\t\to.Set(\"gasPrice\", a.NewString(fmt.Sprintf(\"0x%x\", c.GasPrice)))\n\t}\n\tif c.Value != nil {\n\t\to.Set(\"value\", a.NewString(fmt.Sprintf(\"0x%x\", c.Value)))\n\t}\n\tif c.Gas != nil {\n\t\to.Set(\"gas\", a.NewString(fmt.Sprintf(\"0x%x\", c.Gas)))\n\t}\n\n\tres := o.MarshalTo(nil)\n\tdefaultArena.Put(a)\n\treturn res, nil\n}\n\n// MarshalJSON implements the Marshal interface.\nfunc (l *LogFilter) MarshalJSON() ([]byte, error) {\n\ta := defaultArena.Get()\n\tdefer a.Reset()\n\n\to := a.NewObject()\n\tif len(l.Address) == 1 {\n\t\to.Set(\"address\", a.NewString(l.Address[0].String()))\n\t} else if len(l.Address) > 1 {\n\t\tv := a.NewArray()\n\t\tfor indx, addr := range l.Address {\n\t\t\tv.SetArrayItem(indx, a.NewString(addr.String()))\n\t\t}\n\t}\n\n\tv := a.NewArray()\n\tfor indx, topics := range l.Topics {\n\t\tif topics == nil {\n\t\t\tv.SetArrayItem(indx, a.NewNull())\n\n\t\t\tcontinue\n\t\t}\n\n\t\tinnerTopicArray := a.NewArray()\n\t\tfor innerIndx, innerTopic := range topics {\n\t\t\tif innerTopic == nil {\n\t\t\t\tinnerTopicArray.SetArrayItem(innerIndx, a.NewNull())\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tinnerTopicArray.SetArrayItem(innerIndx, a.NewString(innerTopic.String()))\n\t\t}\n\n\t\tv.SetArrayItem(indx, innerTopicArray)\n\t}\n\to.Set(\"topics\", v)\n\n\tif l.BlockHash != nil {\n\t\to.Set(\"blockHash\", a.NewString((*l.BlockHash).String()))\n\t}\n\tif l.From != nil {\n\t\to.Set(\"fromBlock\", a.NewString((*l.From).String()))\n\t}\n\tif l.To != nil {\n\t\to.Set(\"toBlock\", a.NewString((*l.To).String()))\n\t}\n\n\tres := o.MarshalTo(nil)\n\tdefaultArena.Put(a)\n\treturn res, nil\n}\n\nfunc (s StateOverride) MarshalJSON() ([]byte, error) {\n\ta := defaultArena.Get()\n\tdefer a.Reset()\n\n\to := a.NewObject()\n\tfor addr, obj := range s {\n\t\too := a.NewObject()\n\t\tif obj.Nonce != nil {\n\t\t\too.Set(\"nonce\", a.NewString(fmt.Sprintf(\"0x%x\", *obj.Nonce)))\n\t\t}\n\t\tif obj.Balance != nil {\n\t\t\too.Set(\"balance\", a.NewString(fmt.Sprintf(\"0x%x\", obj.Balance)))\n\t\t}\n\t\tif obj.Code != nil {\n\t\t\too.Set(\"code\", a.NewString(\"0x\"+hex.EncodeToString(*obj.Code)))\n\t\t}\n\t\tif obj.State != nil {\n\t\t\tooo := a.NewObject()\n\t\t\tfor k, v := range *obj.State {\n\t\t\t\tooo.Set(k.String(), a.NewString(v.String()))\n\t\t\t}\n\t\t\too.Set(\"state\", ooo)\n\t\t}\n\t\tif obj.StateDiff != nil {\n\t\t\tooo := a.NewObject()\n\t\t\tfor k, v := range *obj.StateDiff {\n\t\t\t\tooo.Set(k.String(), a.NewString(v.String()))\n\t\t\t}\n\t\t\too.Set(\"stateDiff\", ooo)\n\t\t}\n\t\to.Set(addr.String(), oo)\n\t}\n\n\tres := o.MarshalTo(nil)\n\tdefaultArena.Put(a)\n\n\treturn res, nil\n}\n"
  },
  {
    "path": "structs_marshal_rlp.go",
    "content": "package ethgo\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/fastrlp\"\n)\n\n// GetHash returns the Hash of the transaction\nfunc (t *Transaction) GetHash() (hash Hash, err error) {\n\tvar rlpEncode []byte\n\tif rlpEncode, err = t.MarshalRLPTo(nil); err != nil {\n\t\treturn Hash{}, err\n\t}\n\treturn BytesToHash(Keccak256(rlpEncode)), nil\n}\n\n// MarshalRLPTo marshals the transaction to a []byte destination\nfunc (t *Transaction) MarshalRLPTo(dst []byte) ([]byte, error) {\n\traw, err := fastrlp.MarshalRLP(t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif t.Type == TransactionLegacy {\n\t\treturn raw, nil\n\t}\n\t// append type byte\n\treturn append([]byte{byte(t.Type)}, raw...), nil\n}\n\n// MarshalRLPWith marshals the transaction to RLP with a specific fastrlp.Arena\nfunc (t *Transaction) MarshalRLPWith(arena *fastrlp.Arena) (*fastrlp.Value, error) {\n\tvv := arena.NewArray()\n\n\tif t.Type != 0 {\n\t\t// either dynamic and access type\n\t\tvv.Set(arena.NewBigInt(t.ChainID))\n\t}\n\n\tvv.Set(arena.NewUint(t.Nonce))\n\n\tif t.Type == TransactionDynamicFee {\n\t\t// dynamic fee uses\n\t\tvv.Set(arena.NewBigInt(t.MaxPriorityFeePerGas))\n\t\tvv.Set(arena.NewBigInt(t.MaxFeePerGas))\n\t} else {\n\t\t// legacy and access type use gas price\n\t\tvv.Set(arena.NewUint(t.GasPrice))\n\t}\n\n\tvv.Set(arena.NewUint(t.Gas))\n\n\t// Address may be empty\n\tif t.To != nil {\n\t\tvv.Set(arena.NewBytes((*t.To)[:]))\n\t} else {\n\t\tvv.Set(arena.NewNull())\n\t}\n\n\tvv.Set(arena.NewBigInt(t.Value))\n\tvv.Set(arena.NewCopyBytes(t.Input))\n\n\tif t.Type != 0 {\n\t\t// either dynamic and access type\n\t\taccessList, err := t.AccessList.MarshalRLPWith(arena)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvv.Set(accessList)\n\t}\n\n\t// signature values\n\tvv.Set(arena.NewCopyBytes(t.V))\n\tvv.Set(arena.NewCopyBytes(t.R))\n\tvv.Set(arena.NewCopyBytes(t.S))\n\n\tif t.Type == TransactionLegacy {\n\t\treturn vv, nil\n\t}\n\treturn vv, nil\n}\n\nfunc (t *Transaction) UnmarshalRLP(buf []byte) error {\n\tt.Hash = BytesToHash(Keccak256(buf))\n\n\tif len(buf) < 1 {\n\t\treturn fmt.Errorf(\"expecting 1 byte but 0 byte provided\")\n\t}\n\tif buf[0] <= 0x7f {\n\t\t// it includes a type byte\n\t\tswitch typ := buf[0]; typ {\n\t\tcase 1:\n\t\t\tt.Type = TransactionAccessList\n\t\tcase 2:\n\t\t\tt.Type = TransactionDynamicFee\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"type byte %d not found\", typ)\n\t\t}\n\t\tbuf = buf[1:]\n\t}\n\tif err := fastrlp.UnmarshalRLP(buf, t); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (t *Transaction) UnmarshalRLPWith(v *fastrlp.Value) error {\n\telems, err := v.GetElems()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tgetElem := func() *fastrlp.Value {\n\t\tv := elems[0]\n\t\telems = elems[1:]\n\t\treturn v\n\t}\n\n\tvar num int\n\tswitch t.Type {\n\tcase TransactionLegacy:\n\t\tnum = 9\n\tcase TransactionAccessList:\n\t\t// legacy + chain id + access list\n\t\tnum = 11\n\tcase TransactionDynamicFee:\n\t\t// access list txn + gas fee 1 + gas fee 2 - gas price\n\t\tnum = 12\n\tdefault:\n\t\treturn fmt.Errorf(\"transaction type %d not found\", t.Type)\n\t}\n\tif numElems := len(elems); numElems != num {\n\t\treturn fmt.Errorf(\"not enough elements to decode transaction, expected %d but found %d\", num, numElems)\n\t}\n\n\tif t.Type != 0 {\n\t\tt.ChainID = new(big.Int)\n\t\tif err := getElem().GetBigInt(t.ChainID); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// nonce\n\tif t.Nonce, err = getElem().GetUint64(); err != nil {\n\t\treturn err\n\t}\n\n\tif t.Type == TransactionDynamicFee {\n\t\t// dynamic fee uses\n\t\tt.MaxPriorityFeePerGas = new(big.Int)\n\t\tif err := getElem().GetBigInt(t.MaxPriorityFeePerGas); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tt.MaxFeePerGas = new(big.Int)\n\t\tif err := getElem().GetBigInt(t.MaxFeePerGas); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\t// legacy and access type use gas price\n\t\tif t.GasPrice, err = getElem().GetUint64(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// gas\n\tif t.Gas, err = getElem().GetUint64(); err != nil {\n\t\treturn err\n\t}\n\t// to\n\tvv, _ := getElem().Bytes()\n\tif len(vv) == 20 {\n\t\t// address\n\t\taddr := BytesToAddress(vv)\n\t\tt.To = &addr\n\t} else {\n\t\t// reset To\n\t\tt.To = nil\n\t}\n\t// value\n\tt.Value = new(big.Int)\n\tif err := getElem().GetBigInt(t.Value); err != nil {\n\t\treturn err\n\t}\n\t// input\n\tif t.Input, err = getElem().GetBytes(t.Input[:0]); err != nil {\n\t\treturn err\n\t}\n\n\tif t.Type != 0 {\n\t\tif err := t.AccessList.UnmarshalRLPWith(getElem()); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// V\n\tif t.V, err = getElem().GetBytes(t.V); err != nil {\n\t\treturn err\n\t}\n\t// R\n\tif t.R, err = getElem().GetBytes(t.R); err != nil {\n\t\treturn err\n\t}\n\t// S\n\tif t.S, err = getElem().GetBytes(t.S); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (a *AccessList) MarshalRLPTo(dst []byte) ([]byte, error) {\n\treturn fastrlp.MarshalRLP(a)\n}\n\nfunc (a *AccessList) MarshalRLPWith(arena *fastrlp.Arena) (*fastrlp.Value, error) {\n\tif len(*a) == 0 {\n\t\treturn arena.NewNullArray(), nil\n\t}\n\tv := arena.NewArray()\n\tfor _, i := range *a {\n\t\tacct := arena.NewArray()\n\t\tacct.Set(arena.NewCopyBytes(i.Address[:]))\n\t\tif len(i.Storage) == 0 {\n\t\t\tacct.Set(arena.NewNullArray())\n\t\t} else {\n\t\t\tstrV := arena.NewArray()\n\t\t\tfor _, v := range i.Storage {\n\t\t\t\tstrV.Set(arena.NewCopyBytes(v[:]))\n\t\t\t}\n\t\t\tacct.Set(strV)\n\t\t}\n\t\tv.Set(acct)\n\t}\n\treturn v, nil\n}\n\nfunc (a *AccessList) UnmarshalRLP(buf []byte) error {\n\treturn fastrlp.UnmarshalRLP(buf, a)\n}\n\nfunc (a *AccessList) UnmarshalRLPWith(v *fastrlp.Value) error {\n\tif v.Type() == fastrlp.TypeArrayNull {\n\t\t// empty\n\t\treturn nil\n\t}\n\n\telems, err := v.GetElems()\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, elem := range elems {\n\t\tentry := AccessEntry{}\n\n\t\tacctElems, err := elem.GetElems()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(acctElems) != 2 {\n\t\t\treturn fmt.Errorf(\"two elems expected but %d found\", len(acctElems))\n\t\t}\n\n\t\t// decode 'address'\n\t\tif err = acctElems[0].GetAddr(entry.Address[:]); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// decode 'storage'\n\t\tif acctElems[1].Type() != fastrlp.TypeArrayNull {\n\t\t\tstorageElems, err := acctElems[1].GetElems()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tentry.Storage = make([]Hash, len(storageElems))\n\t\t\tfor indx, storage := range storageElems {\n\t\t\t\t// decode storage\n\t\t\t\tif err = storage.GetHash(entry.Storage[indx][:]); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t(*a) = append((*a), entry)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "structs_marshal_rlp_test.go",
    "content": "package ethgo\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/fastrlp\"\n)\n\nfunc TestEncodingRLP_Transaction_Fuzz(t *testing.T) {\n\ttestTransaction := func(t *testing.T, typ TransactionType) {\n\t\tobj := &Transaction{}\n\t\terr := fastrlp.Fuzz(100, obj,\n\t\t\tfastrlp.WithDefaults(func(obj fastrlp.FuzzObject) {\n\t\t\t\tobj.(*Transaction).Type = typ\n\t\t\t}),\n\t\t\tfastrlp.WithPostHook(func(obj fastrlp.FuzzObject) error {\n\t\t\t\t// Test that the hash from unmarshal is the same as the one computed\n\t\t\t\ttxn := obj.(*Transaction)\n\t\t\t\tcHash, err := txn.GetHash()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif cHash != txn.Hash {\n\t\t\t\t\treturn fmt.Errorf(\"hash not equal\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}),\n\t\t)\n\t\tassert.NoError(t, err)\n\t}\n\n\tt.Run(\"legacy\", func(t *testing.T) {\n\t\ttestTransaction(t, TransactionLegacy)\n\t})\n\tt.Run(\"accesslist\", func(t *testing.T) {\n\t\ttestTransaction(t, TransactionAccessList)\n\t})\n\tt.Run(\"dynamicfee\", func(t *testing.T) {\n\t\ttestTransaction(t, TransactionDynamicFee)\n\t})\n}\n\nfunc TestEncodingRLP_AccessList_Fuzz(t *testing.T) {\n\tobj := &AccessList{}\n\tif err := fastrlp.Fuzz(100, obj); err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "structs_marshal_test.go",
    "content": "package ethgo\n\nimport (\n\t\"encoding/json\"\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc generateHashPtr(input string) *Hash {\n\tres := HexToHash(input)\n\treturn &res\n}\n\nfunc TestLogFilter_MarshalJSON(t *testing.T) {\n\ttestTable := []struct {\n\t\tname   string\n\t\ttopics [][]*Hash\n\t}{\n\t\t{\n\t\t\t\"match any topic\",\n\t\t\t[][]*Hash{\n\t\t\t\tnil,\n\t\t\t\t{},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"match single topic in pos. 1\",\n\t\t\t[][]*Hash{\n\t\t\t\t{\n\t\t\t\t\tgenerateHashPtr(\"0xa\"),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"match single topic in pos. 2\",\n\t\t\t[][]*Hash{\n\t\t\t\t{},\n\t\t\t\t{\n\t\t\t\t\tgenerateHashPtr(\"0xb\"),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"match topic in pos. 1 AND pos. 2\",\n\t\t\t[][]*Hash{\n\t\t\t\t{\n\t\t\t\t\tgenerateHashPtr(\"0xa\"),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tgenerateHashPtr(\"0xb\"),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"match topic A or B in pos. 1 AND C or D in pos. 2\",\n\t\t\t[][]*Hash{\n\t\t\t\t{\n\t\t\t\t\tgenerateHashPtr(\"0xa\"),\n\t\t\t\t\tgenerateHashPtr(\"0xb\"),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tgenerateHashPtr(\"0xc\"),\n\t\t\t\t\tgenerateHashPtr(\"0xd\"),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tdefaultLogFilter := &LogFilter{\n\t\tAddress:   []Address{HexToAddress(\"0x123\")},\n\t\tTopics:    nil,\n\t\tBlockHash: generateHashPtr(\"0xabc\"),\n\t}\n\tfor _, testCase := range testTable {\n\t\tt.Run(testCase.name, func(t *testing.T) {\n\t\t\tdefaultLogFilter.Topics = testCase.topics\n\n\t\t\t// Marshal it to JSON\n\t\t\toutput, marshalErr := defaultLogFilter.MarshalJSON()\n\t\t\tif marshalErr != nil {\n\t\t\t\tt.Fatalf(\"Unable to marshal value, %v\", marshalErr)\n\t\t\t}\n\n\t\t\t// Unmarshal it from JSON\n\t\t\treverseOutput := &LogFilter{}\n\t\t\tunmarshalErr := json.Unmarshal(output, reverseOutput)\n\t\t\tif unmarshalErr != nil {\n\t\t\t\tt.Fatalf(\"Unable to unmarshal value, %v\", unmarshalErr)\n\t\t\t}\n\n\t\t\t// Assert that the original and unmarshalled values match\n\t\t\tassert.Equal(t, defaultLogFilter, reverseOutput)\n\t\t})\n\t}\n}\n\nfunc TestMarshal_StateOverride(t *testing.T) {\n\tnonce := uint64(1)\n\tcode := []byte{0x1}\n\n\to := StateOverride{\n\t\t{0x0}: OverrideAccount{\n\t\t\tNonce:   &nonce,\n\t\t\tBalance: big.NewInt(1),\n\t\t\tCode:    &code,\n\t\t\tState: &map[Hash]Hash{\n\t\t\t\t{0x1}: {0x1},\n\t\t\t},\n\t\t\tStateDiff: &map[Hash]Hash{\n\t\t\t\t{0x1}: {0x1},\n\t\t\t},\n\t\t},\n\t}\n\n\tres, err := o.MarshalJSON()\n\trequire.NoError(t, err)\n\n\texpected := `{\"0x0000000000000000000000000000000000000000\":{\"nonce\":\"0x1\",\"balance\":\"0x1\",\"code\":\"0x01\",\"state\":{\"0x0100000000000000000000000000000000000000000000000000000000000000\":\"0x0100000000000000000000000000000000000000000000000000000000000000\"},\"stateDiff\":{\"0x0100000000000000000000000000000000000000000000000000000000000000\":\"0x0100000000000000000000000000000000000000000000000000000000000000\"}}}`\n\trequire.Equal(t, expected, string(res))\n}\n"
  },
  {
    "path": "structs_test.go",
    "content": "package ethgo\n\nimport (\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestAddress_Checksum(t *testing.T) {\n\tcases := []struct {\n\t\tsrc, dst string\n\t}{\n\t\t{\n\t\t\t\"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed\",\n\t\t\t\"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed\",\n\t\t},\n\t\t{\n\t\t\t\"0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359\",\n\t\t\t\"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359\",\n\t\t},\n\t\t{\n\t\t\t\"0xdbf03b407c01e7cd3cbea99509d93f8dddc8c6fb\",\n\t\t\t\"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB\",\n\t\t},\n\t\t{\n\t\t\t\"0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb\",\n\t\t\t\"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb\",\n\t\t},\n\t}\n\tfor _, c := range cases {\n\t\taddr := HexToAddress(c.src)\n\t\tassert.Equal(t, addr.String(), c.dst)\n\t}\n}\n\nfunc TestAddress_HexToString(t *testing.T) {\n\tassert.Equal(t, HexToAddress(\"0x1\").String(), \"0x0000000000000000000000000000000000000001\")\n\tassert.Equal(t, HexToAddress(\"00000000000000000000000000000000000000001\").String(), \"0x0000000000000000000000000000000000000001\")\n\tassert.Equal(t, HexToAddress(\"0000000000000000000000000000000000000001\").String(), \"0x0000000000000000000000000000000000000001\")\n}\n\nfunc TestHash_HexToString(t *testing.T) {\n\tassert.Equal(t, HexToHash(\"1\").String(), \"0x0000000000000000000000000000000000000000000000000000000000000001\")\n}\n\nfunc TestBlock_Copy(t *testing.T) {\n\tb := &Block{\n\t\tDifficulty:   big.NewInt(1),\n\t\tTransactions: []*Transaction{},\n\t\tExtraData:    []byte{0x1, 0x2},\n\t}\n\tb1 := b.Copy()\n\tif !reflect.DeepEqual(b, b1) {\n\t\tt.Fatal(\"incorrect block copy\")\n\t}\n}\n\nfunc TestTransaction_Copy(t *testing.T) {\n\ttxn := &Transaction{\n\t\tGasPrice: 10,\n\t\tInput:    []byte{0x1, 0x2},\n\t\tV:        []byte{0x1, 0x2},\n\t\tR:        []byte{0x1, 0x2},\n\t\tS:        []byte{0x1, 0x2},\n\t\tAccessList: AccessList{\n\t\t\tAccessEntry{\n\t\t\t\tAddress: Address{0x1},\n\t\t\t\tStorage: []Hash{\n\t\t\t\t\t{0x1},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\ttxn1 := txn.Copy()\n\tif !reflect.DeepEqual(txn, txn1) {\n\t\tt.Fatal(\"incorrect transaction\")\n\t}\n}\n\nfunc TestReceipt_Copy(t *testing.T) {\n\tr := &Receipt{\n\t\tLogsBloom: []byte{0x1, 0x2},\n\t\tLogs: []*Log{\n\t\t\t{LogIndex: 1, Topics: []Hash{{0x1}}},\n\t\t},\n\t\tGasUsed: 10,\n\t}\n\trr := r.Copy()\n\tif !reflect.DeepEqual(r, rr) {\n\t\tt.Fatal(\"incorrect receipt\")\n\t}\n}\n\nfunc TestLog_Copy(t *testing.T) {\n\tl := &Log{\n\t\tData:      []byte{0x1, 0x2},\n\t\tBlockHash: Hash{0x1},\n\t}\n\tll := l.Copy()\n\tif !reflect.DeepEqual(l, ll) {\n\t\tt.Fatal(\"incorrect receipt\")\n\t}\n}\n\n//go:embed testsuite/receipts.json\nvar receiptsFixtures []byte\n\nfunc TestReceipt_Unmarshal(t *testing.T) {\n\tvar cases []json.RawMessage\n\tassert.NoError(t, json.Unmarshal(receiptsFixtures, &cases))\n\n\tfor _, c := range cases {\n\t\treceipt := &Receipt{}\n\t\tassert.NoError(t, receipt.UnmarshalJSON(c))\n\t}\n}\n"
  },
  {
    "path": "structs_unmarshal.go",
    "content": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/valyala/fastjson\"\n)\n\nvar defaultPool fastjson.ParserPool\n\n// UnmarshalJSON implements the unmarshal interface\nfunc (b *Block) UnmarshalJSON(buf []byte) error {\n\tp := defaultPool.Get()\n\tdefer defaultPool.Put(p)\n\n\tv, err := p.Parse(string(buf))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := decodeHash(&b.Hash, v, \"hash\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&b.ParentHash, v, \"parentHash\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&b.Sha3Uncles, v, \"sha3Uncles\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&b.TransactionsRoot, v, \"transactionsRoot\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&b.StateRoot, v, \"stateRoot\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&b.ReceiptsRoot, v, \"receiptsRoot\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeAddr(&b.Miner, v, \"miner\"); err != nil {\n\t\treturn err\n\t}\n\tif b.Number, err = decodeUint(v, \"number\"); err != nil {\n\t\treturn err\n\t}\n\tif b.GasLimit, err = decodeUint(v, \"gasLimit\"); err != nil {\n\t\treturn err\n\t}\n\tif b.GasUsed, err = decodeUint(v, \"gasUsed\"); err != nil {\n\t\treturn err\n\t}\n\tif err = decodeHash(&b.MixHash, v, \"mixHash\"); err != nil {\n\t\treturn err\n\t}\n\tif err = decodeNonce(&b.Nonce, v, \"nonce\"); err != nil {\n\t\treturn err\n\t}\n\tif b.Timestamp, err = decodeUint(v, \"timestamp\"); err != nil {\n\t\treturn err\n\t}\n\tif b.Difficulty, err = decodeBigInt(b.Difficulty, v, \"difficulty\"); err != nil {\n\t\treturn err\n\t}\n\tif b.ExtraData, err = decodeBytes(b.ExtraData[:0], v, \"extraData\"); err != nil {\n\t\treturn err\n\t}\n\tif b.BaseFee, err = decodeBigInt(b.BaseFee, v, \"baseFee\"); err != nil {\n\t\tif err.Error() != \"field 'baseFee' not found\" {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tb.TransactionsHashes = b.TransactionsHashes[:0]\n\tb.Transactions = b.Transactions[:0]\n\n\telems := v.GetArray(\"transactions\")\n\tif len(elems) != 0 {\n\t\tif elems[0].Type() == fastjson.TypeString {\n\t\t\t// hashes (non full block)\n\t\t\tfor _, elem := range elems {\n\t\t\t\tvar h Hash\n\t\t\t\tif err := h.UnmarshalText(elem.GetStringBytes()); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tb.TransactionsHashes = append(b.TransactionsHashes, h)\n\t\t\t}\n\t\t} else {\n\t\t\t// structs (full block)\n\t\t\tfor _, elem := range elems {\n\t\t\t\ttxn := new(Transaction)\n\t\t\t\tif err := txn.unmarshalJSON(elem); err != nil {\n\t\t\t\t\tpanic(err)\n\t\t\t\t}\n\t\t\t\tb.Transactions = append(b.Transactions, txn)\n\t\t\t}\n\t\t}\n\t}\n\n\t// uncles\n\tb.Uncles = b.Uncles[:0]\n\tfor _, elem := range v.GetArray(\"uncles\") {\n\t\tvar h Hash\n\t\tif err := h.UnmarshalText(elem.GetStringBytes()); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tb.Uncles = append(b.Uncles, h)\n\t}\n\n\treturn nil\n}\n\n// UnmarshalJSON implements the unmarshal interface\nfunc (t *Transaction) UnmarshalJSON(buf []byte) error {\n\tp := defaultPool.Get()\n\tdefer defaultPool.Put(p)\n\n\tv, err := p.Parse(string(buf))\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn t.unmarshalJSON(v)\n}\n\n// isKeySet is a helper function for checking if a key has any value != nil,\n// or if it's been set at all\nfunc isKeySet(v *fastjson.Value, key string) bool {\n\tvalue := v.Get(key)\n\treturn value != nil && value.Type() != fastjson.TypeNull\n}\n\nfunc (t *Transaction) unmarshalJSON(v *fastjson.Value) error {\n\texists := func(names ...string) error {\n\t\tfor _, name := range names {\n\t\t\tif !v.Exists(name) {\n\t\t\t\treturn fmt.Errorf(\"'%s' not found\", name)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\tif isKeySet(v, \"type\") {\n\t\ttxnType, err := decodeUint(v, \"type\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tt.Type = TransactionType(txnType)\n\t} else {\n\t\tif isKeySet(v, \"chainId\") {\n\t\t\tif isKeySet(v, \"maxFeePerGas\") {\n\t\t\t\tt.Type = TransactionDynamicFee\n\t\t\t} else {\n\t\t\t\tt.Type = TransactionAccessList\n\t\t\t}\n\t\t} else {\n\t\t\tt.Type = TransactionLegacy\n\t\t}\n\t}\n\n\tvar err error\n\tif err := decodeHash(&t.Hash, v, \"hash\"); err != nil {\n\t\treturn err\n\t}\n\tif err = decodeAddr(&t.From, v, \"from\"); err != nil {\n\t\treturn err\n\t}\n\tif t.Type == TransactionDynamicFee {\n\t\tif t.MaxPriorityFeePerGas, err = decodeBigInt(t.MaxPriorityFeePerGas, v, \"maxPriorityFeePerGas\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif t.MaxFeePerGas, err = decodeBigInt(t.MaxFeePerGas, v, \"maxFeePerGas\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else if t.Type == TransactionLegacy || t.Type == TransactionAccessList {\n\t\tif t.GasPrice, err = decodeUint(v, \"gasPrice\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif t.Input, err = decodeBytes(t.Input[:0], v, \"input\"); err != nil {\n\t\treturn err\n\t}\n\tif t.Value, err = decodeBigInt(t.Value, v, \"value\"); err != nil {\n\t\treturn err\n\t}\n\tif t.Nonce, err = decodeUint(v, \"nonce\"); err != nil {\n\t\treturn err\n\t}\n\n\t{\n\t\t// Do not decode 'to' if it doesn't exist.\n\t\tif err := exists(\"to\"); err == nil {\n\t\t\tif v.Get(\"to\").String() != \"null\" {\n\t\t\t\tvar to Address\n\t\t\t\tif err = decodeAddr(&to, v, \"to\"); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tt.To = &to\n\t\t\t}\n\t\t}\n\t}\n\n\tif t.V, err = decodeBytes(t.V[:0], v, \"v\"); err != nil {\n\t\treturn err\n\t}\n\tif t.R, err = decodeBytes(t.R[:0], v, \"r\"); err != nil {\n\t\treturn err\n\t}\n\tif t.S, err = decodeBytes(t.S[:0], v, \"s\"); err != nil {\n\t\treturn err\n\t}\n\n\tif t.Type == TransactionDynamicFee || t.Type == TransactionAccessList {\n\t\tif t.ChainID, err = decodeBigInt(t.ChainID, v, \"chainId\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif isKeySet(v, \"accessList\") {\n\t\t\tif err := t.AccessList.unmarshalJSON(v.Get(\"accessList\")); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\tif t.Gas, err = decodeUint(v, \"gas\"); err != nil {\n\t\treturn err\n\t}\n\n\t// Check if the block hash field is set\n\t// If it's not -> the transaction is a pending txn, so these fields should be omitted\n\t// If it is -> the transaction is a sealed txn, so these fields should be included\n\tif isKeySet(v, \"blockHash\") {\n\t\t// The transaction is not a pending transaction, read data\n\n\t\t// Grab the block hash\n\t\tif err = decodeHash(&t.BlockHash, v, \"blockHash\"); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Grab the block number\n\t\tif t.BlockNumber, err = decodeUint(v, \"blockNumber\"); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Grab the transaction index\n\t\tif t.TxnIndex, err = decodeUint(v, \"transactionIndex\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (t *AccessList) unmarshalJSON(v *fastjson.Value) error {\n\telems, err := v.Array()\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, elem := range elems {\n\t\tentry := AccessEntry{}\n\t\tif err = decodeAddr(&entry.Address, elem, \"address\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstorage, err := elem.Get(\"storageKeys\").Array()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tentry.Storage = make([]Hash, len(storage))\n\t\tfor indx, stg := range storage {\n\t\t\tb, err := stg.StringBytes()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := entry.Storage[indx].UnmarshalText(b); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\t*t = append(*t, entry)\n\t}\n\treturn nil\n}\n\n// UnmarshalJSON implements the unmarshal interface\nfunc (r *Receipt) UnmarshalJSON(buf []byte) error {\n\tp := defaultPool.Get()\n\tdefer defaultPool.Put(p)\n\n\tv, err := p.Parse(string(buf))\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tif err := decodeAddr(&r.From, v, \"from\"); err != nil {\n\t\treturn err\n\t}\n\tif fieldNotFull(v, \"contractAddress\") {\n\t\tif err := decodeAddr(&r.ContractAddress, v, \"contractAddress\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err := decodeHash(&r.TransactionHash, v, \"transactionHash\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&r.BlockHash, v, \"blockHash\"); err != nil {\n\t\treturn err\n\t}\n\tif r.TransactionIndex, err = decodeUint(v, \"transactionIndex\"); err != nil {\n\t\treturn err\n\t}\n\tif r.BlockNumber, err = decodeUint(v, \"blockNumber\"); err != nil {\n\t\treturn err\n\t}\n\tif r.GasUsed, err = decodeUint(v, \"gasUsed\"); err != nil {\n\t\treturn err\n\t}\n\tif r.CumulativeGasUsed, err = decodeUint(v, \"cumulativeGasUsed\"); err != nil {\n\t\treturn err\n\t}\n\tif r.LogsBloom, err = decodeBytes(r.LogsBloom[:0], v, \"logsBloom\", 256); err != nil {\n\t\treturn err\n\t}\n\tif v.Exists(\"status\") {\n\t\t// post-byzantium fork\n\t\tif r.Status, err = decodeUint(v, \"status\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif v.Exists(\"to\") {\n\t\t// Do not decode 'to' if it doesn't exist.\n\t\tif v.Get(\"to\").String() != \"null\" {\n\t\t\tvar to Address\n\t\t\tif err = decodeAddr(&to, v, \"to\"); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tr.To = &to\n\t\t}\n\t}\n\n\t// logs\n\tr.Logs = r.Logs[:0]\n\tfor _, elem := range v.GetArray(\"logs\") {\n\t\tlog := new(Log)\n\t\tif err := log.unmarshalJSON(elem); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tr.Logs = append(r.Logs, log)\n\t}\n\n\treturn nil\n}\n\nfunc (lf *LogFilter) UnmarshalJSON(buf []byte) error {\n\tp := defaultPool.Get()\n\tdefer defaultPool.Put(p)\n\n\tv, err := p.Parse(string(buf))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to parse input, %w\", err)\n\t}\n\n\t// Unmarshal the address field\n\tlf.Address = lf.Address[:0]\n\n\tappendAddress := func(addressRaw []byte) error {\n\t\taddress := new(Address)\n\t\tif err := address.UnmarshalText(addressRaw); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tlf.Address = append(lf.Address, *address)\n\n\t\treturn nil\n\t}\n\n\tfor _, addressValue := range v.GetArray(\"address\") {\n\t\taddressRaw, err := addressValue.StringBytes()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif err := appendAddress(addressRaw); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// The address field can also be a single value\n\tif addressRaw := v.GetStringBytes(\"address\"); addressRaw != nil {\n\t\tif err := appendAddress(addressRaw); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Unmarshal the block hash\n\tlf.BlockHash = nil\n\tif v.Exists(\"blockHash\") {\n\t\textractedHash := &Hash{}\n\t\tif err := decodeHash(extractedHash, v, \"blockHash\"); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tlf.BlockHash = extractedHash\n\t}\n\n\t// decodeBlockNum is a helper method for extracting a BlockNumber\n\tdecodeBlockNum := func(key string) (*BlockNumber, error) {\n\t\tnumRaw, err := decodeInt64(v, key)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tblockNum := BlockNumber(numRaw)\n\n\t\treturn &blockNum, nil\n\t}\n\n\t// Unmarshal the from field\n\tlf.From = nil\n\tif v.Exists(\"fromBlock\") {\n\t\tif lf.From, err = decodeBlockNum(\"fromBlock\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Unmarshal the to field\n\tlf.To = nil\n\tif v.Exists(\"toBlock\") {\n\t\tif lf.To, err = decodeBlockNum(\"toBlock\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Unmarshal the topics\n\tlf.Topics = lf.Topics[:0]\n\tfor _, topicsValue := range v.GetArray(\"topics\") {\n\t\t// Check if the index is set\n\t\tif topicsValue == nil || topicsValue.String() == \"null\" {\n\t\t\tlf.Topics = append(lf.Topics, nil)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tinnerTopics, err := topicsValue.Array()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tresTopics := make([]*Hash, 0)\n\t\tfor _, innerTopic := range innerTopics {\n\t\t\thashValRaw, err := innerTopic.StringBytes()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\thashVal := &Hash{}\n\t\t\tif err := hashVal.UnmarshalText(hashValRaw); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tresTopics = append(resTopics, hashVal)\n\t\t}\n\n\t\tlf.Topics = append(lf.Topics, resTopics)\n\t}\n\n\treturn nil\n}\n\n// UnmarshalJSON implements the unmarshal interface\nfunc (r *Log) UnmarshalJSON(buf []byte) error {\n\tp := defaultPool.Get()\n\tdefer defaultPool.Put(p)\n\n\tv, err := p.Parse(string(buf))\n\tif err != nil {\n\t\treturn nil\n\t}\n\treturn r.unmarshalJSON(v)\n}\n\nfunc (r *Log) unmarshalJSON(v *fastjson.Value) error {\n\tvar err error\n\tif v.Exists(\"removed\") {\n\t\t// it is empty in etherscan API endpoint\n\t\tif r.Removed, err = decodeBool(v, \"removed\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif r.LogIndex, err = decodeUint(v, \"logIndex\"); err != nil {\n\t\treturn err\n\t}\n\tif r.BlockNumber, err = decodeUint(v, \"blockNumber\"); err != nil {\n\t\treturn err\n\t}\n\tif r.TransactionIndex, err = decodeUint(v, \"transactionIndex\"); err != nil {\n\t\treturn err\n\t}\n\tif err := decodeHash(&r.TransactionHash, v, \"transactionHash\"); err != nil {\n\t\treturn err\n\t}\n\tif v.Exists(\"blockHash\") {\n\t\t// it is empty in etherscan API endpoint\n\t\tif err := decodeHash(&r.BlockHash, v, \"blockHash\"); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err := decodeAddr(&r.Address, v, \"address\"); err != nil {\n\t\treturn err\n\t}\n\tif r.Data, err = decodeBytes(r.Data[:0], v, \"data\"); err != nil {\n\t\treturn err\n\t}\n\n\tr.Topics = r.Topics[:0]\n\tfor _, topic := range v.GetArray(\"topics\") {\n\t\tvar t Hash\n\t\tb, err := topic.StringBytes()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := t.UnmarshalText(b); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tr.Topics = append(r.Topics, t)\n\t}\n\treturn nil\n}\n\nfunc fieldNotFull(v *fastjson.Value, key string) bool {\n\tvv := v.Get(key)\n\tif vv == nil {\n\t\treturn false\n\t}\n\tif vv.String() == \"null\" {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc decodeBigInt(b *big.Int, v *fastjson.Value, key string) (*big.Int, error) {\n\tvv := v.Get(key)\n\tif vv == nil {\n\t\treturn nil, fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\tstr := vv.String()\n\tstr = strings.Trim(str, \"\\\"\")\n\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn nil, fmt.Errorf(\"field '%s' does not have 0x prefix: '%s'\", key, str)\n\t}\n\tif b == nil {\n\t\tb = new(big.Int)\n\t}\n\n\tvar ok bool\n\tb, ok = b.SetString(str[2:], 16)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"field '%s' failed to decode big int: '%s'\", key, str)\n\t}\n\treturn b, nil\n}\n\nfunc decodeBytes(dst []byte, v *fastjson.Value, key string, bits ...int) ([]byte, error) {\n\tvv := v.Get(key)\n\tif vv == nil {\n\t\treturn nil, fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\tstr := vv.String()\n\tstr = strings.Trim(str, \"\\\"\")\n\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn nil, fmt.Errorf(\"field '%s' does not have 0x prefix: '%s'\", key, str)\n\t}\n\tstr = str[2:]\n\tif len(str)%2 != 0 {\n\t\tstr = \"0\" + str\n\t}\n\tbuf, err := hex.DecodeString(str)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(bits) > 0 && bits[0] != len(buf) {\n\t\treturn nil, fmt.Errorf(\"field '%s' invalid length, expected %d but found %d: %s\", key, bits[0], len(buf), str)\n\t}\n\tdst = append(dst, buf...)\n\treturn dst, nil\n}\n\nfunc decodeUint(v *fastjson.Value, key string) (uint64, error) {\n\tvv := v.Get(key)\n\tif vv == nil {\n\t\treturn 0, fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\tstr := vv.String()\n\tstr = strings.Trim(str, \"\\\"\")\n\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn 0, fmt.Errorf(\"field '%s' does not have 0x prefix: '%s'\", key, str)\n\t}\n\tstr = str[2:]\n\tif str == \"\" {\n\t\tstr = \"0\"\n\t}\n\n\tnum, err := strconv.ParseUint(str, 16, 64)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"field '%s' failed to decode uint: %s\", key, str)\n\t}\n\treturn num, nil\n}\n\nfunc decodeInt64(v *fastjson.Value, key string) (int64, error) {\n\tvv := v.Get(key)\n\tif vv == nil {\n\t\treturn 0, fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\tstr := vv.String()\n\tstr = strings.Trim(str, \"\\\"\")\n\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn 0, fmt.Errorf(\"field '%s' does not have 0x prefix: '%s'\", key, str)\n\t}\n\tstr = str[2:]\n\tif str == \"\" {\n\t\tstr = \"0\"\n\t}\n\n\tnum, err := strconv.ParseInt(str, 16, 64)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"field '%s' failed to decode int64: %s\", key, str)\n\t}\n\treturn num, nil\n}\n\nfunc decodeNonce(n *[8]byte, v *fastjson.Value, key string) error {\n\tb := v.GetStringBytes(key)\n\tif len(b) == 0 {\n\t\treturn fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\n\tif err := unmarshalTextByte(n[:], b, 8); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc decodeHash(h *Hash, v *fastjson.Value, key string) error {\n\tb := v.GetStringBytes(key)\n\tif len(b) == 0 {\n\t\treturn fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\n\t// Make sure the memory location is initialized\n\tif h == nil {\n\t\th = &Hash{}\n\t}\n\n\th.UnmarshalText(b)\n\treturn nil\n}\n\nfunc decodeAddr(a *Address, v *fastjson.Value, key string) error {\n\tb := v.GetStringBytes(key)\n\tif len(b) == 0 {\n\t\treturn fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\ta.UnmarshalText(b)\n\treturn nil\n}\n\nfunc decodeBool(v *fastjson.Value, key string) (bool, error) {\n\tvv := v.Get(key)\n\tif vv == nil {\n\t\treturn false, fmt.Errorf(\"field '%s' not found\", key)\n\t}\n\tstr := vv.String()\n\tif str == \"false\" {\n\t\treturn false, nil\n\t} else if str == \"true\" {\n\t\treturn true, nil\n\t}\n\treturn false, fmt.Errorf(\"field '%s' with content '%s' cannot be decoded as bool\", key, str)\n}\n\nfunc unmarshalTextByte(dst, src []byte, size int) error {\n\tstr := string(src)\n\n\tstr = strings.Trim(str, \"\\\"\")\n\tif !strings.HasPrefix(str, \"0x\") {\n\t\treturn fmt.Errorf(\"0x prefix not found\")\n\t}\n\tstr = str[2:]\n\tb, err := hex.DecodeString(str)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(b) != size {\n\t\treturn fmt.Errorf(\"length %d is not correct, expected %d\", len(b), size)\n\t}\n\tcopy(dst, b)\n\treturn nil\n}\n"
  },
  {
    "path": "testcases/accounts_test.go",
    "content": "package testcases\n\nimport (\n\t\"encoding/hex\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/wallet\"\n)\n\nfunc TestAccounts(t *testing.T) {\n\tvar walletSpec []struct {\n\t\tAddress    string  `json:\"address\"`\n\t\tChecksum   string  `json:\"checksumAddress\"`\n\t\tName       string  `json:\"name\"`\n\t\tPrivateKey *string `json:\"privateKey,omitempty\"`\n\t}\n\tReadTestCase(t, \"accounts\", &walletSpec)\n\n\tmsg := []byte(\"msg\")\n\n\tfor _, spec := range walletSpec {\n\t\t// test that an string address can be checksumed\n\t\taddr := ethgo.HexToAddress(spec.Address)\n\t\tassert.Equal(t, addr.String(), spec.Checksum)\n\n\t\tif spec.PrivateKey != nil {\n\t\t\t// test that we can decode the private key\n\t\t\tpriv, err := hex.DecodeString(strings.TrimPrefix(*spec.PrivateKey, \"0x\"))\n\t\t\tassert.NoError(t, err)\n\n\t\t\tkey, err := wallet.NewWalletFromPrivKey(priv)\n\t\t\tassert.NoError(t, err)\n\n\t\t\tassert.Equal(t, key.Address().String(), spec.Checksum)\n\n\t\t\t// test that we can sign and recover address\n\t\t\tsig, err := key.SignMsg(msg)\n\t\t\trequire.NoError(t, err)\n\n\t\t\trecoveredAddr, err := wallet.EcrecoverMsg(msg, sig)\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.Equal(t, recoveredAddr, addr)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "testcases/contract_test.go",
    "content": "package testcases\n\nimport (\n\t\"encoding/hex\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfunc TestContract_Signatures(t *testing.T) {\n\tvar signatures []struct {\n\t\tName      string `json:\"name\"`\n\t\tSignature string `json:\"signature\"`\n\t\tSigHash   string `json:\"sigHash\"`\n\t\tAbi       string `json:\"abi\"`\n\t}\n\tReadTestCase(t, \"contract-signatures\", &signatures)\n\n\tfor _, c := range signatures {\n\t\tm, err := abi.NewMethod(c.Signature)\n\t\tassert.NoError(t, err)\n\n\t\tsigHash := \"0x\" + hex.EncodeToString(m.ID())\n\t\tassert.Equal(t, sigHash, c.SigHash)\n\t}\n}\n\nfunc TestContract_Interface(t *testing.T) {\n\tt.Skip()\n\n\tserver := testutil.NewTestServer(t)\n\n\tvar calls []struct {\n\t\tName      string         `json:\"name\"`\n\t\tInterface string         `json:\"interface\"`\n\t\tBytecode  ethgo.ArgBytes `json:\"bytecode\"`\n\t\tResult    ethgo.ArgBytes `json:\"result\"`\n\t\tValues    string         `json:\"values\"`\n\t}\n\tReadTestCase(t, \"contract-interface\", &calls)\n\n\tfor _, c := range calls {\n\t\ta, err := abi.NewABI(c.Interface)\n\t\tassert.NoError(t, err)\n\n\t\tmethod := a.GetMethod(\"test\")\n\n\t\treceipt, err := server.SendTxn(&ethgo.Transaction{\n\t\t\tInput: c.Bytecode.Bytes(),\n\t\t})\n\t\tassert.NoError(t, err)\n\n\t\toutputRaw, err := server.Call(&ethgo.CallMsg{\n\t\t\tTo:   &receipt.ContractAddress,\n\t\t\tData: method.ID(),\n\t\t})\n\t\tassert.NoError(t, err)\n\n\t\toutput, err := hex.DecodeString(outputRaw[2:])\n\t\tassert.NoError(t, err)\n\n\t\t_, err = method.Decode(output)\n\t\tassert.NoError(t, err)\n\t}\n\n}\n"
  },
  {
    "path": "testcases/eip712_test.go",
    "content": "package testcases\n\nimport (\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo/signing\"\n)\n\ntype eip712Testcase struct {\n\tName   string\n\tDomain struct {\n\t\tName              *string\n\t\tVersion           *string\n\t\tVerifyingContract *string\n\t\tChainId           *uint64\n\t\tSalt              *string\n\t}\n\tType        string\n\tSeed        string\n\tPrimaryType string\n\tTypes       map[string][]*signing.EIP712Type\n\tData        map[string]interface{}\n\tEncoded     string\n\tDigest      string\n}\n\nfunc (e *eip712Testcase) getDomain() *signing.EIP712Domain {\n\td := &signing.EIP712Domain{}\n\n\tif name := e.Domain.Name; name != nil {\n\t\td.Name = *name\n\t}\n\tif version := e.Domain.Version; version != nil {\n\t\td.Version = *version\n\t}\n\tif contract := e.Domain.VerifyingContract; contract != nil {\n\t\td.VerifyingContract = *contract\n\t}\n\tif chain := e.Domain.ChainId; chain != nil {\n\t\td.ChainId = new(big.Int).SetUint64(*chain)\n\t}\n\tif salt := e.Domain.Salt; salt != nil {\n\t\tbuf, _ := hex.DecodeString((*salt)[2:])\n\t\td.Salt = buf\n\t}\n\n\treturn d\n}\n\nfunc TestEIP712(t *testing.T) {\n\tvar cases []eip712Testcase\n\tReadTestCase(t, \"eip712\", &cases)\n\n\tfor indx, c := range cases {\n\t\ttypedData := &signing.EIP712TypedData{\n\t\t\tTypes:       c.Types,\n\t\t\tPrimaryType: c.PrimaryType,\n\t\t\tDomain:      c.getDomain(),\n\t\t\tMessage:     c.Data,\n\t\t}\n\n\t\tdigest, err := typedData.Hash()\n\t\trequire.NoError(t, err)\n\n\t\tif c.Digest != \"0x\"+hex.EncodeToString(digest) {\n\t\t\tt.Fatalf(\"wrong digest: %d\", indx)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "testcases/package.json",
    "content": "{\n  \"name\": \"testsuite\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@ethersproject/testcases\": \"^5.6.0\"\n  }\n}\n"
  },
  {
    "path": "testcases/transaction_test.go",
    "content": "package testcases\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/wallet\"\n)\n\nfunc getUint64FromBigInt(b *ethgo.ArgBig) (uint64, bool) {\n\tg := (*big.Int)(b)\n\tif !g.IsUint64() {\n\t\treturn 0, false\n\t}\n\treturn g.Uint64(), true\n}\n\nfunc TestTransactions(t *testing.T) {\n\tvar transactions []struct {\n\t\tName              string         `json:\"name\"`\n\t\tAccountAddress    ethgo.Address  `json:\"accountAddress\"`\n\t\tPrivateKey        ethgo.ArgBytes `json:\"privateKey\"`\n\t\tSignedTransaction ethgo.ArgBytes `json:\"signedTransactionChainId5\"`\n\n\t\tData     *ethgo.ArgBytes  `json:\"data,omitempty\"`\n\t\tValue    *ethgo.ArgBig    `json:\"value,omitempty\"`\n\t\tTo       *ethgo.Address   `json:\"to,omitempty\"`\n\t\tGasLimit *ethgo.ArgBig    `json:\"gasLimit,omitempty\"`\n\t\tNonce    *ethgo.ArgUint64 `json:\"nonce,omitempty\"`\n\t\tGasPrice *ethgo.ArgBig    `json:\"gasPrice,omitempty\"`\n\t}\n\tReadTestCase(t, \"transactions\", &transactions)\n\n\tfor _, c := range transactions {\n\t\tkey, err := wallet.NewWalletFromPrivKey(c.PrivateKey)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, key.Address(), c.AccountAddress)\n\n\t\ttxn := &ethgo.Transaction{\n\t\t\tChainID: big.NewInt(5),\n\t\t}\n\t\tif c.Data != nil {\n\t\t\ttxn.Input = *c.Data\n\t\t}\n\t\tif c.Value != nil {\n\t\t\ttxn.Value = (*big.Int)(c.Value)\n\t\t}\n\t\tif c.To != nil {\n\t\t\ttxn.To = c.To\n\t\t}\n\t\tif c.GasLimit != nil {\n\t\t\tgasLimit, isUint64 := getUint64FromBigInt(c.GasLimit)\n\t\t\tif !isUint64 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttxn.Gas = gasLimit\n\t\t}\n\t\tif c.Nonce != nil {\n\t\t\ttxn.Nonce = c.Nonce.Uint64()\n\t\t}\n\t\tif c.GasPrice != nil {\n\t\t\tgasPrice, isUint64 := getUint64FromBigInt(c.GasPrice)\n\t\t\tif !isUint64 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttxn.GasPrice = gasPrice\n\t\t}\n\n\t\tsigner := wallet.NewEIP155Signer(5)\n\t\tsignedTxn, err := signer.SignTx(txn, key)\n\t\tassert.NoError(t, err)\n\n\t\ttxnRaw, err := signedTxn.MarshalRLPTo(nil)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, txnRaw, c.SignedTransaction.Bytes())\n\n\t\tsender, err := signer.RecoverSender(signedTxn)\n\t\trequire.NoError(t, err)\n\t\trequire.Equal(t, sender, key.Address())\n\t}\n}\n\nfunc TestTypedTransactions(t *testing.T) {\n\tvar transactions []struct {\n\t\tName           string         `json:\"name\"`\n\t\tAccountAddress ethgo.Address  `json:\"address\"`\n\t\tKey            ethgo.ArgBytes `json:\"key\"`\n\t\tSigned         ethgo.ArgBytes `json:\"signed\"`\n\n\t\tTx struct {\n\t\t\tType                 ethgo.TransactionType\n\t\t\tData                 *ethgo.ArgBytes  `json:\"data,omitempty\"`\n\t\t\tGasLimit             *ethgo.ArgBig    `json:\"gasLimit,omitempty\"`\n\t\t\tMaxPriorityFeePerGas *ethgo.ArgBig    `json:\"maxPriorityFeePerGas,omitempty\"`\n\t\t\tMaxFeePerGas         *ethgo.ArgBig    `json:\"maxFeePerGas,omitempty\"`\n\t\t\tNonce                uint64           `json:\"nonce,omitempty\"`\n\t\t\tTo                   *ethgo.Address   `json:\"to,omitempty\"`\n\t\t\tValue                *ethgo.ArgBig    `json:\"value,omitempty\"`\n\t\t\tGasPrice             *ethgo.ArgBig    `json:\"gasPrice,omitempty\"`\n\t\t\tChainID              uint64           `json:\"chainId,omitempty\"`\n\t\t\tAccessList           ethgo.AccessList `json:\"accessList,omitempty\"`\n\t\t}\n\t}\n\tReadTestCase(t, \"typed-transactions\", &transactions)\n\n\tfor _, c := range transactions {\n\t\tkey, err := wallet.NewWalletFromPrivKey(c.Key)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, key.Address(), c.AccountAddress)\n\n\t\tchainID := big.NewInt(int64(c.Tx.ChainID))\n\n\t\ttxn := &ethgo.Transaction{\n\t\t\tChainID:              chainID,\n\t\t\tType:                 c.Tx.Type,\n\t\t\tMaxPriorityFeePerGas: (*big.Int)(c.Tx.MaxPriorityFeePerGas),\n\t\t\tMaxFeePerGas:         (*big.Int)(c.Tx.MaxFeePerGas),\n\t\t\tAccessList:           c.Tx.AccessList,\n\t\t}\n\t\tif c.Tx.Data != nil {\n\t\t\ttxn.Input = *c.Tx.Data\n\t\t}\n\t\tif c.Tx.Value != nil {\n\t\t\ttxn.Value = (*big.Int)(c.Tx.Value)\n\t\t}\n\t\tif c.Tx.To != nil {\n\t\t\ttxn.To = c.Tx.To\n\t\t}\n\t\tif c.Tx.GasLimit != nil {\n\t\t\tgasLimit, isUint64 := getUint64FromBigInt(c.Tx.GasLimit)\n\t\t\tif !isUint64 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttxn.Gas = gasLimit\n\t\t}\n\t\ttxn.Nonce = c.Tx.Nonce\n\t\tif c.Tx.GasPrice != nil {\n\t\t\tgasPrice, isUint64 := getUint64FromBigInt(c.Tx.GasPrice)\n\t\t\tif !isUint64 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttxn.GasPrice = gasPrice\n\t\t}\n\n\t\tsigner := wallet.NewEIP155Signer(chainID.Uint64())\n\t\tsignedTxn, err := signer.SignTx(txn, key)\n\t\tassert.NoError(t, err)\n\n\t\ttxnRaw, err := signedTxn.MarshalRLPTo(nil)\n\t\tassert.NoError(t, err)\n\n\t\tassert.Equal(t, txnRaw, c.Signed.Bytes())\n\n\t\tsender, err := signer.RecoverSender(signedTxn)\n\t\trequire.NoError(t, err)\n\t\trequire.Equal(t, sender, key.Address())\n\t}\n}\n"
  },
  {
    "path": "testcases/util.go",
    "content": "package testcases\n\nimport (\n\t\"compress/gzip\"\n\t\"encoding/json\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc ReadTestCase(t *testing.T, name string, target interface{}) {\n\t_, b, _, _ := runtime.Caller(0)\n\td := path.Join(path.Dir(b))\n\n\ttestsuiteDir := filepath.Join(filepath.Dir(d), \"testcases\", \"node_modules\")\n\tif _, err := os.Stat(testsuiteDir); os.IsNotExist(err) {\n\t\tt.Skip(\"testcases not downloaded\")\n\t}\n\n\tpath := filepath.Join(testsuiteDir, \"@ethersproject/testcases/testcases\", name+\".json.gz\")\n\n\tf, err := os.Open(path)\n\tassert.NoError(t, err)\n\n\tzr, err := gzip.NewReader(f)\n\tassert.NoError(t, err)\n\n\tdecoder := json.NewDecoder(zr)\n\tassert.NoError(t, decoder.Decode(target))\n}\n"
  },
  {
    "path": "testsuite/arbitrum-block-full.json",
    "content": "{\n    \"baseFeePerGas\": \"0x5f5e100\",\n    \"difficulty\": \"0x1\",\n    \"extraData\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n    \"gasLimit\": \"0x4000000000000\",\n    \"gasUsed\": \"0xac938d\",\n    \"hash\": \"0xc4cfe190b18fa6cfc6f80e5e0df16fdc78c054e750b98caf952443e653cc5049\",\n    \"l1BlockNumber\": \"0x4c62e8\",\n    \"logsBloom\": \"0x00000000000000000000040000008000000000000000000000001000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000040000000000000000000000000000000000000000000000400000000000000000000000000000000000100000000000000000000080000000000004000000000000000000000000000010000000000000000000000000000000000000000000000000000000000028000000000000000000000000200000000000002000000000000000004000000000\",\n    \"miner\": \"0xc573c69f8f638d2954c9618b03765fc17701a1e0\",\n    \"mixHash\": \"0x000000000000000000000000004c62e8000000000000000a0000000000000000\",\n    \"nonce\": \"0x0000000000000002\",\n    \"number\": \"0x1\",\n    \"parentHash\": \"0xde35c12458419b05d0250becd32113a6ceee6788b66fcdc8552ce97b5532c770\",\n    \"receiptsRoot\": \"0x8067122eda9f9c348c529d16c6c25a78538ec7e41ff175bbedaba74f89ffe94b\",\n    \"sendCount\": \"0x0\",\n    \"sendRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n    \"sha3Uncles\": \"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\n    \"size\": \"0xc271\",\n    \"stateRoot\": \"0x99228a91d977cd3a0de4a864b680f8d1b4a2a05a7de3a5d7839f1c5cf4689099\",\n    \"timestamp\": \"0x6593e174\",\n    \"totalDifficulty\": \"0x2\",\n    \"transactions\": [\n        {\n            \"blockHash\": \"0xc4cfe190b18fa6cfc6f80e5e0df16fdc78c054e750b98caf952443e653cc5049\",\n            \"blockNumber\": \"0x1\",\n            \"from\": \"0x00000000000000000000000000000000000a4b05\",\n            \"gas\": \"0x0\",\n            \"gasPrice\": \"0x0\",\n            \"hash\": \"0x3572220ffdd1ca5c613894c630a2e77e590525ef26e1bfc19a295a2fd55b1084\",\n            \"input\": \"0x6bf6a42d0000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000004c62e80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006593e174\",\n            \"nonce\": \"0x0\",\n            \"to\": \"0x00000000000000000000000000000000000a4b05\",\n            \"transactionIndex\": \"0x0\",\n            \"value\": \"0x0\",\n            \"type\": \"0x6a\",\n            \"chainId\": \"0xda8c8b77\",\n            \"v\": \"0x0\",\n            \"r\": \"0x0\",\n            \"s\": \"0x0\"\n        },\n        {\n            \"blockHash\": \"0xc4cfe190b18fa6cfc6f80e5e0df16fdc78c054e750b98caf952443e653cc5049\",\n            \"blockNumber\": \"0x1\",\n            \"from\": \"0xc573c69f8f638d2954c9618b03765fc17701a1e0\",\n            \"gas\": \"0x5b8d80\",\n            \"gasPrice\": \"0x5f5e100\",\n            \"maxFeePerGas\": \"0x5f5e100\",\n            \"hash\": \"0x07fcc2df6293de1451ca79c4299ff16845d2572a41985a0426806aeb09b22d23\",\n            \"input\": \"0xc9f95d3200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000022f250524940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000005b8d8000000000000000000000000000000000000000000000000000000d72a2471400000000000000000000000000bee947aec820389c1560c87bd96e2723bad05b61000000000000000000000000bee947aec820389c1560c87bd96e2723bad05b61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000005f5a608060405234801561001057600080fd5b50615f3a806100206000396000f3fe60806040523480156200001157600080fd5b50600436106200002e5760003560e01c8063b1c7a8701462000033575b600080fd5b6200004a6200004436600462001528565b6200004c565b005b6000620000b9620000866040518060400160405280601181526020017027b93134ba2619283937bc3ca0b236b4b760791b81525062000304565b6040516200009760208201620014b8565b6020820181038252601f19601f8201166040525080519060200120306200033a565b90506001600160a01b0381163b15620000e5576040516377e0068560e11b815260040160405180910390fd5b5060006200011c6040518060400160405280601181526020017027b93134ba2619283937bc3ca0b236b4b760791b81525062000304565b6040516200012a90620014b8565b8190604051809103906000f59050801580156200014b573d6000803e3d6000fd5b50905060006200016c6200016360a08d018d62001603565b86858762000364565b9050600062000189620001808d8062001603565b8d898762000689565b9050620001a86200019e60208e018e62001603565b8c8487876200088c565b620001c4620001bb60408e018e62001603565b8b848762000cb4565b6001600160a01b03881615620002035762000203620001e760608e018e62001603565b8e8060800190620001f9919062001603565b8c8c878a62000ef4565b6200029360006200023c6040518060400160405280601081526020016f13dc989a5d130c935d5b1d1a58d85b1b60821b81525062000304565b6200028d8f8060c0019062000252919062001603565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b6200131c565b5060405163f2fde38b60e01b81526001600160a01b0384169063f2fde38b90620002c290859060040162001654565b600060405180830381600087803b158015620002dd57600080fd5b505af1158015620002f2573d6000803e3d6000fd5b50505050505050505050505050505050565b60008146336040516020016200031d939291906200168e565b604051602081830303815290604052805190602001209050919050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b600080620003f084620003ac6040518060400160405280601b81526020017f4f726269744c32557067726164654578656375746f7250726f7879000000000081525062000304565b620003ea6040518060400160405280601b81526020017a4f726269744c32557067726164654578656375746f724c6f67696360281b81525062000304565b6200142d565b90506000620004796000620004386040518060400160405280601b81526020017a4f726269744c32557067726164654578656375746f724c6f67696360281b81525062000304565b6200028d8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038616906399a88ec490620004ac9085908590600401620016c9565b600060405180830381600087803b158015620004c757600080fd5b505af1158015620004dc573d6000803e3d6000fd5b5060009250829150620004ec9050565b60405190808252806020026020018201604052801562000516578160200160208202803683370190505b5060405163251b648160e21b81529091506001600160a01b0383169063946d9204906200054c9061dead908590600401620016e3565b600060405180830381600087803b1580156200056757600080fd5b505af11580156200057c573d6000803e3d6000fd5b5060009250600291506200058d9050565b604051908082528060200260200182016040528015620005b7578160200160208202803683370190505b5090508781600081518110620005d157620005d162001741565b60200260200101906001600160a01b031690816001600160a01b031681525050858160018151811062000608576200060862001741565b6001600160a01b03928316602091820292909201015260405163251b648160e21b81529085169063946d920490620006479087908590600401620016e3565b600060405180830381600087803b1580156200066257600080fd5b505af115801562000677573d6000803e3d6000fd5b50959c9b505050505050505050505050565b6000806200070983620006cd604051806040016040528060198152602001784f726269744c3247617465776179526f7574657250726f787960381b81525062000304565b620003ea604051806040016040528060198152602001784f726269744c3247617465776179526f757465724c6f67696360381b81525062000304565b905060006200074f600062000438604051806040016040528060198152602001784f726269744c3247617465776179526f757465724c6f67696360381b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038516906399a88ec490620007829085908590600401620016c9565b600060405180830381600087803b1580156200079d57600080fd5b505af1158015620007b2573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038416925063485cc9559150620007e89061dead908190600401620016c9565b600060405180830381600087803b1580156200080357600080fd5b505af115801562000818573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038516925063485cc95591506200084c9089908990600401620016c9565b600060405180830381600087803b1580156200086757600080fd5b505af11580156200087c573d6000803e3d6000fd5b50939a9950505050505050505050565b60006200091183620008d36040518060400160405280601b81526020017f4f726269744c325374616e646172644761746577617950726f7879000000000081525062000304565b620003ea6040518060400160405280601b81526020017a4f726269744c325374616e64617264476174657761794c6f67696360281b81525062000304565b90506000620009596000620004386040518060400160405280601b81526020017a4f726269744c325374616e64617264476174657761794c6f67696360281b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038516906399a88ec4906200098c9085908590600401620016c9565b600060405180830381600087803b158015620009a757600080fd5b505af1158015620009bc573d6000803e3d6000fd5b505060405163c0c53b8b60e01b81526001600160a01b038416925063c0c53b8b9150620009f49061dead908190819060040162001757565b600060405180830381600087803b15801562000a0f57600080fd5b505af115801562000a24573d6000803e3d6000fd5b50505050600062000a626040518060400160405280601581526020017404f726269745374616e64617264417262455243323605c1b81525062000304565b60405162000a7090620014c6565b8190604051809103906000f590508015801562000a91573d6000803e3d6000fd5b509050600062000acf6040518060400160405280601681526020017527b93134ba2ab833b930b232b0b13632a132b0b1b7b760511b81525062000304565b8260405162000ade90620014d4565b62000aea919062001654565b8190604051809103906000f590508015801562000b0b573d6000803e3d6000fd5b509050600062000b4a604051806040016040528060178152602001764f72626974426561636f6e50726f7879466163746f727960481b81525062000304565b60405162000b5890620014e2565b8190604051809103906000f590508015801562000b79573d6000803e3d6000fd5b5060405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de89062000bab90859060040162001654565b600060405180830381600087803b15801562000bc657600080fd5b505af115801562000bdb573d6000803e3d6000fd5b505060405163c0c53b8b60e01b81526001600160a01b038816925063c0c53b8b915062000c11908c908c90869060040162001757565b600060405180830381600087803b15801562000c2c57600080fd5b505af115801562000c41573d6000803e3d6000fd5b505060405163f2fde38b60e01b81526001600160a01b038516925063f2fde38b915062000c7390899060040162001654565b600060405180830381600087803b15801562000c8e57600080fd5b505af115801562000ca3573d6000803e3d6000fd5b505050505050505050505050505050565b600062000d338262000cf7604051806040016040528060198152602001784f726269744c32437573746f6d4761746577617950726f787960381b81525062000304565b620003ea604051806040016040528060198152602001784f726269744c32437573746f6d476174657761794c6f67696360381b81525062000304565b9050600062000dba600062000d79604051806040016040528060198152602001784f726269744c32437573746f6d476174657761794c6f67696360381b81525062000304565b6200028d8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038416906399a88ec49062000ded9085908590600401620016c9565b600060405180830381600087803b15801562000e0857600080fd5b505af115801562000e1d573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038416925063485cc955915062000e539061dead908190600401620016c9565b600060405180830381600087803b15801562000e6e57600080fd5b505af115801562000e83573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038516925063485cc955915062000eb79088908890600401620016c9565b600060405180830381600087803b15801562000ed257600080fd5b505af115801562000ee7573d6000803e3d6000fd5b5050505050505050505050565b600062000f5c8262000f2e6040518060400160405280601081526020016f4f726269744c325745544850726f787960801b81525062000304565b620003ea6040518060400160405280600b81526020016a09ee4c4d2e89864ae8aa8960ab1b81525062000304565b9050600062000f946000620004386040518060400160405280600b81526020016a09ee4c4d2e89864ae8aa8960ab1b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038416906399a88ec49062000fc79085908590600401620016c9565b600060405180830381600087803b15801562000fe257600080fd5b505af115801562000ff7573d6000803e3d6000fd5b50505050600062001076846200103c604051806040016040528060178152602001764f726269744c32576574684761746577617950726f787960481b81525062000304565b620003ea604051806040016040528060178152602001764f726269744c3257657468476174657761794c6f67696360481b81525062000304565b90506000620010fb6000620010ba604051806040016040528060178152602001764f726269744c3257657468476174657761794c6f67696360481b81525062000304565b6200028d8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038616906399a88ec4906200112e9085908590600401620016c9565b600060405180830381600087803b1580156200114957600080fd5b505af11580156200115e573d6000803e3d6000fd5b5050604051637c643b2f60e11b81526001600160a01b038416925063f8c8765e9150620011989061dead908190819081906004016200177a565b600060405180830381600087803b158015620011b357600080fd5b505af1158015620011c8573d6000803e3d6000fd5b5050604051637c643b2f60e11b81526001600160a01b038516925063f8c8765e915062001200908b908a908c908a906004016200177a565b600060405180830381600087803b1580156200121b57600080fd5b505af115801562001230573d6000803e3d6000fd5b505060405163641078a360e11b815260a06004820152600060a4820181905260c0602483015260c48201819052604482015261dead6064820181905260848201526001600160a01b038616925063c820f146915060e401600060405180830381600087803b158015620012a257600080fd5b505af1158015620012b7573d6000803e3d6000fd5b505060405163641078a360e11b81526001600160a01b038716925063c820f1469150620002c29060129086908c90600401620017bc565b6060815182604051602001620013069291906200180b565b6040516020818303038152906040529050919050565b600083471015620013745760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b8151600003620013c75760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016200136b565b8282516020840186f590506001600160a01b038116620014265760405162461bcd60e51b8152602060048201526019602482015278437265617465323a204661696c6564206f6e206465706c6f7960381b60448201526064016200136b565b9392505050565b600082826040516200143f90620014f0565b8190604051809103906000f590508015801562001460573d6000803e3d6000fd5b5085604051806020016040528060008152506040516200148090620014fd565b6200148e939291906200187b565b8190604051809103906000f5905080158015620014af573d6000803e3d6000fd5b50949350505050565b61070f80620018cb83390190565b611e7e8062001fda83390190565b6104e28062003e5883390190565b610cb4806200433a83390190565b605c8062004fee83390190565b610ebb806200504a83390190565b80356001600160a01b03811681146200152357600080fd5b919050565b60008060008060008060008060006101208a8c0312156200154857600080fd5b893567ffffffffffffffff8111156200156057600080fd5b8a0160e0818d0312156200157357600080fd5b98506200158360208b016200150b565b97506200159360408b016200150b565b9650620015a360608b016200150b565b9550620015b360808b016200150b565b9450620015c360a08b016200150b565b9350620015d360c08b016200150b565b9250620015e360e08b016200150b565b9150620015f46101008b016200150b565b90509295985092959850929598565b6000808335601e198436030181126200161b57600080fd5b83018035915067ffffffffffffffff8211156200163757600080fd5b6020019150368190038213156200164d57600080fd5b9250929050565b6001600160a01b0391909116815260200190565b60005b83811015620016855781810151838201526020016200166b565b50506000910152565b60008451620016a281846020890162001668565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156200173357855185168352948301949183019160010162001713565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b60048152630ae8aa8960e31b602082015260400190565b60a081526000620017d060a08301620017a5565b8281036020840152620017e381620017a5565b60ff96909616604084015250506001600160a01b039283166060820152911660809091015290565b710608060405234801561001057600080fd5b560741b8152606160f81b601282015260f083901b6001600160f01b03191660138201526a4030801030001cb00079ff60a91b601582015281516000906200186d81602080860190870162001668565b919091016020019392505050565b600060018060a01b038086168352808516602084015250606060408301528251806060840152620018b481608085016020870162001668565b601f01601f19169190910160800194935050505056fe608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6106918061007e6000396000f3fe60806040526004361061006b5760003560e01c8063204e1c7a14610070578063715018a6146100a65780637eff275e146100bd5780638da5cb5b146100dd5780639623609d146100fb57806399a88ec41461010e578063f2fde38b1461012e578063f3b7dead1461014e575b600080fd5b34801561007c57600080fd5b5061009061008b366004610483565b61016e565b60405161009d91906104a7565b60405180910390f35b3480156100b257600080fd5b506100bb6101ff565b005b3480156100c957600080fd5b506100bb6100d83660046104bb565b610213565b3480156100e957600080fd5b506000546001600160a01b0316610090565b6100bb61010936600461050a565b61027d565b34801561011a57600080fd5b506100bb6101293660046104bb565b6102ec565b34801561013a57600080fd5b506100bb610149366004610483565b610320565b34801561015a57600080fd5b50610090610169366004610483565b61039e565b6000806000836001600160a01b031660405161019490635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101cf576040519150601f19603f3d011682016040523d82523d6000602084013e6101d4565b606091505b5091509150816101e357600080fd5b808060200190518101906101f791906105e0565b949350505050565b6102076103c4565b610211600061041e565b565b61021b6103c4565b6040516308f2839760e41b81526001600160a01b03831690638f283970906102479084906004016104a7565b600060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050505050565b6102856103c4565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102b590869086906004016105fd565b6000604051808303818588803b1580156102ce57600080fd5b505af11580156102e2573d6000803e3d6000fd5b5050505050505050565b6102f46103c4565b604051631b2ce7f360e11b81526001600160a01b03831690633659cfe6906102479084906004016104a7565b6103286103c4565b6001600160a01b0381166103925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61039b8161041e565b50565b6000806000836001600160a01b0316604051610194906303e1469160e61b815260040190565b6000546001600160a01b031633146102115760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610389565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461039b57600080fd5b60006020828403121561049557600080fd5b81356104a08161046e565b9392505050565b6001600160a01b0391909116815260200190565b600080604083850312156104ce57600080fd5b82356104d98161046e565b915060208301356104e98161046e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561051f57600080fd5b833561052a8161046e565b9250602084013561053a8161046e565b9150604084013567ffffffffffffffff8082111561055757600080fd5b818601915086601f83011261056b57600080fd5b81358181111561057d5761057d6104f4565b604051601f8201601f19908116603f011681019083821181831017156105a5576105a56104f4565b816040528281528960208487010111156105be57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156105f257600080fd5b81516104a08161046e565b60018060a01b038316815260006020604081840152835180604085015260005b818110156106395785810183015185820160600152820161061d565b506000606082860101526060601f19601f83011685010192505050939250505056fea26469706673582212208a2d9d6b4833462246845f0898b3da66a9086b54eb9fb2d870a9780af5c177f664736f6c6343000810003360806040523480156200001157600080fd5b50600054610100900460ff1615808015620000335750600054600160ff909116105b8062000063575062000050306200015060201b620007b71760201c565b15801562000063575060005460ff166001145b620000cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000ef576000805461ff0019166101001790555b801562000136576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5060cd805460ff60a01b1916600160a01b1790556200015f565b6001600160a01b03163b151590565b611d0f806200016f6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806370a08231116100b857806395d89b411161007c57806395d89b411461029e578063a457c2d7146102a6578063a9059cbb146102b9578063c2eeeebd146102cc578063d505accf146102df578063dd62ed3e146102f257600080fd5b806370a082311461021157806374f4f5471461023a5780637ecebe001461024d5780638c2a993e146102605780638fa74a0e1461027357600080fd5b8063313ce567116100ff578063313ce567146101b75780633644e515146101d157806339509351146101d95780634000aea0146101ec5780636f791d29146101ff57600080fd5b806306fdde031461013c578063095ea7b31461015a57806318160ddd1461017d578063189db7d21461018f57806323b872dd146101a4575b600080fd5b610144610305565b604051610151919061162e565b60405180910390f35b61016d61016836600461165d565b61032a565b6040519015158152602001610151565b6035545b604051908152602001610151565b6101a261019d36600461174a565b610344565b005b61016d6101b2366004611797565b6103fb565b6101bf610421565b60405160ff9091168152602001610151565b61018161043e565b61016d6101e736600461165d565b610448565b61016d6101fa3660046117d3565b61046a565b60cd54600160a01b900460ff1661016d565b61018161021f366004611829565b6001600160a01b031660009081526033602052604090205490565b6101a261024836600461165d565b6104e0565b61018161025b366004611829565b610521565b6101a261026e36600461165d565b61053f565b60cc54610286906001600160a01b031681565b6040516001600160a01b039091168152602001610151565b610144610573565b61016d6102b436600461165d565b610594565b61016d6102c736600461165d565b61061a565b60cd54610286906001600160a01b031681565b6101a26102ed366004611844565b610628565b6101816103003660046118b7565b61078c565b60ce54606090610100900460ff161561031d57600080fd5b6103256107c6565b905090565b600033610338818585610858565b60019150505b92915050565b60008060008380602001905181019061035d919061193a565b92509250925060008061036f8561097d565b9150915060008061037f8661097d565b9150915060008061038f87610b06565b915091506103a0858483338f610b55565b506040805160608101825291158083529515602083018190529315910181905260ce805461ffff191661ff0019909616959095176101009093029290921762ff00001916620100009092029190911790925550505050505050565b600033610409858285610c27565b610414858585610ca1565b60019150505b9392505050565b60ce5460009060ff161561043457600080fd5b5060385460ff1690565b6000610325610e3a565b60003361033881858561045b838361078c565b61046591906119cd565b610858565b6000610476848461061a565b50836001600160a01b0316336001600160a01b03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1685856040516104bc9291906119e0565b60405180910390a3833b156104d6576104d6848484610eb5565b5060019392505050565b60cc546001600160a01b031633146105135760405162461bcd60e51b815260040161050a90611a01565b60405180910390fd5b61051d8282610f1f565b5050565b6001600160a01b03811660009081526099602052604081205461033e565b60cc546001600160a01b031633146105695760405162461bcd60e51b815260040161050a90611a01565b61051d828261103e565b60ce5460609062010000900460ff161561058c57600080fd5b6103256110ed565b600033816105a2828661078c565b9050838110156106025760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161050a565b61060f8286868403610858565b506001949350505050565b600033610338818585610ca1565b834211156106785760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161050a565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886106a78c6110fc565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e001604051602081830303815290604052805190602001209050600061070282611124565b9050600061071282878787611172565b9050896001600160a01b0316816001600160a01b0316146107755760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161050a565b6107808a8a8a610858565b50505050505050505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6001600160a01b03163b151590565b6060603680546107d590611a27565b80601f016020809104026020016040519081016040528092919081815260200182805461080190611a27565b801561084e5780601f106108235761010080835404028352916020019161084e565b820191906000526020600020905b81548152906001019060200180831161083157829003601f168201915b5050505050905090565b6001600160a01b0383166108ba5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161050a565b6001600160a01b03821661091b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161050a565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000606082516000036109935760009150915091565b8251602003610ae65782516000908490601f9081106109b4576109b4611a5b565b01602001516001600160f81b031916146109d15760009150915091565b6001915060205b600081118015610a1257506000846109f1600184611a71565b81518110610a0157610a01611a5b565b01602001516001600160f81b031916145b15610a295780610a2181611a84565b9150506109d8565b6000816001600160401b03811115610a4357610a43611687565b6040519080825280601f01601f191660200182016040528015610a6d576020820181803683370190505b50905060005b828160ff161015610adc57858160ff1681518110610a9357610a93611a5b565b602001015160f81c60f81b828260ff1681518110610ab357610ab3611a5b565b60200101906001600160f81b031916908160001a90535080610ad481611a9b565b915050610a73565b509150610b019050565b6001915082806020019051810190610afe9190611aba565b90505b915091565b6000808251602014610b1d57506000928392509050565b600083806020019051810190610b339190611b02565b905060ff811115610b4a5750600093849350915050565b600194909350915050565b6001600160a01b038216610b9d5760405162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015260640161050a565b60cc546001600160a01b031615610be55760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640161050a565b60cc80546001600160a01b038085166001600160a01b03199283161790925560cd805492841692909116919091179055610c2085858561119a565b5050505050565b6000610c33848461078c565b90506000198114610c9b5781811015610c8e5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161050a565b610c9b8484848403610858565b50505050565b6001600160a01b038316610d055760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161050a565b6001600160a01b038216610d675760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161050a565b6001600160a01b03831660009081526033602052604090205481811015610ddf5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161050a565b6001600160a01b038085166000818152603360205260408082208686039055928616808252908390208054860190559151600080516020611cba83398151915290610e2d9086815260200190565b60405180910390a3610c9b565b60006103257f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610e6960655490565b6066546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b604051635260769b60e11b815283906001600160a01b0382169063a4c0ed3690610ee790339087908790600401611b1b565b600060405180830381600087803b158015610f0157600080fd5b505af1158015610f15573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038216610f7f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161050a565b6001600160a01b03821660009081526033602052604090205481811015610ff35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161050a565b6001600160a01b0383166000818152603360209081526040808320868603905560358054879003905551858152919291600080516020611cba8339815191529101610970565b505050565b6001600160a01b0382166110945760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161050a565b80603560008282546110a691906119cd565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020611cba833981519152910160405180910390a35050565b6060603780546107d590611a27565b6001600160a01b03811660009081526099602052604090208054600181018255905b50919050565b600061033e611131610e3a565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000611183878787876112ce565b9150915061119081611388565b5095945050505050565b600054610100900460ff16158080156111ba5750600054600160ff909116105b806111db57506111c9306107b7565b1580156111db575060005460ff166001145b61123e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161050a565b6000805460ff191660011790558015611261576000805461ff0019166101001790555b61126a846114d0565b611274848461151a565b6038805460ff191660ff84161790558015610c9b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156112fb575060009050600361137f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561134f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166113785760006001925092505061137f565b9150600090505b94509492505050565b600081600481111561139c5761139c611b4b565b036113a45750565b60018160048111156113b8576113b8611b4b565b036114005760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b604482015260640161050a565b600281600481111561141457611414611b4b565b036114615760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161050a565b600381600481111561147557611475611b4b565b036114cd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161050a565b50565b600054610100900460ff166114f75760405162461bcd60e51b815260040161050a90611b61565b6114cd81604051806040016040528060018152602001603160f81b81525061154b565b600054610100900460ff166115415760405162461bcd60e51b815260040161050a90611b61565b61051d828261158c565b600054610100900460ff166115725760405162461bcd60e51b815260040161050a90611b61565b815160209283012081519190920120606591909155606655565b600054610100900460ff166115b35760405162461bcd60e51b815260040161050a90611b61565b60366115bf8382611bfa565b5060376115cc8282611bfa565b50506038805460ff1916601217905550565b60005b838110156115f95781810151838201526020016115e1565b50506000910152565b6000815180845261161a8160208601602086016115de565b601f01601f19169290920160200192915050565b60208152600061041a6020830184611602565b80356001600160a01b038116811461165857600080fd5b919050565b6000806040838503121561167057600080fd5b61167983611641565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156116c5576116c5611687565b604052919050565b60006001600160401b038211156116e6576116e6611687565b50601f01601f191660200190565b600082601f83011261170557600080fd5b8135611718611713826116cd565b61169d565b81815284602083860101111561172d57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561175d57600080fd5b61176683611641565b915060208301356001600160401b0381111561178157600080fd5b61178d858286016116f4565b9150509250929050565b6000806000606084860312156117ac57600080fd5b6117b584611641565b92506117c360208501611641565b9150604084013590509250925092565b6000806000606084860312156117e857600080fd5b6117f184611641565b92506020840135915060408401356001600160401b0381111561181357600080fd5b61181f868287016116f4565b9150509250925092565b60006020828403121561183b57600080fd5b61041a82611641565b600080600080600080600060e0888a03121561185f57600080fd5b61186888611641565b965061187660208901611641565b95506040880135945060608801359350608088013560ff8116811461189a57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156118ca57600080fd5b6118d383611641565b91506118e160208401611641565b90509250929050565b60006118f8611713846116cd565b905082815283838301111561190c57600080fd5b61041a8360208301846115de565b600082601f83011261192b57600080fd5b61041a838351602085016118ea565b60008060006060848603121561194f57600080fd5b83516001600160401b038082111561196657600080fd5b6119728783880161191a565b9450602086015191508082111561198857600080fd5b6119948783880161191a565b935060408601519150808211156119aa57600080fd5b5061181f8682870161191a565b634e487b7160e01b600052601160045260246000fd5b8082018082111561033e5761033e6119b7565b8281526040602082015260006119f96040830184611602565b949350505050565b6020808252600c908201526b4f4e4c595f4741544557415960a01b604082015260600190565b600181811c90821680611a3b57607f821691505b60208210810361111e57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b8181038181111561033e5761033e6119b7565b600081611a9357611a936119b7565b506000190190565b600060ff821660ff8103611ab157611ab16119b7565b60010192915050565b600060208284031215611acc57600080fd5b81516001600160401b03811115611ae257600080fd5b8201601f81018413611af357600080fd5b6119f9848251602084016118ea565b600060208284031215611b1457600080fd5b5051919050565b60018060a01b0384168152826020820152606060408201526000611b426060830184611602565b95945050505050565b634e487b7160e01b600052602160045260246000fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b601f82111561103957600081815260208120601f850160051c81016020861015611bd35750805b601f850160051c820191505b81811015611bf257828155600101611bdf565b505050505050565b81516001600160401b03811115611c1357611c13611687565b611c2781611c218454611a27565b84611bac565b602080601f831160018114611c5c5760008415611c445750858301515b600019600386901b1c1916600185901b178555611bf2565b600085815260208120601f198616915b82811015611c8b57888601518255948401946001909101908401611c6c565b5085821015611ca95787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122070845537e703bebbfe17ccc1f6f77686f42e5101a18b732d87a34447165dfe1164736f6c63430008100033608060405234801561001057600080fd5b506040516104e23803806104e283398101604081905261002f91610151565b61003833610047565b61004181610097565b50610181565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161014260201b6101a01760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03163b151590565b60006020828403121561016357600080fd5b81516001600160a01b038116811461017a57600080fd5b9392505050565b610352806101906000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ec565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ec565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029c565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029c565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b610212816101a0565b61027a5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156102fe57600080fd5b81356001600160a01b038116811461031557600080fd5b939250505056fea264697066735822122059e4b83111825434711a238db6203ec67d74a40640c8c22ba30c6fc5fc18964a64736f6c63430008100033608060405234801561001057600080fd5b50610c94806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000765760003560e01c806329a5c5cf146200007b578063396a5f9514620000af57806359659e9014620000c657806397881f8d14620000da578063b3e3bf4214620000f3578063c4d66de8146200010a578063e75b21411462000123575b600080fd5b620000926200008c36600462000354565b6200013a565b6040516001600160a01b0390911681526020015b60405180910390f35b62000092620000c036600462000354565b62000186565b60005462000092906001600160a01b031681565b620000e4620001c7565b604051908152602001620000a6565b620000e4620001043660046200038b565b620001f6565b620001216200011b366004620003b8565b62000233565b005b62000092620001343660046200038b565b620002ec565b600080620001493384620001f6565b90506000816040516200015c9062000346565b8190604051809103906000f59050801580156200017d573d6000803e3d6000fd5b50949350505050565b6000620001c182604051806020016200019f9062000346565b6020820181038252601f19601f8201166040525080519060200120306200031c565b92915050565b604051620001d86020820162000346565b6020820181038252601f19601f820116604052508051906020012081565b604080516001600160a01b038416602082015290810182905260009060600160405160208183030381529060405280519060200120905092915050565b6001600160a01b038116620002805760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa122a0a1a7a760911b60448201526064015b60405180910390fd5b6000546001600160a01b031615620002ca5760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640162000277565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080620002fb8484620001f6565b90506200031481604051806020016200019f9062000346565b949350505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b61088180620003de83390190565b6000602082840312156200036757600080fd5b5035919050565b80356001600160a01b03811681146200038657600080fd5b919050565b600080604083850312156200039f57600080fd5b620003aa836200036e565b946020939093013593505050565b600060208284031215620003cb57600080fd5b620003d6826200036e565b939250505056fe608060405234801561001057600080fd5b50336001600160a01b03166359659e906040518163ffffffff1660e01b8152600401602060405180830381865afa15801561004f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610073919061046c565b604051806020016040528060008152506100958282600061009c60201b60201c565b5050610508565b6100a583610167565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a26000825111806100e65750805b1561016257610160836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561012c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610150919061046c565b8361030a60201b6100291760201c565b505b505050565b61017a8161033660201b6100551760201c565b6101d95760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b61024d816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561021a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023e919061046c565b61033660201b6100551760201c565b6102b25760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b60648201526084016101d0565b806102e97fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b61034560201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b606061032f838360405180606001604052806027815260200161085a60279139610348565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b03168560405161036591906104b9565b600060405180830381855af49150503d80600081146103a0576040519150601f19603f3d011682016040523d82523d6000602084013e6103a5565b606091505b5090925090506103b7868383876103c1565b9695505050505050565b60608315610430578251600003610429576001600160a01b0385163b6104295760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d0565b508161043a565b61043a8383610442565b949350505050565b8151156104525781518083602001fd5b8060405162461bcd60e51b81526004016101d091906104d5565b60006020828403121561047e57600080fd5b81516001600160a01b038116811461032f57600080fd5b60005b838110156104b0578181015183820152602001610498565b50506000910152565b600082516104cb818460208701610495565b9190910192915050565b60208152600082518060208401526104f4816040850160208701610495565b601f01601f19169190910160400192915050565b610343806105176000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102e760279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024a565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b0316856040516101419190610297565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020e578251600003610207576101b685610055565b6102075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610218565b6102188383610220565b949350505050565b8151156102305781518083602001fd5b8060405162461bcd60e51b81526004016101fe91906102b3565b60006020828403121561025c57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028e578181015183820152602001610276565b50506000910152565b600082516102a9818460208701610273565b9190910192915050565b60208152600082518060208401526102d2816040850160208701610273565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e9bed491ce4cc7495def60dc616a13f39ccd912637e0c8ba02d45400506de9c064736f6c63430008100033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220237fb73aef7b871fb5f0c1ef15f58a63a1b7502356cc319c2d83ad0717d2cd7264736f6c634300081000336080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea26469706673582212203fc1d73d12f631c8d0a3a1e5ebc667c0e6e4c09698b94f0ed53d99f55382279e64736f6c63430008100033608060405260405162000ebb38038062000ebb833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e9460279139620002f8565b9392505050565b60006200018060008051602062000e7483398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e7483398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61089a80620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e838360405180606001604052806027815260200161083e6027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610691565b81019061020091906106d7565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610691565b8101906102509190610708565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610691565b81019061029d91906106d7565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107ee565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c4565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610504565b50565b600061041c6105ad565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b25782516000036104ab5761045f85610198565b6104ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104bc565b6104bc83836105d5565b949350505050565b6104cd816105ff565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105695760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e55781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080a565b61060881610198565b61066a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058c565b600080858511156106a157600080fd5b838611156106ae57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d257600080fd5b919050565b6000602082840312156106e957600080fd5b61018e826106bb565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071b57600080fd5b610724836106bb565b9150602083013567ffffffffffffffff8082111561074157600080fd5b818501915085601f83011261075557600080fd5b813581811115610767576107676106f2565b604051601f8201601f19908116603f0116810190838211818310171561078f5761078f6106f2565b816040528281528860208487010111156107a857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e55781810151838201526020016107cd565b50506000910152565b600082516108008184602087016107ca565b9190910192915050565b60208152600082518060208401526108298160408501602087016107ca565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122072007c277cc5d8471be1434c6b2d5b70fb7c2f6f77a0697617733c4d4ae5b76964736f6c63430008100033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220377d031a5f294a74596aa9acc30ca418bd32dd3f9cbae6ed71ce8cc1f17439cc64736f6c63430008100033000000000000\",\n            \"nonce\": \"0x0\",\n            \"to\": \"0x000000000000000000000000000000000000006e\",\n            \"transactionIndex\": \"0x1\",\n            \"value\": \"0x0\",\n            \"type\": \"0x69\",\n            \"chainId\": \"0xda8c8b77\",\n            \"v\": \"0x0\",\n            \"r\": \"0x0\",\n            \"s\": \"0x0\",\n            \"requestId\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n            \"refundTo\": \"0xbee947aec820389c1560c87bd96e2723bad05b61\",\n            \"l1BaseFee\": \"0x5f5e100\",\n            \"depositValue\": \"0x22f2505249400\",\n            \"retryValue\": \"0x0\",\n            \"retryData\": \"0x608060405234801561001057600080fd5b50615f3a806100206000396000f3fe60806040523480156200001157600080fd5b50600436106200002e5760003560e01c8063b1c7a8701462000033575b600080fd5b6200004a6200004436600462001528565b6200004c565b005b6000620000b9620000866040518060400160405280601181526020017027b93134ba2619283937bc3ca0b236b4b760791b81525062000304565b6040516200009760208201620014b8565b6020820181038252601f19601f8201166040525080519060200120306200033a565b90506001600160a01b0381163b15620000e5576040516377e0068560e11b815260040160405180910390fd5b5060006200011c6040518060400160405280601181526020017027b93134ba2619283937bc3ca0b236b4b760791b81525062000304565b6040516200012a90620014b8565b8190604051809103906000f59050801580156200014b573d6000803e3d6000fd5b50905060006200016c6200016360a08d018d62001603565b86858762000364565b9050600062000189620001808d8062001603565b8d898762000689565b9050620001a86200019e60208e018e62001603565b8c8487876200088c565b620001c4620001bb60408e018e62001603565b8b848762000cb4565b6001600160a01b03881615620002035762000203620001e760608e018e62001603565b8e8060800190620001f9919062001603565b8c8c878a62000ef4565b6200029360006200023c6040518060400160405280601081526020016f13dc989a5d130c935d5b1d1a58d85b1b60821b81525062000304565b6200028d8f8060c0019062000252919062001603565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b6200131c565b5060405163f2fde38b60e01b81526001600160a01b0384169063f2fde38b90620002c290859060040162001654565b600060405180830381600087803b158015620002dd57600080fd5b505af1158015620002f2573d6000803e3d6000fd5b50505050505050505050505050505050565b60008146336040516020016200031d939291906200168e565b604051602081830303815290604052805190602001209050919050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b600080620003f084620003ac6040518060400160405280601b81526020017f4f726269744c32557067726164654578656375746f7250726f7879000000000081525062000304565b620003ea6040518060400160405280601b81526020017a4f726269744c32557067726164654578656375746f724c6f67696360281b81525062000304565b6200142d565b90506000620004796000620004386040518060400160405280601b81526020017a4f726269744c32557067726164654578656375746f724c6f67696360281b81525062000304565b6200028d8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038616906399a88ec490620004ac9085908590600401620016c9565b600060405180830381600087803b158015620004c757600080fd5b505af1158015620004dc573d6000803e3d6000fd5b5060009250829150620004ec9050565b60405190808252806020026020018201604052801562000516578160200160208202803683370190505b5060405163251b648160e21b81529091506001600160a01b0383169063946d9204906200054c9061dead908590600401620016e3565b600060405180830381600087803b1580156200056757600080fd5b505af11580156200057c573d6000803e3d6000fd5b5060009250600291506200058d9050565b604051908082528060200260200182016040528015620005b7578160200160208202803683370190505b5090508781600081518110620005d157620005d162001741565b60200260200101906001600160a01b031690816001600160a01b031681525050858160018151811062000608576200060862001741565b6001600160a01b03928316602091820292909201015260405163251b648160e21b81529085169063946d920490620006479087908590600401620016e3565b600060405180830381600087803b1580156200066257600080fd5b505af115801562000677573d6000803e3d6000fd5b50959c9b505050505050505050505050565b6000806200070983620006cd604051806040016040528060198152602001784f726269744c3247617465776179526f7574657250726f787960381b81525062000304565b620003ea604051806040016040528060198152602001784f726269744c3247617465776179526f757465724c6f67696360381b81525062000304565b905060006200074f600062000438604051806040016040528060198152602001784f726269744c3247617465776179526f757465724c6f67696360381b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038516906399a88ec490620007829085908590600401620016c9565b600060405180830381600087803b1580156200079d57600080fd5b505af1158015620007b2573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038416925063485cc9559150620007e89061dead908190600401620016c9565b600060405180830381600087803b1580156200080357600080fd5b505af115801562000818573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038516925063485cc95591506200084c9089908990600401620016c9565b600060405180830381600087803b1580156200086757600080fd5b505af11580156200087c573d6000803e3d6000fd5b50939a9950505050505050505050565b60006200091183620008d36040518060400160405280601b81526020017f4f726269744c325374616e646172644761746577617950726f7879000000000081525062000304565b620003ea6040518060400160405280601b81526020017a4f726269744c325374616e64617264476174657761794c6f67696360281b81525062000304565b90506000620009596000620004386040518060400160405280601b81526020017a4f726269744c325374616e64617264476174657761794c6f67696360281b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038516906399a88ec4906200098c9085908590600401620016c9565b600060405180830381600087803b158015620009a757600080fd5b505af1158015620009bc573d6000803e3d6000fd5b505060405163c0c53b8b60e01b81526001600160a01b038416925063c0c53b8b9150620009f49061dead908190819060040162001757565b600060405180830381600087803b15801562000a0f57600080fd5b505af115801562000a24573d6000803e3d6000fd5b50505050600062000a626040518060400160405280601581526020017404f726269745374616e64617264417262455243323605c1b81525062000304565b60405162000a7090620014c6565b8190604051809103906000f590508015801562000a91573d6000803e3d6000fd5b509050600062000acf6040518060400160405280601681526020017527b93134ba2ab833b930b232b0b13632a132b0b1b7b760511b81525062000304565b8260405162000ade90620014d4565b62000aea919062001654565b8190604051809103906000f590508015801562000b0b573d6000803e3d6000fd5b509050600062000b4a604051806040016040528060178152602001764f72626974426561636f6e50726f7879466163746f727960481b81525062000304565b60405162000b5890620014e2565b8190604051809103906000f590508015801562000b79573d6000803e3d6000fd5b5060405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de89062000bab90859060040162001654565b600060405180830381600087803b15801562000bc657600080fd5b505af115801562000bdb573d6000803e3d6000fd5b505060405163c0c53b8b60e01b81526001600160a01b038816925063c0c53b8b915062000c11908c908c90869060040162001757565b600060405180830381600087803b15801562000c2c57600080fd5b505af115801562000c41573d6000803e3d6000fd5b505060405163f2fde38b60e01b81526001600160a01b038516925063f2fde38b915062000c7390899060040162001654565b600060405180830381600087803b15801562000c8e57600080fd5b505af115801562000ca3573d6000803e3d6000fd5b505050505050505050505050505050565b600062000d338262000cf7604051806040016040528060198152602001784f726269744c32437573746f6d4761746577617950726f787960381b81525062000304565b620003ea604051806040016040528060198152602001784f726269744c32437573746f6d476174657761794c6f67696360381b81525062000304565b9050600062000dba600062000d79604051806040016040528060198152602001784f726269744c32437573746f6d476174657761794c6f67696360381b81525062000304565b6200028d8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038416906399a88ec49062000ded9085908590600401620016c9565b600060405180830381600087803b15801562000e0857600080fd5b505af115801562000e1d573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038416925063485cc955915062000e539061dead908190600401620016c9565b600060405180830381600087803b15801562000e6e57600080fd5b505af115801562000e83573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038516925063485cc955915062000eb79088908890600401620016c9565b600060405180830381600087803b15801562000ed257600080fd5b505af115801562000ee7573d6000803e3d6000fd5b5050505050505050505050565b600062000f5c8262000f2e6040518060400160405280601081526020016f4f726269744c325745544850726f787960801b81525062000304565b620003ea6040518060400160405280600b81526020016a09ee4c4d2e89864ae8aa8960ab1b81525062000304565b9050600062000f946000620004386040518060400160405280600b81526020016a09ee4c4d2e89864ae8aa8960ab1b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038416906399a88ec49062000fc79085908590600401620016c9565b600060405180830381600087803b15801562000fe257600080fd5b505af115801562000ff7573d6000803e3d6000fd5b50505050600062001076846200103c604051806040016040528060178152602001764f726269744c32576574684761746577617950726f787960481b81525062000304565b620003ea604051806040016040528060178152602001764f726269744c3257657468476174657761794c6f67696360481b81525062000304565b90506000620010fb6000620010ba604051806040016040528060178152602001764f726269744c3257657468476174657761794c6f67696360481b81525062000304565b6200028d8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038616906399a88ec4906200112e9085908590600401620016c9565b600060405180830381600087803b1580156200114957600080fd5b505af11580156200115e573d6000803e3d6000fd5b5050604051637c643b2f60e11b81526001600160a01b038416925063f8c8765e9150620011989061dead908190819081906004016200177a565b600060405180830381600087803b158015620011b357600080fd5b505af1158015620011c8573d6000803e3d6000fd5b5050604051637c643b2f60e11b81526001600160a01b038516925063f8c8765e915062001200908b908a908c908a906004016200177a565b600060405180830381600087803b1580156200121b57600080fd5b505af115801562001230573d6000803e3d6000fd5b505060405163641078a360e11b815260a06004820152600060a4820181905260c0602483015260c48201819052604482015261dead6064820181905260848201526001600160a01b038616925063c820f146915060e401600060405180830381600087803b158015620012a257600080fd5b505af1158015620012b7573d6000803e3d6000fd5b505060405163641078a360e11b81526001600160a01b038716925063c820f1469150620002c29060129086908c90600401620017bc565b6060815182604051602001620013069291906200180b565b6040516020818303038152906040529050919050565b600083471015620013745760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b8151600003620013c75760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016200136b565b8282516020840186f590506001600160a01b038116620014265760405162461bcd60e51b8152602060048201526019602482015278437265617465323a204661696c6564206f6e206465706c6f7960381b60448201526064016200136b565b9392505050565b600082826040516200143f90620014f0565b8190604051809103906000f590508015801562001460573d6000803e3d6000fd5b5085604051806020016040528060008152506040516200148090620014fd565b6200148e939291906200187b565b8190604051809103906000f5905080158015620014af573d6000803e3d6000fd5b50949350505050565b61070f80620018cb83390190565b611e7e8062001fda83390190565b6104e28062003e5883390190565b610cb4806200433a83390190565b605c8062004fee83390190565b610ebb806200504a83390190565b80356001600160a01b03811681146200152357600080fd5b919050565b60008060008060008060008060006101208a8c0312156200154857600080fd5b893567ffffffffffffffff8111156200156057600080fd5b8a0160e0818d0312156200157357600080fd5b98506200158360208b016200150b565b97506200159360408b016200150b565b9650620015a360608b016200150b565b9550620015b360808b016200150b565b9450620015c360a08b016200150b565b9350620015d360c08b016200150b565b9250620015e360e08b016200150b565b9150620015f46101008b016200150b565b90509295985092959850929598565b6000808335601e198436030181126200161b57600080fd5b83018035915067ffffffffffffffff8211156200163757600080fd5b6020019150368190038213156200164d57600080fd5b9250929050565b6001600160a01b0391909116815260200190565b60005b83811015620016855781810151838201526020016200166b565b50506000910152565b60008451620016a281846020890162001668565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156200173357855185168352948301949183019160010162001713565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b60048152630ae8aa8960e31b602082015260400190565b60a081526000620017d060a08301620017a5565b8281036020840152620017e381620017a5565b60ff96909616604084015250506001600160a01b039283166060820152911660809091015290565b710608060405234801561001057600080fd5b560741b8152606160f81b601282015260f083901b6001600160f01b03191660138201526a4030801030001cb00079ff60a91b601582015281516000906200186d81602080860190870162001668565b919091016020019392505050565b600060018060a01b038086168352808516602084015250606060408301528251806060840152620018b481608085016020870162001668565b601f01601f19169190910160800194935050505056fe608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6106918061007e6000396000f3fe60806040526004361061006b5760003560e01c8063204e1c7a14610070578063715018a6146100a65780637eff275e146100bd5780638da5cb5b146100dd5780639623609d146100fb57806399a88ec41461010e578063f2fde38b1461012e578063f3b7dead1461014e575b600080fd5b34801561007c57600080fd5b5061009061008b366004610483565b61016e565b60405161009d91906104a7565b60405180910390f35b3480156100b257600080fd5b506100bb6101ff565b005b3480156100c957600080fd5b506100bb6100d83660046104bb565b610213565b3480156100e957600080fd5b506000546001600160a01b0316610090565b6100bb61010936600461050a565b61027d565b34801561011a57600080fd5b506100bb6101293660046104bb565b6102ec565b34801561013a57600080fd5b506100bb610149366004610483565b610320565b34801561015a57600080fd5b50610090610169366004610483565b61039e565b6000806000836001600160a01b031660405161019490635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101cf576040519150601f19603f3d011682016040523d82523d6000602084013e6101d4565b606091505b5091509150816101e357600080fd5b808060200190518101906101f791906105e0565b949350505050565b6102076103c4565b610211600061041e565b565b61021b6103c4565b6040516308f2839760e41b81526001600160a01b03831690638f283970906102479084906004016104a7565b600060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050505050565b6102856103c4565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102b590869086906004016105fd565b6000604051808303818588803b1580156102ce57600080fd5b505af11580156102e2573d6000803e3d6000fd5b5050505050505050565b6102f46103c4565b604051631b2ce7f360e11b81526001600160a01b03831690633659cfe6906102479084906004016104a7565b6103286103c4565b6001600160a01b0381166103925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61039b8161041e565b50565b6000806000836001600160a01b0316604051610194906303e1469160e61b815260040190565b6000546001600160a01b031633146102115760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610389565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461039b57600080fd5b60006020828403121561049557600080fd5b81356104a08161046e565b9392505050565b6001600160a01b0391909116815260200190565b600080604083850312156104ce57600080fd5b82356104d98161046e565b915060208301356104e98161046e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561051f57600080fd5b833561052a8161046e565b9250602084013561053a8161046e565b9150604084013567ffffffffffffffff8082111561055757600080fd5b818601915086601f83011261056b57600080fd5b81358181111561057d5761057d6104f4565b604051601f8201601f19908116603f011681019083821181831017156105a5576105a56104f4565b816040528281528960208487010111156105be57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156105f257600080fd5b81516104a08161046e565b60018060a01b038316815260006020604081840152835180604085015260005b818110156106395785810183015185820160600152820161061d565b506000606082860101526060601f19601f83011685010192505050939250505056fea26469706673582212208a2d9d6b4833462246845f0898b3da66a9086b54eb9fb2d870a9780af5c177f664736f6c6343000810003360806040523480156200001157600080fd5b50600054610100900460ff1615808015620000335750600054600160ff909116105b8062000063575062000050306200015060201b620007b71760201c565b15801562000063575060005460ff166001145b620000cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000ef576000805461ff0019166101001790555b801562000136576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5060cd805460ff60a01b1916600160a01b1790556200015f565b6001600160a01b03163b151590565b611d0f806200016f6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806370a08231116100b857806395d89b411161007c57806395d89b411461029e578063a457c2d7146102a6578063a9059cbb146102b9578063c2eeeebd146102cc578063d505accf146102df578063dd62ed3e146102f257600080fd5b806370a082311461021157806374f4f5471461023a5780637ecebe001461024d5780638c2a993e146102605780638fa74a0e1461027357600080fd5b8063313ce567116100ff578063313ce567146101b75780633644e515146101d157806339509351146101d95780634000aea0146101ec5780636f791d29146101ff57600080fd5b806306fdde031461013c578063095ea7b31461015a57806318160ddd1461017d578063189db7d21461018f57806323b872dd146101a4575b600080fd5b610144610305565b604051610151919061162e565b60405180910390f35b61016d61016836600461165d565b61032a565b6040519015158152602001610151565b6035545b604051908152602001610151565b6101a261019d36600461174a565b610344565b005b61016d6101b2366004611797565b6103fb565b6101bf610421565b60405160ff9091168152602001610151565b61018161043e565b61016d6101e736600461165d565b610448565b61016d6101fa3660046117d3565b61046a565b60cd54600160a01b900460ff1661016d565b61018161021f366004611829565b6001600160a01b031660009081526033602052604090205490565b6101a261024836600461165d565b6104e0565b61018161025b366004611829565b610521565b6101a261026e36600461165d565b61053f565b60cc54610286906001600160a01b031681565b6040516001600160a01b039091168152602001610151565b610144610573565b61016d6102b436600461165d565b610594565b61016d6102c736600461165d565b61061a565b60cd54610286906001600160a01b031681565b6101a26102ed366004611844565b610628565b6101816103003660046118b7565b61078c565b60ce54606090610100900460ff161561031d57600080fd5b6103256107c6565b905090565b600033610338818585610858565b60019150505b92915050565b60008060008380602001905181019061035d919061193a565b92509250925060008061036f8561097d565b9150915060008061037f8661097d565b9150915060008061038f87610b06565b915091506103a0858483338f610b55565b506040805160608101825291158083529515602083018190529315910181905260ce805461ffff191661ff0019909616959095176101009093029290921762ff00001916620100009092029190911790925550505050505050565b600033610409858285610c27565b610414858585610ca1565b60019150505b9392505050565b60ce5460009060ff161561043457600080fd5b5060385460ff1690565b6000610325610e3a565b60003361033881858561045b838361078c565b61046591906119cd565b610858565b6000610476848461061a565b50836001600160a01b0316336001600160a01b03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1685856040516104bc9291906119e0565b60405180910390a3833b156104d6576104d6848484610eb5565b5060019392505050565b60cc546001600160a01b031633146105135760405162461bcd60e51b815260040161050a90611a01565b60405180910390fd5b61051d8282610f1f565b5050565b6001600160a01b03811660009081526099602052604081205461033e565b60cc546001600160a01b031633146105695760405162461bcd60e51b815260040161050a90611a01565b61051d828261103e565b60ce5460609062010000900460ff161561058c57600080fd5b6103256110ed565b600033816105a2828661078c565b9050838110156106025760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161050a565b61060f8286868403610858565b506001949350505050565b600033610338818585610ca1565b834211156106785760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161050a565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886106a78c6110fc565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e001604051602081830303815290604052805190602001209050600061070282611124565b9050600061071282878787611172565b9050896001600160a01b0316816001600160a01b0316146107755760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161050a565b6107808a8a8a610858565b50505050505050505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6001600160a01b03163b151590565b6060603680546107d590611a27565b80601f016020809104026020016040519081016040528092919081815260200182805461080190611a27565b801561084e5780601f106108235761010080835404028352916020019161084e565b820191906000526020600020905b81548152906001019060200180831161083157829003601f168201915b5050505050905090565b6001600160a01b0383166108ba5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161050a565b6001600160a01b03821661091b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161050a565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000606082516000036109935760009150915091565b8251602003610ae65782516000908490601f9081106109b4576109b4611a5b565b01602001516001600160f81b031916146109d15760009150915091565b6001915060205b600081118015610a1257506000846109f1600184611a71565b81518110610a0157610a01611a5b565b01602001516001600160f81b031916145b15610a295780610a2181611a84565b9150506109d8565b6000816001600160401b03811115610a4357610a43611687565b6040519080825280601f01601f191660200182016040528015610a6d576020820181803683370190505b50905060005b828160ff161015610adc57858160ff1681518110610a9357610a93611a5b565b602001015160f81c60f81b828260ff1681518110610ab357610ab3611a5b565b60200101906001600160f81b031916908160001a90535080610ad481611a9b565b915050610a73565b509150610b019050565b6001915082806020019051810190610afe9190611aba565b90505b915091565b6000808251602014610b1d57506000928392509050565b600083806020019051810190610b339190611b02565b905060ff811115610b4a5750600093849350915050565b600194909350915050565b6001600160a01b038216610b9d5760405162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015260640161050a565b60cc546001600160a01b031615610be55760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640161050a565b60cc80546001600160a01b038085166001600160a01b03199283161790925560cd805492841692909116919091179055610c2085858561119a565b5050505050565b6000610c33848461078c565b90506000198114610c9b5781811015610c8e5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161050a565b610c9b8484848403610858565b50505050565b6001600160a01b038316610d055760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161050a565b6001600160a01b038216610d675760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161050a565b6001600160a01b03831660009081526033602052604090205481811015610ddf5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161050a565b6001600160a01b038085166000818152603360205260408082208686039055928616808252908390208054860190559151600080516020611cba83398151915290610e2d9086815260200190565b60405180910390a3610c9b565b60006103257f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610e6960655490565b6066546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b604051635260769b60e11b815283906001600160a01b0382169063a4c0ed3690610ee790339087908790600401611b1b565b600060405180830381600087803b158015610f0157600080fd5b505af1158015610f15573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038216610f7f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161050a565b6001600160a01b03821660009081526033602052604090205481811015610ff35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161050a565b6001600160a01b0383166000818152603360209081526040808320868603905560358054879003905551858152919291600080516020611cba8339815191529101610970565b505050565b6001600160a01b0382166110945760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161050a565b80603560008282546110a691906119cd565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020611cba833981519152910160405180910390a35050565b6060603780546107d590611a27565b6001600160a01b03811660009081526099602052604090208054600181018255905b50919050565b600061033e611131610e3a565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000611183878787876112ce565b9150915061119081611388565b5095945050505050565b600054610100900460ff16158080156111ba5750600054600160ff909116105b806111db57506111c9306107b7565b1580156111db575060005460ff166001145b61123e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161050a565b6000805460ff191660011790558015611261576000805461ff0019166101001790555b61126a846114d0565b611274848461151a565b6038805460ff191660ff84161790558015610c9b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156112fb575060009050600361137f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561134f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166113785760006001925092505061137f565b9150600090505b94509492505050565b600081600481111561139c5761139c611b4b565b036113a45750565b60018160048111156113b8576113b8611b4b565b036114005760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b604482015260640161050a565b600281600481111561141457611414611b4b565b036114615760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161050a565b600381600481111561147557611475611b4b565b036114cd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161050a565b50565b600054610100900460ff166114f75760405162461bcd60e51b815260040161050a90611b61565b6114cd81604051806040016040528060018152602001603160f81b81525061154b565b600054610100900460ff166115415760405162461bcd60e51b815260040161050a90611b61565b61051d828261158c565b600054610100900460ff166115725760405162461bcd60e51b815260040161050a90611b61565b815160209283012081519190920120606591909155606655565b600054610100900460ff166115b35760405162461bcd60e51b815260040161050a90611b61565b60366115bf8382611bfa565b5060376115cc8282611bfa565b50506038805460ff1916601217905550565b60005b838110156115f95781810151838201526020016115e1565b50506000910152565b6000815180845261161a8160208601602086016115de565b601f01601f19169290920160200192915050565b60208152600061041a6020830184611602565b80356001600160a01b038116811461165857600080fd5b919050565b6000806040838503121561167057600080fd5b61167983611641565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156116c5576116c5611687565b604052919050565b60006001600160401b038211156116e6576116e6611687565b50601f01601f191660200190565b600082601f83011261170557600080fd5b8135611718611713826116cd565b61169d565b81815284602083860101111561172d57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561175d57600080fd5b61176683611641565b915060208301356001600160401b0381111561178157600080fd5b61178d858286016116f4565b9150509250929050565b6000806000606084860312156117ac57600080fd5b6117b584611641565b92506117c360208501611641565b9150604084013590509250925092565b6000806000606084860312156117e857600080fd5b6117f184611641565b92506020840135915060408401356001600160401b0381111561181357600080fd5b61181f868287016116f4565b9150509250925092565b60006020828403121561183b57600080fd5b61041a82611641565b600080600080600080600060e0888a03121561185f57600080fd5b61186888611641565b965061187660208901611641565b95506040880135945060608801359350608088013560ff8116811461189a57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156118ca57600080fd5b6118d383611641565b91506118e160208401611641565b90509250929050565b60006118f8611713846116cd565b905082815283838301111561190c57600080fd5b61041a8360208301846115de565b600082601f83011261192b57600080fd5b61041a838351602085016118ea565b60008060006060848603121561194f57600080fd5b83516001600160401b038082111561196657600080fd5b6119728783880161191a565b9450602086015191508082111561198857600080fd5b6119948783880161191a565b935060408601519150808211156119aa57600080fd5b5061181f8682870161191a565b634e487b7160e01b600052601160045260246000fd5b8082018082111561033e5761033e6119b7565b8281526040602082015260006119f96040830184611602565b949350505050565b6020808252600c908201526b4f4e4c595f4741544557415960a01b604082015260600190565b600181811c90821680611a3b57607f821691505b60208210810361111e57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b8181038181111561033e5761033e6119b7565b600081611a9357611a936119b7565b506000190190565b600060ff821660ff8103611ab157611ab16119b7565b60010192915050565b600060208284031215611acc57600080fd5b81516001600160401b03811115611ae257600080fd5b8201601f81018413611af357600080fd5b6119f9848251602084016118ea565b600060208284031215611b1457600080fd5b5051919050565b60018060a01b0384168152826020820152606060408201526000611b426060830184611602565b95945050505050565b634e487b7160e01b600052602160045260246000fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b601f82111561103957600081815260208120601f850160051c81016020861015611bd35750805b601f850160051c820191505b81811015611bf257828155600101611bdf565b505050505050565b81516001600160401b03811115611c1357611c13611687565b611c2781611c218454611a27565b84611bac565b602080601f831160018114611c5c5760008415611c445750858301515b600019600386901b1c1916600185901b178555611bf2565b600085815260208120601f198616915b82811015611c8b57888601518255948401946001909101908401611c6c565b5085821015611ca95787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122070845537e703bebbfe17ccc1f6f77686f42e5101a18b732d87a34447165dfe1164736f6c63430008100033608060405234801561001057600080fd5b506040516104e23803806104e283398101604081905261002f91610151565b61003833610047565b61004181610097565b50610181565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161014260201b6101a01760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03163b151590565b60006020828403121561016357600080fd5b81516001600160a01b038116811461017a57600080fd5b9392505050565b610352806101906000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ec565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ec565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029c565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029c565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b610212816101a0565b61027a5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156102fe57600080fd5b81356001600160a01b038116811461031557600080fd5b939250505056fea264697066735822122059e4b83111825434711a238db6203ec67d74a40640c8c22ba30c6fc5fc18964a64736f6c63430008100033608060405234801561001057600080fd5b50610c94806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000765760003560e01c806329a5c5cf146200007b578063396a5f9514620000af57806359659e9014620000c657806397881f8d14620000da578063b3e3bf4214620000f3578063c4d66de8146200010a578063e75b21411462000123575b600080fd5b620000926200008c36600462000354565b6200013a565b6040516001600160a01b0390911681526020015b60405180910390f35b62000092620000c036600462000354565b62000186565b60005462000092906001600160a01b031681565b620000e4620001c7565b604051908152602001620000a6565b620000e4620001043660046200038b565b620001f6565b620001216200011b366004620003b8565b62000233565b005b62000092620001343660046200038b565b620002ec565b600080620001493384620001f6565b90506000816040516200015c9062000346565b8190604051809103906000f59050801580156200017d573d6000803e3d6000fd5b50949350505050565b6000620001c182604051806020016200019f9062000346565b6020820181038252601f19601f8201166040525080519060200120306200031c565b92915050565b604051620001d86020820162000346565b6020820181038252601f19601f820116604052508051906020012081565b604080516001600160a01b038416602082015290810182905260009060600160405160208183030381529060405280519060200120905092915050565b6001600160a01b038116620002805760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa122a0a1a7a760911b60448201526064015b60405180910390fd5b6000546001600160a01b031615620002ca5760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640162000277565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080620002fb8484620001f6565b90506200031481604051806020016200019f9062000346565b949350505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b61088180620003de83390190565b6000602082840312156200036757600080fd5b5035919050565b80356001600160a01b03811681146200038657600080fd5b919050565b600080604083850312156200039f57600080fd5b620003aa836200036e565b946020939093013593505050565b600060208284031215620003cb57600080fd5b620003d6826200036e565b939250505056fe608060405234801561001057600080fd5b50336001600160a01b03166359659e906040518163ffffffff1660e01b8152600401602060405180830381865afa15801561004f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610073919061046c565b604051806020016040528060008152506100958282600061009c60201b60201c565b5050610508565b6100a583610167565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a26000825111806100e65750805b1561016257610160836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561012c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610150919061046c565b8361030a60201b6100291760201c565b505b505050565b61017a8161033660201b6100551760201c565b6101d95760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b61024d816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561021a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023e919061046c565b61033660201b6100551760201c565b6102b25760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b60648201526084016101d0565b806102e97fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b61034560201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b606061032f838360405180606001604052806027815260200161085a60279139610348565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b03168560405161036591906104b9565b600060405180830381855af49150503d80600081146103a0576040519150601f19603f3d011682016040523d82523d6000602084013e6103a5565b606091505b5090925090506103b7868383876103c1565b9695505050505050565b60608315610430578251600003610429576001600160a01b0385163b6104295760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d0565b508161043a565b61043a8383610442565b949350505050565b8151156104525781518083602001fd5b8060405162461bcd60e51b81526004016101d091906104d5565b60006020828403121561047e57600080fd5b81516001600160a01b038116811461032f57600080fd5b60005b838110156104b0578181015183820152602001610498565b50506000910152565b600082516104cb818460208701610495565b9190910192915050565b60208152600082518060208401526104f4816040850160208701610495565b601f01601f19169190910160400192915050565b610343806105176000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102e760279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024a565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b0316856040516101419190610297565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020e578251600003610207576101b685610055565b6102075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610218565b6102188383610220565b949350505050565b8151156102305781518083602001fd5b8060405162461bcd60e51b81526004016101fe91906102b3565b60006020828403121561025c57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028e578181015183820152602001610276565b50506000910152565b600082516102a9818460208701610273565b9190910192915050565b60208152600082518060208401526102d2816040850160208701610273565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e9bed491ce4cc7495def60dc616a13f39ccd912637e0c8ba02d45400506de9c064736f6c63430008100033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220237fb73aef7b871fb5f0c1ef15f58a63a1b7502356cc319c2d83ad0717d2cd7264736f6c634300081000336080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea26469706673582212203fc1d73d12f631c8d0a3a1e5ebc667c0e6e4c09698b94f0ed53d99f55382279e64736f6c63430008100033608060405260405162000ebb38038062000ebb833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e9460279139620002f8565b9392505050565b60006200018060008051602062000e7483398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e7483398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61089a80620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e838360405180606001604052806027815260200161083e6027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610691565b81019061020091906106d7565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610691565b8101906102509190610708565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610691565b81019061029d91906106d7565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107ee565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c4565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610504565b50565b600061041c6105ad565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b25782516000036104ab5761045f85610198565b6104ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104bc565b6104bc83836105d5565b949350505050565b6104cd816105ff565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105695760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e55781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080a565b61060881610198565b61066a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058c565b600080858511156106a157600080fd5b838611156106ae57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d257600080fd5b919050565b6000602082840312156106e957600080fd5b61018e826106bb565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071b57600080fd5b610724836106bb565b9150602083013567ffffffffffffffff8082111561074157600080fd5b818501915085601f83011261075557600080fd5b813581811115610767576107676106f2565b604051601f8201601f19908116603f0116810190838211818310171561078f5761078f6106f2565b816040528281528860208487010111156107a857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e55781810151838201526020016107cd565b50506000910152565b600082516108008184602087016107ca565b9190910192915050565b60208152600082518060208401526108298160408501602087016107ca565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122072007c277cc5d8471be1434c6b2d5b70fb7c2f6f77a0697617733c4d4ae5b76964736f6c63430008100033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220377d031a5f294a74596aa9acc30ca418bd32dd3f9cbae6ed71ce8cc1f17439cc64736f6c63430008100033\",\n            \"beneficiary\": \"0xbee947aec820389c1560c87bd96e2723bad05b61\",\n            \"maxSubmissionFee\": \"0xd72a2471400\"\n        },\n        {\n            \"blockHash\": \"0xc4cfe190b18fa6cfc6f80e5e0df16fdc78c054e750b98caf952443e653cc5049\",\n            \"blockNumber\": \"0x1\",\n            \"from\": \"0xc573c69f8f638d2954c9618b03765fc17701a1e0\",\n            \"gas\": \"0x5b8d80\",\n            \"gasPrice\": \"0x5f5e100\",\n            \"maxFeePerGas\": \"0x5f5e100\",\n            \"hash\": \"0x2f9350314c5271853749c318c9621e57c30d22836f5023e0052004bdbc1e1492\",\n            \"input\": \"0x608060405234801561001057600080fd5b50615f3a806100206000396000f3fe60806040523480156200001157600080fd5b50600436106200002e5760003560e01c8063b1c7a8701462000033575b600080fd5b6200004a6200004436600462001528565b6200004c565b005b6000620000b9620000866040518060400160405280601181526020017027b93134ba2619283937bc3ca0b236b4b760791b81525062000304565b6040516200009760208201620014b8565b6020820181038252601f19601f8201166040525080519060200120306200033a565b90506001600160a01b0381163b15620000e5576040516377e0068560e11b815260040160405180910390fd5b5060006200011c6040518060400160405280601181526020017027b93134ba2619283937bc3ca0b236b4b760791b81525062000304565b6040516200012a90620014b8565b8190604051809103906000f59050801580156200014b573d6000803e3d6000fd5b50905060006200016c6200016360a08d018d62001603565b86858762000364565b9050600062000189620001808d8062001603565b8d898762000689565b9050620001a86200019e60208e018e62001603565b8c8487876200088c565b620001c4620001bb60408e018e62001603565b8b848762000cb4565b6001600160a01b03881615620002035762000203620001e760608e018e62001603565b8e8060800190620001f9919062001603565b8c8c878a62000ef4565b6200029360006200023c6040518060400160405280601081526020016f13dc989a5d130c935d5b1d1a58d85b1b60821b81525062000304565b6200028d8f8060c0019062000252919062001603565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b6200131c565b5060405163f2fde38b60e01b81526001600160a01b0384169063f2fde38b90620002c290859060040162001654565b600060405180830381600087803b158015620002dd57600080fd5b505af1158015620002f2573d6000803e3d6000fd5b50505050505050505050505050505050565b60008146336040516020016200031d939291906200168e565b604051602081830303815290604052805190602001209050919050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b600080620003f084620003ac6040518060400160405280601b81526020017f4f726269744c32557067726164654578656375746f7250726f7879000000000081525062000304565b620003ea6040518060400160405280601b81526020017a4f726269744c32557067726164654578656375746f724c6f67696360281b81525062000304565b6200142d565b90506000620004796000620004386040518060400160405280601b81526020017a4f726269744c32557067726164654578656375746f724c6f67696360281b81525062000304565b6200028d8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038616906399a88ec490620004ac9085908590600401620016c9565b600060405180830381600087803b158015620004c757600080fd5b505af1158015620004dc573d6000803e3d6000fd5b5060009250829150620004ec9050565b60405190808252806020026020018201604052801562000516578160200160208202803683370190505b5060405163251b648160e21b81529091506001600160a01b0383169063946d9204906200054c9061dead908590600401620016e3565b600060405180830381600087803b1580156200056757600080fd5b505af11580156200057c573d6000803e3d6000fd5b5060009250600291506200058d9050565b604051908082528060200260200182016040528015620005b7578160200160208202803683370190505b5090508781600081518110620005d157620005d162001741565b60200260200101906001600160a01b031690816001600160a01b031681525050858160018151811062000608576200060862001741565b6001600160a01b03928316602091820292909201015260405163251b648160e21b81529085169063946d920490620006479087908590600401620016e3565b600060405180830381600087803b1580156200066257600080fd5b505af115801562000677573d6000803e3d6000fd5b50959c9b505050505050505050505050565b6000806200070983620006cd604051806040016040528060198152602001784f726269744c3247617465776179526f7574657250726f787960381b81525062000304565b620003ea604051806040016040528060198152602001784f726269744c3247617465776179526f757465724c6f67696360381b81525062000304565b905060006200074f600062000438604051806040016040528060198152602001784f726269744c3247617465776179526f757465724c6f67696360381b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038516906399a88ec490620007829085908590600401620016c9565b600060405180830381600087803b1580156200079d57600080fd5b505af1158015620007b2573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038416925063485cc9559150620007e89061dead908190600401620016c9565b600060405180830381600087803b1580156200080357600080fd5b505af115801562000818573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038516925063485cc95591506200084c9089908990600401620016c9565b600060405180830381600087803b1580156200086757600080fd5b505af11580156200087c573d6000803e3d6000fd5b50939a9950505050505050505050565b60006200091183620008d36040518060400160405280601b81526020017f4f726269744c325374616e646172644761746577617950726f7879000000000081525062000304565b620003ea6040518060400160405280601b81526020017a4f726269744c325374616e64617264476174657761794c6f67696360281b81525062000304565b90506000620009596000620004386040518060400160405280601b81526020017a4f726269744c325374616e64617264476174657761794c6f67696360281b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038516906399a88ec4906200098c9085908590600401620016c9565b600060405180830381600087803b158015620009a757600080fd5b505af1158015620009bc573d6000803e3d6000fd5b505060405163c0c53b8b60e01b81526001600160a01b038416925063c0c53b8b9150620009f49061dead908190819060040162001757565b600060405180830381600087803b15801562000a0f57600080fd5b505af115801562000a24573d6000803e3d6000fd5b50505050600062000a626040518060400160405280601581526020017404f726269745374616e64617264417262455243323605c1b81525062000304565b60405162000a7090620014c6565b8190604051809103906000f590508015801562000a91573d6000803e3d6000fd5b509050600062000acf6040518060400160405280601681526020017527b93134ba2ab833b930b232b0b13632a132b0b1b7b760511b81525062000304565b8260405162000ade90620014d4565b62000aea919062001654565b8190604051809103906000f590508015801562000b0b573d6000803e3d6000fd5b509050600062000b4a604051806040016040528060178152602001764f72626974426561636f6e50726f7879466163746f727960481b81525062000304565b60405162000b5890620014e2565b8190604051809103906000f590508015801562000b79573d6000803e3d6000fd5b5060405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de89062000bab90859060040162001654565b600060405180830381600087803b15801562000bc657600080fd5b505af115801562000bdb573d6000803e3d6000fd5b505060405163c0c53b8b60e01b81526001600160a01b038816925063c0c53b8b915062000c11908c908c90869060040162001757565b600060405180830381600087803b15801562000c2c57600080fd5b505af115801562000c41573d6000803e3d6000fd5b505060405163f2fde38b60e01b81526001600160a01b038516925063f2fde38b915062000c7390899060040162001654565b600060405180830381600087803b15801562000c8e57600080fd5b505af115801562000ca3573d6000803e3d6000fd5b505050505050505050505050505050565b600062000d338262000cf7604051806040016040528060198152602001784f726269744c32437573746f6d4761746577617950726f787960381b81525062000304565b620003ea604051806040016040528060198152602001784f726269744c32437573746f6d476174657761794c6f67696360381b81525062000304565b9050600062000dba600062000d79604051806040016040528060198152602001784f726269744c32437573746f6d476174657761794c6f67696360381b81525062000304565b6200028d8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038416906399a88ec49062000ded9085908590600401620016c9565b600060405180830381600087803b15801562000e0857600080fd5b505af115801562000e1d573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038416925063485cc955915062000e539061dead908190600401620016c9565b600060405180830381600087803b15801562000e6e57600080fd5b505af115801562000e83573d6000803e3d6000fd5b505060405163485cc95560e01b81526001600160a01b038516925063485cc955915062000eb79088908890600401620016c9565b600060405180830381600087803b15801562000ed257600080fd5b505af115801562000ee7573d6000803e3d6000fd5b5050505050505050505050565b600062000f5c8262000f2e6040518060400160405280601081526020016f4f726269744c325745544850726f787960801b81525062000304565b620003ea6040518060400160405280600b81526020016a09ee4c4d2e89864ae8aa8960ab1b81525062000304565b9050600062000f946000620004386040518060400160405280600b81526020016a09ee4c4d2e89864ae8aa8960ab1b81525062000304565b60405163266a23b160e21b81529091506001600160a01b038416906399a88ec49062000fc79085908590600401620016c9565b600060405180830381600087803b15801562000fe257600080fd5b505af115801562000ff7573d6000803e3d6000fd5b50505050600062001076846200103c604051806040016040528060178152602001764f726269744c32576574684761746577617950726f787960481b81525062000304565b620003ea604051806040016040528060178152602001764f726269744c3257657468476174657761794c6f67696360481b81525062000304565b90506000620010fb6000620010ba604051806040016040528060178152602001764f726269744c3257657468476174657761794c6f67696360481b81525062000304565b6200028d8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620012ee92505050565b60405163266a23b160e21b81529091506001600160a01b038616906399a88ec4906200112e9085908590600401620016c9565b600060405180830381600087803b1580156200114957600080fd5b505af11580156200115e573d6000803e3d6000fd5b5050604051637c643b2f60e11b81526001600160a01b038416925063f8c8765e9150620011989061dead908190819081906004016200177a565b600060405180830381600087803b158015620011b357600080fd5b505af1158015620011c8573d6000803e3d6000fd5b5050604051637c643b2f60e11b81526001600160a01b038516925063f8c8765e915062001200908b908a908c908a906004016200177a565b600060405180830381600087803b1580156200121b57600080fd5b505af115801562001230573d6000803e3d6000fd5b505060405163641078a360e11b815260a06004820152600060a4820181905260c0602483015260c48201819052604482015261dead6064820181905260848201526001600160a01b038616925063c820f146915060e401600060405180830381600087803b158015620012a257600080fd5b505af1158015620012b7573d6000803e3d6000fd5b505060405163641078a360e11b81526001600160a01b038716925063c820f1469150620002c29060129086908c90600401620017bc565b6060815182604051602001620013069291906200180b565b6040516020818303038152906040529050919050565b600083471015620013745760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b8151600003620013c75760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016200136b565b8282516020840186f590506001600160a01b038116620014265760405162461bcd60e51b8152602060048201526019602482015278437265617465323a204661696c6564206f6e206465706c6f7960381b60448201526064016200136b565b9392505050565b600082826040516200143f90620014f0565b8190604051809103906000f590508015801562001460573d6000803e3d6000fd5b5085604051806020016040528060008152506040516200148090620014fd565b6200148e939291906200187b565b8190604051809103906000f5905080158015620014af573d6000803e3d6000fd5b50949350505050565b61070f80620018cb83390190565b611e7e8062001fda83390190565b6104e28062003e5883390190565b610cb4806200433a83390190565b605c8062004fee83390190565b610ebb806200504a83390190565b80356001600160a01b03811681146200152357600080fd5b919050565b60008060008060008060008060006101208a8c0312156200154857600080fd5b893567ffffffffffffffff8111156200156057600080fd5b8a0160e0818d0312156200157357600080fd5b98506200158360208b016200150b565b97506200159360408b016200150b565b9650620015a360608b016200150b565b9550620015b360808b016200150b565b9450620015c360a08b016200150b565b9350620015d360c08b016200150b565b9250620015e360e08b016200150b565b9150620015f46101008b016200150b565b90509295985092959850929598565b6000808335601e198436030181126200161b57600080fd5b83018035915067ffffffffffffffff8211156200163757600080fd5b6020019150368190038213156200164d57600080fd5b9250929050565b6001600160a01b0391909116815260200190565b60005b83811015620016855781810151838201526020016200166b565b50506000910152565b60008451620016a281846020890162001668565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b818110156200173357855185168352948301949183019160010162001713565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b60048152630ae8aa8960e31b602082015260400190565b60a081526000620017d060a08301620017a5565b8281036020840152620017e381620017a5565b60ff96909616604084015250506001600160a01b039283166060820152911660809091015290565b710608060405234801561001057600080fd5b560741b8152606160f81b601282015260f083901b6001600160f01b03191660138201526a4030801030001cb00079ff60a91b601582015281516000906200186d81602080860190870162001668565b919091016020019392505050565b600060018060a01b038086168352808516602084015250606060408301528251806060840152620018b481608085016020870162001668565b601f01601f19169190910160800194935050505056fe608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6106918061007e6000396000f3fe60806040526004361061006b5760003560e01c8063204e1c7a14610070578063715018a6146100a65780637eff275e146100bd5780638da5cb5b146100dd5780639623609d146100fb57806399a88ec41461010e578063f2fde38b1461012e578063f3b7dead1461014e575b600080fd5b34801561007c57600080fd5b5061009061008b366004610483565b61016e565b60405161009d91906104a7565b60405180910390f35b3480156100b257600080fd5b506100bb6101ff565b005b3480156100c957600080fd5b506100bb6100d83660046104bb565b610213565b3480156100e957600080fd5b506000546001600160a01b0316610090565b6100bb61010936600461050a565b61027d565b34801561011a57600080fd5b506100bb6101293660046104bb565b6102ec565b34801561013a57600080fd5b506100bb610149366004610483565b610320565b34801561015a57600080fd5b50610090610169366004610483565b61039e565b6000806000836001600160a01b031660405161019490635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101cf576040519150601f19603f3d011682016040523d82523d6000602084013e6101d4565b606091505b5091509150816101e357600080fd5b808060200190518101906101f791906105e0565b949350505050565b6102076103c4565b610211600061041e565b565b61021b6103c4565b6040516308f2839760e41b81526001600160a01b03831690638f283970906102479084906004016104a7565b600060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050505050565b6102856103c4565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102b590869086906004016105fd565b6000604051808303818588803b1580156102ce57600080fd5b505af11580156102e2573d6000803e3d6000fd5b5050505050505050565b6102f46103c4565b604051631b2ce7f360e11b81526001600160a01b03831690633659cfe6906102479084906004016104a7565b6103286103c4565b6001600160a01b0381166103925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61039b8161041e565b50565b6000806000836001600160a01b0316604051610194906303e1469160e61b815260040190565b6000546001600160a01b031633146102115760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610389565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461039b57600080fd5b60006020828403121561049557600080fd5b81356104a08161046e565b9392505050565b6001600160a01b0391909116815260200190565b600080604083850312156104ce57600080fd5b82356104d98161046e565b915060208301356104e98161046e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561051f57600080fd5b833561052a8161046e565b9250602084013561053a8161046e565b9150604084013567ffffffffffffffff8082111561055757600080fd5b818601915086601f83011261056b57600080fd5b81358181111561057d5761057d6104f4565b604051601f8201601f19908116603f011681019083821181831017156105a5576105a56104f4565b816040528281528960208487010111156105be57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156105f257600080fd5b81516104a08161046e565b60018060a01b038316815260006020604081840152835180604085015260005b818110156106395785810183015185820160600152820161061d565b506000606082860101526060601f19601f83011685010192505050939250505056fea26469706673582212208a2d9d6b4833462246845f0898b3da66a9086b54eb9fb2d870a9780af5c177f664736f6c6343000810003360806040523480156200001157600080fd5b50600054610100900460ff1615808015620000335750600054600160ff909116105b8062000063575062000050306200015060201b620007b71760201c565b15801562000063575060005460ff166001145b620000cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000ef576000805461ff0019166101001790555b801562000136576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5060cd805460ff60a01b1916600160a01b1790556200015f565b6001600160a01b03163b151590565b611d0f806200016f6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806370a08231116100b857806395d89b411161007c57806395d89b411461029e578063a457c2d7146102a6578063a9059cbb146102b9578063c2eeeebd146102cc578063d505accf146102df578063dd62ed3e146102f257600080fd5b806370a082311461021157806374f4f5471461023a5780637ecebe001461024d5780638c2a993e146102605780638fa74a0e1461027357600080fd5b8063313ce567116100ff578063313ce567146101b75780633644e515146101d157806339509351146101d95780634000aea0146101ec5780636f791d29146101ff57600080fd5b806306fdde031461013c578063095ea7b31461015a57806318160ddd1461017d578063189db7d21461018f57806323b872dd146101a4575b600080fd5b610144610305565b604051610151919061162e565b60405180910390f35b61016d61016836600461165d565b61032a565b6040519015158152602001610151565b6035545b604051908152602001610151565b6101a261019d36600461174a565b610344565b005b61016d6101b2366004611797565b6103fb565b6101bf610421565b60405160ff9091168152602001610151565b61018161043e565b61016d6101e736600461165d565b610448565b61016d6101fa3660046117d3565b61046a565b60cd54600160a01b900460ff1661016d565b61018161021f366004611829565b6001600160a01b031660009081526033602052604090205490565b6101a261024836600461165d565b6104e0565b61018161025b366004611829565b610521565b6101a261026e36600461165d565b61053f565b60cc54610286906001600160a01b031681565b6040516001600160a01b039091168152602001610151565b610144610573565b61016d6102b436600461165d565b610594565b61016d6102c736600461165d565b61061a565b60cd54610286906001600160a01b031681565b6101a26102ed366004611844565b610628565b6101816103003660046118b7565b61078c565b60ce54606090610100900460ff161561031d57600080fd5b6103256107c6565b905090565b600033610338818585610858565b60019150505b92915050565b60008060008380602001905181019061035d919061193a565b92509250925060008061036f8561097d565b9150915060008061037f8661097d565b9150915060008061038f87610b06565b915091506103a0858483338f610b55565b506040805160608101825291158083529515602083018190529315910181905260ce805461ffff191661ff0019909616959095176101009093029290921762ff00001916620100009092029190911790925550505050505050565b600033610409858285610c27565b610414858585610ca1565b60019150505b9392505050565b60ce5460009060ff161561043457600080fd5b5060385460ff1690565b6000610325610e3a565b60003361033881858561045b838361078c565b61046591906119cd565b610858565b6000610476848461061a565b50836001600160a01b0316336001600160a01b03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1685856040516104bc9291906119e0565b60405180910390a3833b156104d6576104d6848484610eb5565b5060019392505050565b60cc546001600160a01b031633146105135760405162461bcd60e51b815260040161050a90611a01565b60405180910390fd5b61051d8282610f1f565b5050565b6001600160a01b03811660009081526099602052604081205461033e565b60cc546001600160a01b031633146105695760405162461bcd60e51b815260040161050a90611a01565b61051d828261103e565b60ce5460609062010000900460ff161561058c57600080fd5b6103256110ed565b600033816105a2828661078c565b9050838110156106025760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161050a565b61060f8286868403610858565b506001949350505050565b600033610338818585610ca1565b834211156106785760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161050a565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886106a78c6110fc565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e001604051602081830303815290604052805190602001209050600061070282611124565b9050600061071282878787611172565b9050896001600160a01b0316816001600160a01b0316146107755760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161050a565b6107808a8a8a610858565b50505050505050505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6001600160a01b03163b151590565b6060603680546107d590611a27565b80601f016020809104026020016040519081016040528092919081815260200182805461080190611a27565b801561084e5780601f106108235761010080835404028352916020019161084e565b820191906000526020600020905b81548152906001019060200180831161083157829003601f168201915b5050505050905090565b6001600160a01b0383166108ba5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161050a565b6001600160a01b03821661091b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161050a565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000606082516000036109935760009150915091565b8251602003610ae65782516000908490601f9081106109b4576109b4611a5b565b01602001516001600160f81b031916146109d15760009150915091565b6001915060205b600081118015610a1257506000846109f1600184611a71565b81518110610a0157610a01611a5b565b01602001516001600160f81b031916145b15610a295780610a2181611a84565b9150506109d8565b6000816001600160401b03811115610a4357610a43611687565b6040519080825280601f01601f191660200182016040528015610a6d576020820181803683370190505b50905060005b828160ff161015610adc57858160ff1681518110610a9357610a93611a5b565b602001015160f81c60f81b828260ff1681518110610ab357610ab3611a5b565b60200101906001600160f81b031916908160001a90535080610ad481611a9b565b915050610a73565b509150610b019050565b6001915082806020019051810190610afe9190611aba565b90505b915091565b6000808251602014610b1d57506000928392509050565b600083806020019051810190610b339190611b02565b905060ff811115610b4a5750600093849350915050565b600194909350915050565b6001600160a01b038216610b9d5760405162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015260640161050a565b60cc546001600160a01b031615610be55760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640161050a565b60cc80546001600160a01b038085166001600160a01b03199283161790925560cd805492841692909116919091179055610c2085858561119a565b5050505050565b6000610c33848461078c565b90506000198114610c9b5781811015610c8e5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161050a565b610c9b8484848403610858565b50505050565b6001600160a01b038316610d055760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161050a565b6001600160a01b038216610d675760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161050a565b6001600160a01b03831660009081526033602052604090205481811015610ddf5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161050a565b6001600160a01b038085166000818152603360205260408082208686039055928616808252908390208054860190559151600080516020611cba83398151915290610e2d9086815260200190565b60405180910390a3610c9b565b60006103257f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610e6960655490565b6066546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b604051635260769b60e11b815283906001600160a01b0382169063a4c0ed3690610ee790339087908790600401611b1b565b600060405180830381600087803b158015610f0157600080fd5b505af1158015610f15573d6000803e3d6000fd5b5050505050505050565b6001600160a01b038216610f7f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161050a565b6001600160a01b03821660009081526033602052604090205481811015610ff35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161050a565b6001600160a01b0383166000818152603360209081526040808320868603905560358054879003905551858152919291600080516020611cba8339815191529101610970565b505050565b6001600160a01b0382166110945760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161050a565b80603560008282546110a691906119cd565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020611cba833981519152910160405180910390a35050565b6060603780546107d590611a27565b6001600160a01b03811660009081526099602052604090208054600181018255905b50919050565b600061033e611131610e3a565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000611183878787876112ce565b9150915061119081611388565b5095945050505050565b600054610100900460ff16158080156111ba5750600054600160ff909116105b806111db57506111c9306107b7565b1580156111db575060005460ff166001145b61123e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161050a565b6000805460ff191660011790558015611261576000805461ff0019166101001790555b61126a846114d0565b611274848461151a565b6038805460ff191660ff84161790558015610c9b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156112fb575060009050600361137f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561134f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166113785760006001925092505061137f565b9150600090505b94509492505050565b600081600481111561139c5761139c611b4b565b036113a45750565b60018160048111156113b8576113b8611b4b565b036114005760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b604482015260640161050a565b600281600481111561141457611414611b4b565b036114615760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161050a565b600381600481111561147557611475611b4b565b036114cd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161050a565b50565b600054610100900460ff166114f75760405162461bcd60e51b815260040161050a90611b61565b6114cd81604051806040016040528060018152602001603160f81b81525061154b565b600054610100900460ff166115415760405162461bcd60e51b815260040161050a90611b61565b61051d828261158c565b600054610100900460ff166115725760405162461bcd60e51b815260040161050a90611b61565b815160209283012081519190920120606591909155606655565b600054610100900460ff166115b35760405162461bcd60e51b815260040161050a90611b61565b60366115bf8382611bfa565b5060376115cc8282611bfa565b50506038805460ff1916601217905550565b60005b838110156115f95781810151838201526020016115e1565b50506000910152565b6000815180845261161a8160208601602086016115de565b601f01601f19169290920160200192915050565b60208152600061041a6020830184611602565b80356001600160a01b038116811461165857600080fd5b919050565b6000806040838503121561167057600080fd5b61167983611641565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156116c5576116c5611687565b604052919050565b60006001600160401b038211156116e6576116e6611687565b50601f01601f191660200190565b600082601f83011261170557600080fd5b8135611718611713826116cd565b61169d565b81815284602083860101111561172d57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561175d57600080fd5b61176683611641565b915060208301356001600160401b0381111561178157600080fd5b61178d858286016116f4565b9150509250929050565b6000806000606084860312156117ac57600080fd5b6117b584611641565b92506117c360208501611641565b9150604084013590509250925092565b6000806000606084860312156117e857600080fd5b6117f184611641565b92506020840135915060408401356001600160401b0381111561181357600080fd5b61181f868287016116f4565b9150509250925092565b60006020828403121561183b57600080fd5b61041a82611641565b600080600080600080600060e0888a03121561185f57600080fd5b61186888611641565b965061187660208901611641565b95506040880135945060608801359350608088013560ff8116811461189a57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156118ca57600080fd5b6118d383611641565b91506118e160208401611641565b90509250929050565b60006118f8611713846116cd565b905082815283838301111561190c57600080fd5b61041a8360208301846115de565b600082601f83011261192b57600080fd5b61041a838351602085016118ea565b60008060006060848603121561194f57600080fd5b83516001600160401b038082111561196657600080fd5b6119728783880161191a565b9450602086015191508082111561198857600080fd5b6119948783880161191a565b935060408601519150808211156119aa57600080fd5b5061181f8682870161191a565b634e487b7160e01b600052601160045260246000fd5b8082018082111561033e5761033e6119b7565b8281526040602082015260006119f96040830184611602565b949350505050565b6020808252600c908201526b4f4e4c595f4741544557415960a01b604082015260600190565b600181811c90821680611a3b57607f821691505b60208210810361111e57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b8181038181111561033e5761033e6119b7565b600081611a9357611a936119b7565b506000190190565b600060ff821660ff8103611ab157611ab16119b7565b60010192915050565b600060208284031215611acc57600080fd5b81516001600160401b03811115611ae257600080fd5b8201601f81018413611af357600080fd5b6119f9848251602084016118ea565b600060208284031215611b1457600080fd5b5051919050565b60018060a01b0384168152826020820152606060408201526000611b426060830184611602565b95945050505050565b634e487b7160e01b600052602160045260246000fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b601f82111561103957600081815260208120601f850160051c81016020861015611bd35750805b601f850160051c820191505b81811015611bf257828155600101611bdf565b505050505050565b81516001600160401b03811115611c1357611c13611687565b611c2781611c218454611a27565b84611bac565b602080601f831160018114611c5c5760008415611c445750858301515b600019600386901b1c1916600185901b178555611bf2565b600085815260208120601f198616915b82811015611c8b57888601518255948401946001909101908401611c6c565b5085821015611ca95787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122070845537e703bebbfe17ccc1f6f77686f42e5101a18b732d87a34447165dfe1164736f6c63430008100033608060405234801561001057600080fd5b506040516104e23803806104e283398101604081905261002f91610151565b61003833610047565b61004181610097565b50610181565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161014260201b6101a01760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03163b151590565b60006020828403121561016357600080fd5b81516001600160a01b038116811461017a57600080fd5b9392505050565b610352806101906000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ec565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ec565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029c565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029c565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b610212816101a0565b61027a5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156102fe57600080fd5b81356001600160a01b038116811461031557600080fd5b939250505056fea264697066735822122059e4b83111825434711a238db6203ec67d74a40640c8c22ba30c6fc5fc18964a64736f6c63430008100033608060405234801561001057600080fd5b50610c94806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000765760003560e01c806329a5c5cf146200007b578063396a5f9514620000af57806359659e9014620000c657806397881f8d14620000da578063b3e3bf4214620000f3578063c4d66de8146200010a578063e75b21411462000123575b600080fd5b620000926200008c36600462000354565b6200013a565b6040516001600160a01b0390911681526020015b60405180910390f35b62000092620000c036600462000354565b62000186565b60005462000092906001600160a01b031681565b620000e4620001c7565b604051908152602001620000a6565b620000e4620001043660046200038b565b620001f6565b620001216200011b366004620003b8565b62000233565b005b62000092620001343660046200038b565b620002ec565b600080620001493384620001f6565b90506000816040516200015c9062000346565b8190604051809103906000f59050801580156200017d573d6000803e3d6000fd5b50949350505050565b6000620001c182604051806020016200019f9062000346565b6020820181038252601f19601f8201166040525080519060200120306200031c565b92915050565b604051620001d86020820162000346565b6020820181038252601f19601f820116604052508051906020012081565b604080516001600160a01b038416602082015290810182905260009060600160405160208183030381529060405280519060200120905092915050565b6001600160a01b038116620002805760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa122a0a1a7a760911b60448201526064015b60405180910390fd5b6000546001600160a01b031615620002ca5760405162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015260640162000277565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080620002fb8484620001f6565b90506200031481604051806020016200019f9062000346565b949350505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b61088180620003de83390190565b6000602082840312156200036757600080fd5b5035919050565b80356001600160a01b03811681146200038657600080fd5b919050565b600080604083850312156200039f57600080fd5b620003aa836200036e565b946020939093013593505050565b600060208284031215620003cb57600080fd5b620003d6826200036e565b939250505056fe608060405234801561001057600080fd5b50336001600160a01b03166359659e906040518163ffffffff1660e01b8152600401602060405180830381865afa15801561004f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610073919061046c565b604051806020016040528060008152506100958282600061009c60201b60201c565b5050610508565b6100a583610167565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a26000825111806100e65750805b1561016257610160836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561012c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610150919061046c565b8361030a60201b6100291760201c565b505b505050565b61017a8161033660201b6100551760201c565b6101d95760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b61024d816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561021a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023e919061046c565b61033660201b6100551760201c565b6102b25760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b60648201526084016101d0565b806102e97fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b61034560201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b606061032f838360405180606001604052806027815260200161085a60279139610348565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b03168560405161036591906104b9565b600060405180830381855af49150503d80600081146103a0576040519150601f19603f3d011682016040523d82523d6000602084013e6103a5565b606091505b5090925090506103b7868383876103c1565b9695505050505050565b60608315610430578251600003610429576001600160a01b0385163b6104295760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d0565b508161043a565b61043a8383610442565b949350505050565b8151156104525781518083602001fd5b8060405162461bcd60e51b81526004016101d091906104d5565b60006020828403121561047e57600080fd5b81516001600160a01b038116811461032f57600080fd5b60005b838110156104b0578181015183820152602001610498565b50506000910152565b600082516104cb818460208701610495565b9190910192915050565b60208152600082518060208401526104f4816040850160208701610495565b601f01601f19169190910160400192915050565b610343806105176000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102e760279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024a565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b0316856040516101419190610297565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020e578251600003610207576101b685610055565b6102075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610218565b6102188383610220565b949350505050565b8151156102305781518083602001fd5b8060405162461bcd60e51b81526004016101fe91906102b3565b60006020828403121561025c57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028e578181015183820152602001610276565b50506000910152565b600082516102a9818460208701610273565b9190910192915050565b60208152600082518060208401526102d2816040850160208701610273565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e9bed491ce4cc7495def60dc616a13f39ccd912637e0c8ba02d45400506de9c064736f6c63430008100033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220237fb73aef7b871fb5f0c1ef15f58a63a1b7502356cc319c2d83ad0717d2cd7264736f6c634300081000336080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea26469706673582212203fc1d73d12f631c8d0a3a1e5ebc667c0e6e4c09698b94f0ed53d99f55382279e64736f6c63430008100033608060405260405162000ebb38038062000ebb833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e9460279139620002f8565b9392505050565b60006200018060008051602062000e7483398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e7483398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61089a80620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e838360405180606001604052806027815260200161083e6027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610691565b81019061020091906106d7565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610691565b8101906102509190610708565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610691565b81019061029d91906106d7565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107ee565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c4565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610504565b50565b600061041c6105ad565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b25782516000036104ab5761045f85610198565b6104ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104bc565b6104bc83836105d5565b949350505050565b6104cd816105ff565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105695760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e55781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080a565b61060881610198565b61066a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058c565b600080858511156106a157600080fd5b838611156106ae57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d257600080fd5b919050565b6000602082840312156106e957600080fd5b61018e826106bb565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071b57600080fd5b610724836106bb565b9150602083013567ffffffffffffffff8082111561074157600080fd5b818501915085601f83011261075557600080fd5b813581811115610767576107676106f2565b604051601f8201601f19908116603f0116810190838211818310171561078f5761078f6106f2565b816040528281528860208487010111156107a857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e55781810151838201526020016107cd565b50506000910152565b600082516108008184602087016107ca565b9190910192915050565b60208152600082518060208401526108298160408501602087016107ca565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122072007c277cc5d8471be1434c6b2d5b70fb7c2f6f77a0697617733c4d4ae5b76964736f6c63430008100033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220377d031a5f294a74596aa9acc30ca418bd32dd3f9cbae6ed71ce8cc1f17439cc64736f6c63430008100033\",\n            \"nonce\": \"0x0\",\n            \"to\": null,\n            \"transactionIndex\": \"0x2\",\n            \"value\": \"0x0\",\n            \"type\": \"0x68\",\n            \"chainId\": \"0xda8c8b77\",\n            \"v\": \"0x0\",\n            \"r\": \"0x0\",\n            \"s\": \"0x0\",\n            \"ticketId\": \"0x07fcc2df6293de1451ca79c4299ff16845d2572a41985a0426806aeb09b22d23\",\n            \"maxRefund\": \"0x22f2505249400\",\n            \"submissionFeeRefund\": \"0xd72a2471400\",\n            \"refundTo\": \"0xbee947aec820389c1560c87bd96e2723bad05b61\"\n        }\n    ],\n    \"transactionsRoot\": \"0xe44e2d243f72d352be0157632b1fc84149b77914c0e429faac99bdca4acc66b0\",\n    \"uncles\": []\n}"
  },
  {
    "path": "testsuite/block-full.json",
    "content": "{\n    \"number\": \"0x1\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"parentHash\": \"0x0000000000000000000000000000000000000000000000000000000000000002\",\n    \"sha3Uncles\": \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n    \"transactionsRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"stateRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n    \"receiptsRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000002\",\n    \"miner\": \"0x0000000000000000000000000000000000000001\",\n    \"gasLimit\": \"0x2\",\n    \"gasUsed\": \"0x3\",\n    \"timestamp\": \"0x4\",\n    \"difficulty\": \"0x5\",\n    \"extraData\": \"0x01\",\n    \"mixHash\": \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n    \"nonce\": \"0x0a00000000000000\",\n    \"uncles\": [\n        \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n        \"0x0000000000000000000000000000000000000000000000000000000000000002\"\n    ],\n    \"transactions\": [\n        {\n            \"type\": \"0x0\",\n            \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n            \"from\": \"0x0000000000000000000000000000000000000001\",\n            \"input\": \"0x00\",\n            \"value\": \"0x0\",\n            \"gasPrice\": \"0x0\",\n            \"gas\": \"0x10\",\n            \"nonce\": \"0x10\",\n            \"to\": \"0x0000000000000000000000000000000000000001\",\n            \"v\": \"0x25\",\n            \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n            \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n            \"blockHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n            \"blockNumber\": \"0x0\",\n            \"transactionIndex\": \"0x0\"\n        }\n    ]\n}"
  },
  {
    "path": "testsuite/block-txn-hashes.json",
    "content": "{\n    \"number\": \"0x1\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"parentHash\": \"0x0000000000000000000000000000000000000000000000000000000000000002\",\n    \"sha3Uncles\": \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n    \"transactionsRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"stateRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n    \"receiptsRoot\": \"0x0000000000000000000000000000000000000000000000000000000000000002\",\n    \"miner\": \"0x0000000000000000000000000000000000000001\",\n    \"gasLimit\": \"0x2\",\n    \"gasUsed\": \"0x3\",\n    \"timestamp\": \"0x4\",\n    \"difficulty\": \"0x5\",\n    \"extraData\": \"0x01\",\n    \"mixHash\": \"0x0000000000000000000000000000000000000000000000000000000000000003\",\n    \"nonce\": \"0x0a00000000000000\",\n    \"uncles\": [\n        \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n        \"0x0000000000000000000000000000000000000000000000000000000000000002\"\n    ],\n    \"transactions\": [\n        \"0x0000000000000000000000000000000000000000000000000000000000000001\"\n    ]\n}"
  },
  {
    "path": "testsuite/receipts.json",
    "content": "[\n    {\n        \"blockHash\": \"0x1ee40a01cdb865600eef166d175eade70ab51f215c5663a7fcc5ec1f960f4e40\",\n        \"blockNumber\": \"0x10482a\",\n        \"contractAddress\": \"0xd63d7145f125b16bb36fe73f2128bb77dcc8ccf1\",\n        \"cumulativeGasUsed\": \"0x3765f\",\n        \"effectiveGasPrice\": \"0xba43b7400\",\n        \"from\": \"0x20e021a751cb6bcab2eaf7b9db570ec10c8ad0a2\",\n        \"gasUsed\": \"0x32457\",\n        \"logs\": [],\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"root\": \"0xe41f2551706d287917eb795bb81348d68ca6f9300e1394e4c8d3288ae16865dc\",\n        \"to\": null,\n        \"transactionHash\": \"0xcbb8db2cec3fa38e2ff221462708252bbbe32abb57e5a43f402155880d2883e0\",\n        \"transactionIndex\": \"0x1\",\n        \"type\": \"0x0\"\n    },\n    {\n        \"blockHash\": \"0x7ba787b8371397a05412121bf915373ebbcdfa6e4117f6076911a34ee9bca4a8\",\n        \"blockNumber\": \"0xee76d0\",\n        \"contractAddress\": null,\n        \"cumulativeGasUsed\": \"0x114db42\",\n        \"effectiveGasPrice\": \"0x222359b14\",\n        \"from\": \"0xdafea492d9c6733ae3d56b7ed1adb60692c98bc5\",\n        \"gasUsed\": \"0x523f\",\n        \"logs\": [],\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"status\": \"0x1\",\n        \"to\": \"0xebec795c9c8bbd61ffc14a6662944748f299cacf\",\n        \"transactionHash\": \"0xdd002538bd3165c8aed8a7435f965420bca4406951e490190f4271302a4c5254\",\n        \"transactionIndex\": \"0x90\",\n        \"type\": \"0x0\"\n    }\n]"
  },
  {
    "path": "testsuite/transaction-call.json",
    "content": "{\n    \"type\": \"0x0\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"from\": \"0x0000000000000000000000000000000000000001\",\n    \"input\": \"0x00\",\n    \"value\": \"0x0\",\n    \"gasPrice\": \"0x0\",\n    \"gas\": \"0x10\",\n    \"nonce\": \"0x10\",\n    \"to\": \"0x0000000000000000000000000000000000000001\",\n    \"v\": \"0x25\",\n    \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockNumber\": \"0x0\",\n    \"transactionIndex\": \"0x0\"\n}"
  },
  {
    "path": "testsuite/transaction-contract-creation.json",
    "content": "{\n    \"type\": \"0x0\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"from\": \"0x0000000000000000000000000000000000000001\",\n    \"input\": \"0x00\",\n    \"value\": \"0x0\",\n    \"gasPrice\": \"0x0\",\n    \"gas\": \"0x10\",\n    \"nonce\": \"0x10\",\n    \"to\": null,\n    \"v\": \"0x25\",\n    \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockNumber\": \"0x0\",\n    \"transactionIndex\": \"0x0\"\n}"
  },
  {
    "path": "testsuite/transaction-eip1159.json",
    "content": "{\n    \"type\": \"0x2\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"from\": \"0x0000000000000000000000000000000000000001\",\n    \"input\": \"0x00\",\n    \"value\": \"0x0\",\n    \"maxPriorityFeePerGas\": \"0x10\",\n    \"maxFeePerGas\": \"0x10\",\n    \"gas\": \"0x10\",\n    \"nonce\": \"0x10\",\n    \"to\": null,\n    \"v\": \"0x25\",\n    \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockNumber\": \"0x0\",\n    \"transactionIndex\": \"0x0\",\n    \"chainId\": \"0x1\",\n    \"accessList\": [\n        {\n            \"address\": \"0x0000000000000000000000000000000000000001\",\n            \"storageKeys\": [\n                \"0x0000000000000000000000000000000000000000000000000000000000000001\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "testsuite/transaction-eip1559-notype.json",
    "content": "{\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"from\": \"0x0000000000000000000000000000000000000001\",\n    \"input\": \"0x00\",\n    \"value\": \"0x0\",\n    \"maxPriorityFeePerGas\": \"0x10\",\n    \"maxFeePerGas\": \"0x10\",\n    \"gas\": \"0x10\",\n    \"nonce\": \"0x10\",\n    \"to\": null,\n    \"v\": \"0x25\",\n    \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockNumber\": \"0x0\",\n    \"transactionIndex\": \"0x0\",\n    \"chainId\": \"0x1\",\n    \"accessList\": [\n        {\n            \"address\": \"0x0000000000000000000000000000000000000001\",\n            \"storageKeys\": [\n                \"0x0000000000000000000000000000000000000000000000000000000000000001\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "testsuite/transaction-eip2930.json",
    "content": "{\n    \"type\": \"0x1\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"from\": \"0x0000000000000000000000000000000000000001\",\n    \"input\": \"0x00\",\n    \"value\": \"0x0\",\n    \"gasPrice\": \"0x0\",\n    \"gas\": \"0x10\",\n    \"nonce\": \"0x10\",\n    \"to\": null,\n    \"v\": \"0x25\",\n    \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockNumber\": \"0x0\",\n    \"transactionIndex\": \"0x0\",\n    \"chainId\": \"0x1\",\n    \"accessList\": [\n        {\n            \"address\": \"0x0000000000000000000000000000000000000001\",\n            \"storageKeys\": [\n                \"0x0000000000000000000000000000000000000000000000000000000000000001\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "testsuite/transaction-pending.json",
    "content": "{\n    \"type\": \"0x0\",\n    \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"from\": \"0x0000000000000000000000000000000000000001\",\n    \"input\": \"0x00\",\n    \"value\": \"0x0\",\n    \"gasPrice\": \"0x0\",\n    \"gas\": \"0x10\",\n    \"nonce\": \"0x10\",\n    \"to\": \"0x0000000000000000000000000000000000000001\",\n    \"v\": \"0x25\",\n    \"r\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"s\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n    \"blockHash\": null,\n    \"blockNumber\": null,\n    \"transactionIndex\": null\n}"
  },
  {
    "path": "testutil/contract.go",
    "content": "package testutil\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo/compiler\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\n// Contract is a test contract\ntype Contract struct {\n\tevents    []*Event\n\tcallbacks []func() string\n}\n\n// AddEvent adds a new event to the contract\nfunc (c *Contract) AddEvent(e *Event) {\n\tif c.events == nil {\n\t\tc.events = []*Event{}\n\t}\n\tc.AddCallback(e.printDecl)\n\tc.AddCallback(e.printSetter)\n\tc.events = append(c.events, e)\n}\n\n// GetEvent returns the event with the given name\nfunc (c *Contract) GetEvent(name string) *Event {\n\tfor _, i := range c.events {\n\t\tif i.name == name {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn nil\n}\n\n// Print prints the contract\nfunc (c *Contract) Print() string {\n\tstr := \"pragma solidity ^0.5.5;\\n\"\n\tstr += \"pragma experimental ABIEncoderV2;\\n\"\n\tstr += \"\\n\"\n\tstr += \"contract Sample {\\n\"\n\n\tfor _, f := range c.callbacks {\n\t\tstr += f() + \"\\n\"\n\t}\n\n\tstr += \"}\"\n\treturn str\n}\n\nfunc (c *Contract) AddCallback(f func() string) {\n\tif c.callbacks == nil {\n\t\tc.callbacks = []func() string{}\n\t}\n\tc.callbacks = append(c.callbacks, f)\n}\n\n// Compile compiles the contract\nfunc (c *Contract) Compile() (*compiler.Artifact, error) {\n\toutput, err := compiler.NewSolidityCompiler(\"solc\").CompileCode(c.Print())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsolcContract, ok := output.Contracts[\"<stdin>:Sample\"]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"Expected the contract to be called Sample\")\n\t}\n\treturn solcContract, nil\n}\n\n// AddConstructor creates a constructor with args that set contract variables\nfunc (c *Contract) AddConstructor(args ...string) {\n\t// add variables\n\tc.AddCallback(func() string {\n\t\tstr := \"\"\n\n\t\tinput := []string{}\n\t\tbody := \"\"\n\t\tfor indx, arg := range args {\n\t\t\tstr += fmt.Sprintf(\"%s public val_%d;\\n\", arg, indx)\n\n\t\t\tinput = append(input, fmt.Sprintf(\"%s local_%d\", arg, indx))\n\t\t\tbody += fmt.Sprintf(\"val_%d = local_%d;\\n\", indx, indx)\n\t\t}\n\n\t\tstr += \"constructor(\" + strings.Join(input, \",\") + \") public {\\n\"\n\t\tstr += body\n\t\tstr += \"}\"\n\t\treturn str\n\t})\n}\n\n// AddDualCaller adds a call function that returns the same values that takes\nfunc (c *Contract) AddDualCaller(funcName string, args ...string) {\n\tc.AddCallback(func() string {\n\t\tvar params, rets, body []string\n\t\tfor indx, i := range args {\n\t\t\tname := \"val_\" + strconv.Itoa(indx)\n\t\t\t// function params\n\t\t\tparams = append(params, i+\" \"+name)\n\t\t\t// function returns\n\t\t\trets = append(rets, i)\n\t\t\t// function body\n\t\t\tbody = append(body, name)\n\t\t}\n\n\t\tstr := \"function \" + funcName + \"(\" + strings.Join(params, \",\") + \") public view returns (\" + strings.Join(rets, \",\") + \") {\\n\"\n\t\tstr += \"return (\" + strings.Join(body, \",\") + \");\\n\"\n\t\tstr += \"}\"\n\t\treturn str\n\t})\n}\n\n// AddOutputCaller adsd a view function that does not take any input\nfunc (c *Contract) AddOutputCaller(funcName string) {\n\tc.AddCallback(func() string {\n\t\treturn `function ` + funcName + ` () public view returns (uint256) {\n\t\t\treturn 1;\n\t\t}`\n\t})\n}\n\n// EmitEvent emits a specific event\nfunc (c *Contract) EmitEvent(funcName string, name string, args ...string) {\n\texists := false\n\tfor _, i := range c.events {\n\t\tif i.name == name {\n\t\t\texists = true\n\t\t}\n\t}\n\tif !exists {\n\t\tpanic(fmt.Errorf(\"event %s does not exists\", name))\n\t}\n\tc.AddCallback(func() string {\n\t\tstr := \"function \" + funcName + \"() public payable {\\n\"\n\t\tstr += fmt.Sprintf(\"emit %s(%s)\", name, strings.Join(args, \", \")) + \";\\n\"\n\t\tstr += \"}\"\n\t\treturn str\n\t})\n}\n\ntype eventField struct {\n\tindexed bool\n\ttyp     string\n}\n\n// Event is a test event\ntype Event struct {\n\tname   string\n\tfields []*eventField\n}\n\nfunc (e *Event) printDecl() string {\n\targs := []string{}\n\tfor indx, i := range e.fields {\n\t\targ := i.typ\n\t\tif i.indexed {\n\t\t\targ += \" indexed\"\n\t\t}\n\t\targ += \" val_\" + strconv.Itoa(indx)\n\t\targs = append(args, arg)\n\t}\n\treturn fmt.Sprintf(\"event %s(%s);\", e.name, strings.Join(args, \", \"))\n}\n\nfunc (e *Event) printSetter() string {\n\tparams := []string{}\n\tbody := []string{}\n\tfor indx, i := range e.fields {\n\t\t// function params\n\n\t\t// Some params are in memory\n\t\ttyp := i.typ\n\t\tif typ == \"string\" || strings.Contains(typ, \"[\") {\n\t\t\ttyp = typ + \" memory\"\n\t\t}\n\t\tparams = append(params, fmt.Sprintf(\"%s val_%d\", typ, indx))\n\t\t// function body\n\t\tbody = append(body, fmt.Sprintf(\"val_%d\", indx))\n\t}\n\n\tstr := \"function setter\" + e.name + \"(\" + strings.Join(params, \", \") + \") public payable {\\n\"\n\tstr += \"emit \" + e.name + \"(\" + strings.Join(body, \", \") + \");\\n\"\n\tstr += \"}\"\n\treturn str\n}\n\n// Add adds a new field to the event\nfunc (e *Event) Add(typStr string, indexed bool) *Event {\n\tif e.fields == nil {\n\t\te.fields = []*eventField{}\n\t}\n\te.fields = append(e.fields, &eventField{indexed, typStr})\n\treturn e\n}\n\n// Sig returns the signature of the event\nfunc (e *Event) Sig() string {\n\targs := []string{}\n\tfor _, i := range e.fields {\n\t\targs = append(args, i.typ)\n\t}\n\n\tsignature := e.name + \"(\" + strings.Join(args, \",\") + \")\"\n\n\th := sha3.NewLegacyKeccak256()\n\th.Write([]byte(signature))\n\tb := h.Sum(nil)\n\treturn \"0x\" + hex.EncodeToString(b)\n}\n\n// NewEvent creates a new contract event\nfunc NewEvent(name string, args ...interface{}) *Event {\n\tif len(args)%2 != 0 {\n\t\tpanic(\"it should be even\")\n\t}\n\te := &Event{name: name}\n\tfor i := 0; i < len(args); i++ {\n\t\te.Add(args[i].(string), args[i+1].(bool))\n\t}\n\treturn e\n}\n"
  },
  {
    "path": "testutil/mock.go",
    "content": "package testutil\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\ntype mockCall int\n\nconst (\n\tblockByNumberCall mockCall = iota\n\tblockByHashCall\n\tblockNumberCall\n\tgetLogsCall\n)\n\ntype MockClient struct {\n\tlock     sync.Mutex\n\tnum      uint64\n\tblockNum map[uint64]ethgo.Hash\n\tblocks   map[ethgo.Hash]*ethgo.Block\n\tlogs     map[ethgo.Hash][]*ethgo.Log\n\tchainID  *big.Int\n}\n\nfunc (m *MockClient) SetChainID(id *big.Int) {\n\tm.chainID = id\n}\n\nfunc (d *MockClient) ChainID() (*big.Int, error) {\n\tif d.chainID == nil {\n\t\td.chainID = big.NewInt(1337)\n\t}\n\treturn d.chainID, nil\n}\n\nfunc (d *MockClient) GetLastBlocks(n uint64) (res []*ethgo.Block) {\n\tif d.num == 0 {\n\t\treturn\n\t}\n\tnum := n\n\tif d.num < num {\n\t\tnum = d.num + 1\n\t}\n\n\tfor i := int(num - 1); i >= 0; i-- {\n\t\tres = append(res, d.blocks[d.blockNum[d.num-uint64(i)]])\n\t}\n\treturn\n}\n\nfunc (d *MockClient) GetAllLogs() (res []*ethgo.Log) {\n\tif d.num == 0 {\n\t\treturn\n\t}\n\tfor i := uint64(0); i <= d.num; i++ {\n\t\tres = append(res, d.logs[d.blocks[d.blockNum[i]].Hash]...)\n\t}\n\treturn\n}\n\nfunc (d *MockClient) AddScenario(m MockList) {\n\td.lock.Lock()\n\tdefer d.lock.Unlock()\n\n\t// add the logs\n\tfor _, b := range m {\n\t\tblock := &ethgo.Block{\n\t\t\tHash:   b.Hash(),\n\t\t\tNumber: uint64(b.num),\n\t\t}\n\n\t\tif b.num != 0 {\n\t\t\tbb, err := d.blockByNumberLock(uint64(b.num) - 1)\n\t\t\tif err != nil {\n\t\t\t\t// This happens during reconcile tests because we include only partial blocks\n\t\t\t\tblock.ParentHash = encodeHash(strconv.Itoa(b.num - 1))\n\t\t\t} else {\n\t\t\t\tblock.ParentHash = bb.Hash\n\t\t\t}\n\t\t}\n\n\t\t// add history block\n\t\td.addBlocks(block)\n\n\t\t// add logs\n\t\t// remove any other logs for this block in case there are any\n\t\tif _, ok := d.logs[block.Hash]; ok {\n\t\t\tdelete(d.logs, block.Hash)\n\t\t}\n\n\t\td.AddLogs(b.GetLogs())\n\t}\n}\n\nfunc (d *MockClient) AddLogs(logs []*ethgo.Log) {\n\tif d.logs == nil {\n\t\td.logs = map[ethgo.Hash][]*ethgo.Log{}\n\t}\n\tfor _, log := range logs {\n\t\tentry, ok := d.logs[log.BlockHash]\n\t\tif ok {\n\t\t\tentry = append(entry, log)\n\t\t} else {\n\t\t\tentry = []*ethgo.Log{log}\n\t\t}\n\t\td.logs[log.BlockHash] = entry\n\t}\n}\n\nfunc (d *MockClient) addBlocks(bb ...*ethgo.Block) {\n\tif d.blocks == nil {\n\t\td.blocks = map[ethgo.Hash]*ethgo.Block{}\n\t}\n\tif d.blockNum == nil {\n\t\td.blockNum = map[uint64]ethgo.Hash{}\n\t}\n\tfor _, b := range bb {\n\t\tif b.Number > d.num {\n\t\t\td.num = b.Number\n\t\t}\n\t\td.blocks[b.Hash] = b\n\t\td.blockNum[b.Number] = b.Hash\n\t}\n}\n\nfunc (d *MockClient) BlockNumber() (uint64, error) {\n\td.lock.Lock()\n\tdefer d.lock.Unlock()\n\n\treturn d.num, nil\n}\n\nfunc (d *MockClient) GetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block, error) {\n\td.lock.Lock()\n\tdefer d.lock.Unlock()\n\n\tb := d.blocks[hash]\n\tif b == nil {\n\t\treturn nil, fmt.Errorf(\"hash %s not found\", hash)\n\t}\n\treturn b, nil\n}\n\nfunc (d *MockClient) blockByNumberLock(i uint64) (*ethgo.Block, error) {\n\thash, ok := d.blockNum[i]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"number %d not found\", i)\n\t}\n\treturn d.blocks[hash], nil\n}\n\nfunc (d *MockClient) GetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error) {\n\td.lock.Lock()\n\tdefer d.lock.Unlock()\n\n\tif i < 0 {\n\t\tswitch i {\n\t\tcase ethgo.Latest:\n\t\t\tif d.num == 0 {\n\t\t\t\treturn &ethgo.Block{Number: 0}, nil\n\t\t\t}\n\t\t\treturn d.blockByNumberLock(d.num)\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"getBlockByNumber query not supported\")\n\t\t}\n\t}\n\treturn d.blockByNumberLock(uint64(i))\n}\n\nfunc (d *MockClient) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error) {\n\td.lock.Lock()\n\tdefer d.lock.Unlock()\n\n\tif filter.BlockHash != nil {\n\t\treturn d.logs[*filter.BlockHash], nil\n\t}\n\n\tfrom, to := uint64(*filter.From), uint64(*filter.To)\n\tif from > to {\n\t\treturn nil, fmt.Errorf(\"from higher than to\")\n\t}\n\tif int(to) > len(d.blocks) {\n\t\treturn nil, fmt.Errorf(\"out of bounds\")\n\t}\n\n\tlogs := []*ethgo.Log{}\n\tfor i := from; i <= to; i++ {\n\t\tb, err := d.blockByNumberLock(i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\telems, ok := d.logs[b.Hash]\n\t\tif ok {\n\t\t\tlogs = append(logs, elems...)\n\t\t}\n\t}\n\treturn logs, nil\n}\n\ntype MockLog struct {\n\tdata string\n}\n\ntype MockBlock struct {\n\thash   string\n\textra  string\n\tparent string\n\tnum    int\n\tlogs   []*MockLog\n}\n\nfunc mustDecodeHash(str string) []byte {\n\tif strings.HasPrefix(str, \"0x\") {\n\t\tstr = str[2:]\n\t}\n\tif len(str)%2 == 1 {\n\t\tstr = str + \"0\"\n\t}\n\tbuf, err := hex.DecodeString(str)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn buf\n}\n\nfunc (m *MockBlock) Extra(data string) *MockBlock {\n\tm.extra = data\n\treturn m\n}\n\nfunc (m *MockBlock) GetLogs() (logs []*ethgo.Log) {\n\tfor _, log := range m.logs {\n\t\tlogs = append(logs, &ethgo.Log{Data: mustDecodeHash(log.data), BlockNumber: uint64(m.num), BlockHash: m.Hash()})\n\t}\n\treturn\n}\n\nfunc (m *MockBlock) Log(data string) *MockBlock {\n\tm.logs = append(m.logs, &MockLog{data})\n\treturn m\n}\n\nfunc (m *MockBlock) GetNum() int {\n\treturn m.num\n}\n\nfunc (m *MockBlock) Num(i int) *MockBlock {\n\tm.num = i\n\treturn m\n}\n\nfunc (m *MockBlock) Parent(i int) *MockBlock {\n\tm.parent = strconv.Itoa(i)\n\tm.num = i + 1\n\treturn m\n}\n\nfunc encodeHash(str string) (h ethgo.Hash) {\n\ttmp := \"\"\n\tfor i := 0; i < 64-len(str); i++ {\n\t\ttmp += \"0\"\n\t}\n\tstr = \"0x\" + tmp + str\n\tif err := h.UnmarshalText([]byte(str)); err != nil {\n\t\tpanic(err)\n\t}\n\treturn\n}\n\nfunc (m *MockBlock) Hash() ethgo.Hash {\n\treturn encodeHash(m.extra + m.hash)\n}\n\nfunc (m *MockBlock) Block() *ethgo.Block {\n\tb := &ethgo.Block{\n\t\tHash:   m.Hash(),\n\t\tNumber: uint64(m.num),\n\t}\n\tif m.num != 0 {\n\t\tb.ParentHash = encodeHash(m.parent)\n\t}\n\treturn b\n}\n\nfunc Mock(number int) *MockBlock {\n\treturn &MockBlock{hash: strconv.Itoa(number), num: number, parent: strconv.Itoa(number - 1)}\n}\n\ntype MockList []*MockBlock\n\nfunc (m *MockList) Create(from, to int, callback func(b *MockBlock)) {\n\tfor i := from; i < to; i++ {\n\t\tb := Mock(i)\n\t\tcallback(b)\n\t\t*m = append(*m, b)\n\t}\n}\n\nfunc (m *MockList) GetLogs() (res []*ethgo.Log) {\n\tfor _, log := range *m {\n\t\tres = append(res, log.GetLogs()...)\n\t}\n\treturn\n}\n\nfunc (m *MockList) ToBlocks() []*ethgo.Block {\n\te := []*ethgo.Block{}\n\tfor _, i := range *m {\n\t\te = append(e, i.Block())\n\t}\n\treturn e\n}\n"
  },
  {
    "path": "testutil/server.go",
    "content": "package testutil\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/ory/dockertest\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/compiler\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\nvar (\n\tDefaultGasPrice = uint64(1879048192) // 0x70000000\n\tDefaultGasLimit = uint64(5242880)    // 0x500000\n)\n\nvar (\n\tDummyAddr = ethgo.HexToAddress(\"0x015f68893a39b3ba0681584387670ff8b00f4db2\")\n)\n\nfunc getOpenPort() string {\n\trand.Seed(time.Now().UnixNano())\n\tmin, max := 12000, 15000\n\tfor {\n\t\tport := strconv.Itoa(rand.Intn(max-min) + min)\n\t\tserver, err := net.Listen(\"tcp\", \":\"+port)\n\t\tif err == nil {\n\t\t\tserver.Close()\n\t\t\treturn port\n\t\t}\n\t}\n}\n\n// MultiAddr creates new servers to test different addresses\nfunc MultiAddr(t *testing.T, c func(s *TestServer, addr string)) {\n\ts := NewTestServer(t)\n\n\t// http addr\n\tc(s, s.HTTPAddr())\n\n\t// ws addr\n\t// c(s, s.WSAddr())\n\n\t// ip addr\n\t// c(s, s.IPCPath())\n\n\t// s.Close()\n}\n\n// TestServerConfig is the configuration of the server\ntype TestServerConfig struct {\n\tPeriod int\n}\n\n// ServerConfigCallback is the callback to modify the config\ntype ServerConfigCallback func(c *TestServerConfig)\n\n// TestServer is a Geth test server\ntype TestServer struct {\n\taddr     string\n\taccounts []ethgo.Address\n\tclient   *ethClient\n}\n\n// DeployTestServer creates a new Geth test server\nfunc DeployTestServer(t *testing.T, cb ServerConfigCallback) *TestServer {\n\ttmpDir, err := ioutil.TempDir(\"/tmp\", \"geth-\")\n\tif err != nil {\n\t\tt.Fatalf(\"err: %s\", err)\n\t}\n\n\tconfig := &TestServerConfig{}\n\tif cb != nil {\n\t\tcb(config)\n\t}\n\n\targs := []string{\"--dev\"}\n\n\t// periodic mining\n\tif config.Period != 0 {\n\t\targs = append(args, \"--dev.period\", strconv.Itoa(config.Period))\n\t}\n\n\t// add data dir\n\targs = append(args, \"--datadir\", \"/eth1data\")\n\n\t// add ipcpath\n\targs = append(args, \"--ipcpath\", \"/eth1data/geth.ipc\")\n\n\t// enable rpc\n\targs = append(args, \"--http\", \"--http.addr\", \"0.0.0.0\", \"--http.api\", \"eth,net,web3,debug\")\n\n\t// enable ws\n\targs = append(args, \"--ws\", \"--ws.addr\", \"0.0.0.0\")\n\n\t// enable debug verbosity\n\targs = append(args, \"--verbosity\", \"4\")\n\n\topts := &dockertest.RunOptions{\n\t\tRepository: \"ethereum/client-go\",\n\t\tTag:        \"v1.10.15\",\n\t\tCmd:        args,\n\t\tMounts: []string{\n\t\t\ttmpDir + \":/eth1data\",\n\t\t},\n\t}\n\n\tpool, err := dockertest.NewPool(\"\")\n\tif err != nil {\n\t\tt.Fatalf(\"Could not connect to docker: %s\", err)\n\t}\n\tresource, err := pool.RunWithOptions(opts)\n\tif err != nil {\n\t\tt.Fatalf(\"Could not start go-ethereum: %s\", err)\n\t}\n\n\tcloseFn := func() {\n\t\tif err := pool.Purge(resource); err != nil {\n\t\t\tt.Fatalf(\"Could not purge geth: %s\", err)\n\t\t}\n\t}\n\n\tipAddr := resource.Container.NetworkSettings.IPAddress\n\taddr := fmt.Sprintf(\"http://%s:8545\", ipAddr)\n\n\tif err := pool.Retry(func() error {\n\t\treturn testHTTPEndpoint(addr)\n\t}); err != nil {\n\t\tcloseFn()\n\t}\n\n\tt.Cleanup(func() {\n\t\tcloseFn()\n\t})\n\n\treturn NewTestServer(t, addr)\n}\n\nfunc NewTestServer(t *testing.T, addrs ...string) *TestServer {\n\tvar addr string\n\tif len(addrs) != 0 {\n\t\taddr = addrs[0]\n\t} else {\n\t\t// default address\n\t\taddr = \"http://127.0.0.1:8545\"\n\t}\n\n\tserver := &TestServer{\n\t\taddr: addr,\n\t}\n\n\tserver.client = &ethClient{addr}\n\tif err := server.client.call(\"eth_accounts\", &server.accounts); err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn server\n}\n\n// Account returns a specific account\nfunc (t *TestServer) Account(i int) ethgo.Address {\n\treturn t.accounts[i]\n}\n\n// IPCPath returns the ipc endpoint\nfunc (t *TestServer) IPCPath() string {\n\treturn \"\"\n\t// return t.tmpDir + \"/geth.ipc\"\n}\n\n// WSAddr returns the websocket endpoint\nfunc (t *TestServer) WSAddr() string {\n\treturn fmt.Sprintf(\"ws://localhost:8546\")\n}\n\n// HTTPAddr returns the http endpoint\nfunc (t *TestServer) HTTPAddr() string {\n\treturn fmt.Sprintf(t.addr)\n}\n\n// ProcessBlock processes a new block\nfunc (t *TestServer) ProcessBlockWithReceipt() (*ethgo.Receipt, error) {\n\treceipt, err := t.SendTxn(&ethgo.Transaction{\n\t\tFrom:  t.accounts[0],\n\t\tTo:    &DummyAddr,\n\t\tValue: big.NewInt(10),\n\t})\n\treturn receipt, err\n}\n\nfunc (t *TestServer) ProcessBlock() error {\n\t_, err := t.ProcessBlockWithReceipt()\n\treturn err\n}\n\nvar emptyAddr ethgo.Address\n\nfunc isEmptyAddr(w ethgo.Address) bool {\n\treturn bytes.Equal(w[:], emptyAddr[:])\n}\n\n// Call sends a contract call\nfunc (t *TestServer) Call(msg *ethgo.CallMsg) (string, error) {\n\tif isEmptyAddr(msg.From) {\n\t\tmsg.From = t.Account(0)\n\t}\n\tvar resp string\n\tif err := t.client.call(\"eth_call\", &resp, msg, \"latest\"); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn resp, nil\n}\n\nfunc (t *TestServer) Fund(address ethgo.Address) (*ethgo.Receipt, error) {\n\treturn t.Transfer(address, big.NewInt(1000000000000000000))\n}\n\nfunc (t *TestServer) Transfer(address ethgo.Address, value *big.Int) (*ethgo.Receipt, error) {\n\treturn t.SendTxn(&ethgo.Transaction{\n\t\tFrom:  t.accounts[0],\n\t\tTo:    &address,\n\t\tValue: value,\n\t})\n}\n\n// TxnTo sends a transaction to a given method without any arguments\nfunc (t *TestServer) TxnTo(address ethgo.Address, method string) (*ethgo.Receipt, error) {\n\treturn t.SendTxn(&ethgo.Transaction{\n\t\tTo:    &address,\n\t\tInput: MethodSig(method),\n\t})\n}\n\n// SendTxn sends a transaction\nfunc (t *TestServer) SendTxn(txn *ethgo.Transaction) (*ethgo.Receipt, error) {\n\tif isEmptyAddr(txn.From) {\n\t\ttxn.From = t.Account(0)\n\t}\n\n\tif txn.Type == ethgo.TransactionDynamicFee {\n\t\tif txn.MaxPriorityFeePerGas == nil || txn.MaxPriorityFeePerGas.Cmp(big.NewInt(0)) == 0 {\n\t\t\ttxn.MaxPriorityFeePerGas = new(big.Int).SetUint64(DefaultGasPrice)\n\t\t}\n\t} else {\n\t\tif txn.GasPrice == 0 {\n\t\t\ttxn.GasPrice = DefaultGasPrice\n\t\t}\n\t}\n\tif txn.Gas == 0 {\n\t\ttxn.Gas = DefaultGasLimit\n\t}\n\n\tvar hash ethgo.Hash\n\tif err := t.client.call(\"eth_sendTransaction\", &hash, txn); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn t.WaitForReceipt(hash)\n}\n\n// WaitForReceipt waits for the receipt\nfunc (t *TestServer) WaitForReceipt(hash ethgo.Hash) (*ethgo.Receipt, error) {\n\tvar receipt *ethgo.Receipt\n\tvar count uint64\n\tfor {\n\t\terr := t.client.call(\"eth_getTransactionReceipt\", &receipt, hash)\n\t\tif err != nil {\n\t\t\tif err.Error() != \"not found\" {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\tif receipt != nil {\n\t\t\tbreak\n\t\t}\n\t\tif count > 300 {\n\t\t\treturn nil, fmt.Errorf(\"timeout waiting for receipt\")\n\t\t}\n\t\ttime.Sleep(500 * time.Millisecond)\n\t\tcount++\n\t}\n\treturn receipt, nil\n}\n\n// DeployContract deploys a contract with account 0 and returns the address\nfunc (t *TestServer) DeployContract(c *Contract) (*compiler.Artifact, ethgo.Address, error) {\n\t// solcContract := compile(c.Print())\n\tsolcContract, err := c.Compile()\n\tif err != nil {\n\t\treturn nil, ethgo.Address{}, err\n\t}\n\tbuf, err := hex.DecodeString(solcContract.Bin)\n\tif err != nil {\n\t\treturn nil, ethgo.Address{}, err\n\t}\n\n\treceipt, err := t.SendTxn(&ethgo.Transaction{\n\t\tInput: buf,\n\t})\n\tif err != nil {\n\t\treturn nil, ethgo.Address{}, err\n\t}\n\treturn solcContract, receipt.ContractAddress, nil\n}\n\n// Simple jsonrpc client to avoid cycle dependencies\n\ntype jsonRPCRequest struct {\n\tID     int             `json:\"id\"`\n\tMethod string          `json:\"method\"`\n\tParams json.RawMessage `json:\"params\"`\n}\n\ntype jsonRPCResponse struct {\n\tID     int                 `json:\"id\"`\n\tResult json.RawMessage     `json:\"result\"`\n\tError  *jsonRPCErrorObject `json:\"error,omitempty\"`\n}\n\ntype jsonRPCErrorObject struct {\n\tCode    int         `json:\"code\"`\n\tMessage string      `json:\"message\"`\n\tData    interface{} `json:\"data,omitempty\"`\n}\n\ntype ethClient struct {\n\turl string\n}\n\nvar errNotFound = fmt.Errorf(\"not found\")\n\nfunc (e *ethClient) call(method string, out interface{}, params ...interface{}) error {\n\tif e.url == \"\" {\n\t\te.url = \"http://127.0.0.1:8545\"\n\t}\n\n\tvar err error\n\tjsonReq := &jsonRPCRequest{\n\t\tMethod: method,\n\t}\n\tif len(params) > 0 {\n\t\tjsonReq.Params, err = json.Marshal(params)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\traw, err := json.Marshal(jsonReq)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tresp, err := http.Post(e.url, \"application/json\", bytes.NewBuffer(raw))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tvar jsonResp jsonRPCResponse\n\td := json.NewDecoder(resp.Body)\n\tif err := d.Decode(&jsonResp); err != nil {\n\t\treturn err\n\t}\n\n\tif jsonResp.Error != nil {\n\t\treturn fmt.Errorf(jsonResp.Error.Message)\n\t}\n\tif bytes.Equal(jsonResp.Result, []byte(\"null\")) {\n\t\treturn errNotFound\n\t}\n\tif err := json.Unmarshal(jsonResp.Result, out); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// MethodSig returns the signature of a non-parametrized function\nfunc MethodSig(name string) []byte {\n\th := sha3.NewLegacyKeccak256()\n\th.Write([]byte(name + \"()\"))\n\tb := h.Sum(nil)\n\treturn b[:4]\n}\n\n// TestInfuraEndpoint returns the testing infura endpoint to make testing requests\nfunc TestInfuraEndpoint(t *testing.T) string {\n\turl := os.Getenv(\"INFURA_URL\")\n\tif url == \"\" {\n\t\tt.Skip(\"Infura url not set\")\n\t}\n\treturn url\n}\n\nfunc testHTTPEndpoint(endpoint string) error {\n\tresp, err := http.Post(endpoint, \"application/json\", nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\treturn nil\n}\n"
  },
  {
    "path": "testutil/server_test.go",
    "content": "package testutil\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc TestDeployServer(t *testing.T) {\n\tsrv := DeployTestServer(t, nil)\n\trequire.NotEmpty(t, srv.accounts)\n\n\tclt := &ethClient{srv.HTTPAddr()}\n\taccount := []ethgo.Address{}\n\n\terr := clt.call(\"eth_accounts\", &account)\n\trequire.NoError(t, err)\n}\n"
  },
  {
    "path": "testutil/util.go",
    "content": "package testutil\n\nimport (\n\t\"math/big\"\n\t\"reflect\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc CompareLogs(one, two []*ethgo.Log) bool {\n\tif len(one) != len(two) {\n\t\treturn false\n\t}\n\tif len(one) == 0 {\n\t\treturn true\n\t}\n\treturn reflect.DeepEqual(one, two)\n}\n\nfunc CompareBlocks(one, two []*ethgo.Block) bool {\n\tif len(one) != len(two) {\n\t\treturn false\n\t}\n\tif len(one) == 0 {\n\t\treturn true\n\t}\n\t// difficulty is hard to check, set the values to zero\n\tfor _, i := range one {\n\t\tif i.Transactions == nil {\n\t\t\ti.Transactions = []*ethgo.Transaction{}\n\t\t}\n\t\ti.Difficulty = big.NewInt(0)\n\t}\n\tfor _, i := range two {\n\t\tif i.Transactions == nil {\n\t\t\ti.Transactions = []*ethgo.Transaction{}\n\t\t}\n\t\ti.Difficulty = big.NewInt(0)\n\t}\n\treturn reflect.DeepEqual(one, two)\n}\n"
  },
  {
    "path": "tracker/README.md",
    "content": "\n# Tracker\n\n```\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/binary\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/tracker\"\n\n\tboltdbStore \"github.com/umbracle/ethgo/tracker/store/boltdb\"\n)\n\nvar depositEvent = abi.MustNewEvent(`DepositEvent(\n\tbytes pubkey,\n\tbytes whitdrawalcred,\n\tbytes amount,\n\tbytes signature,\n\tbytes index\n)`)\n\nfunc main() {\n\tvar endpoint string\n\tvar target string\n\n\tflag.StringVar(&endpoint, \"endpoint\", \"\", \"\")\n\tflag.StringVar(&target, \"target\", \"\", \"\")\n\n\tflag.Parse()\n\n\tprovider, err := jsonrpc.NewClient(endpoint)\n\tif err != nil {\n\t\tfmt.Printf(\"[ERR]: %v\", err)\n\t\tos.Exit(1)\n\t}\n\n\tstore, err := boltdbStore.New(\"deposit.db\")\n\tif err != nil {\n\t\tfmt.Printf(\"[ERR]: failted to start store %v\", err)\n\t\tos.Exit(1)\n\t}\n\n\ttt, err := tracker.NewTracker(provider.Eth(),\n\t\ttracker.WithBatchSize(20000),\n\t\ttracker.WithStore(store),\n\t\ttracker.WithEtherscan(os.Getenv(\"ETHERSCAN_APIKEY\")),\n\t\ttracker.WithFilter(&tracker.FilterConfig{\n\t\t\tAsync: true,\n\t\t\tAddress: []ethgo.Address{\n\t\t\t\tethgo.HexToAddress(target),\n\t\t\t},\n\t\t}),\n\t)\n\tif err != nil {\n\t\tfmt.Printf(\"[ERR]: failed to create the tracker %v\", err)\n\t\tos.Exit(1)\n\t}\n\n\tlastBlock, err := tt.GetLastBlock()\n\tif err != nil {\n\t\tfmt.Printf(\"[ERR]: failed to get last block %v\", err)\n\t\tos.Exit(1)\n\t}\n\tif lastBlock != nil {\n\t\tfmt.Printf(\"Last block processed: %d\\n\", lastBlock.Number)\n\t}\n\n\tctx, cancelFn := context.WithCancel(context.Background())\n\tgo func() {\n\t\tgo func() {\n\t\t\tif err := tt.Sync(ctx); err != nil {\n\t\t\t\tfmt.Printf(\"[ERR]: %v\", err)\n\t\t\t}\n\t\t}()\n\n\t\tgo func() {\n\t\t\tfor {\n\t\t\t\tselect {\n\t\t\t\tcase evnt := <-tt.EventCh:\n\t\t\t\t\tfor _, log := range evnt.Added {\n\t\t\t\t\t\tif depositEvent.Match(log) {\n\t\t\t\t\t\t\tvals, err := depositEvent.ParseLog(log)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tpanic(err)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tindex := binary.LittleEndian.Uint64(vals[\"index\"].([]byte))\n\t\t\t\t\t\t\tamount := binary.LittleEndian.Uint64(vals[\"amount\"].([]byte))\n\n\t\t\t\t\t\t\tfmt.Printf(\"Deposit: Block %d Index %d Amount %d\\n\", log.BlockNumber, index, amount)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tcase <-tt.DoneCh:\n\t\t\t\t\tfmt.Println(\"historical sync done\")\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\n\t}()\n\n\thandleSignals(cancelFn)\n}\n\nfunc handleSignals(cancelFn context.CancelFunc) int {\n\tsignalCh := make(chan os.Signal, 4)\n\tsignal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)\n\n\t<-signalCh\n\n\tgracefulCh := make(chan struct{})\n\tgo func() {\n\t\tcancelFn()\n\t\tclose(gracefulCh)\n\t}()\n\n\tselect {\n\tcase <-signalCh:\n\t\treturn 1\n\tcase <-gracefulCh:\n\t\treturn 0\n\t}\n}\n```\n\nYou can query the ETH2.0 Deposit contract like so:\n\n```\ngo run main.go --endpoint https://mainnet.infura.io/v3/... --target 0x00000000219ab540356cbb839cbe05303d7705fa\n```\n"
  },
  {
    "path": "tracker/store/boltdb/bolt_store.go",
    "content": "package trackerboltdb\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/tracker/store\"\n\tbolt \"go.etcd.io/bbolt\"\n)\n\nvar _ store.Store = (*BoltStore)(nil)\n\nvar (\n\tdbLogs = []byte(\"logs\")\n\tdbConf = []byte(\"conf\")\n)\n\n// BoltStore is a tracker store implementation.\ntype BoltStore struct {\n\tconn *bolt.DB\n}\n\n// New creates a new boltdbstore\nfunc New(path string) (*BoltStore, error) {\n\tdb, err := bolt.Open(path, 0600, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstore := &BoltStore{\n\t\tconn: db,\n\t}\n\tif err := store.setupDB(); err != nil {\n\t\tstore.Close()\n\t\treturn nil, err\n\t}\n\treturn store, nil\n}\n\nfunc (b *BoltStore) setupDB() error {\n\ttxn, err := b.conn.Begin(true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer txn.Rollback()\n\n\tif _, err := txn.CreateBucketIfNotExists(dbConf); err != nil {\n\t\treturn err\n\t}\n\treturn txn.Commit()\n}\n\n// Close implements the store interface\nfunc (b *BoltStore) Close() error {\n\treturn b.conn.Close()\n}\n\n// Get implements the store interface\nfunc (b *BoltStore) Get(k string) (string, error) {\n\ttxn, err := b.conn.Begin(false)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer txn.Rollback()\n\n\tbucket := txn.Bucket(dbConf)\n\tval := bucket.Get([]byte(k))\n\n\treturn string(val), nil\n}\n\n// ListPrefix implements the store interface\nfunc (b *BoltStore) ListPrefix(prefix string) ([]string, error) {\n\ttxn, err := b.conn.Begin(false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer txn.Rollback()\n\n\tres := []string{}\n\tc := txn.Bucket(dbConf).Cursor()\n\tfor k, v := c.Seek([]byte(prefix)); k != nil && bytes.HasPrefix(k, []byte(prefix)); k, v = c.Next() {\n\t\tres = append(res, string(v))\n\t}\n\treturn res, nil\n}\n\n// Set implements the store interface\nfunc (b *BoltStore) Set(k, v string) error {\n\ttxn, err := b.conn.Begin(true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer txn.Rollback()\n\n\tbucket := txn.Bucket(dbConf)\n\tif err := bucket.Put([]byte(k), []byte(v)); err != nil {\n\t\treturn err\n\t}\n\treturn txn.Commit()\n}\n\n// GetEntry implements the store interface\nfunc (b *BoltStore) GetEntry(hash string) (store.Entry, error) {\n\ttxn, err := b.conn.Begin(true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer txn.Rollback()\n\n\tbucketName := append(dbLogs, []byte(hash)...)\n\tif _, err := txn.CreateBucketIfNotExists(bucketName); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := txn.Commit(); err != nil {\n\t\treturn nil, err\n\t}\n\te := &Entry{\n\t\tconn:   b.conn,\n\t\tbucket: bucketName,\n\t}\n\treturn e, nil\n}\n\n// Entry is an store.Entry implementation\ntype Entry struct {\n\tconn   *bolt.DB\n\tbucket []byte\n}\n\n// LastIndex implements the store interface\nfunc (e *Entry) LastIndex() (uint64, error) {\n\ttx, err := e.conn.Begin(false)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer tx.Rollback()\n\n\tcurs := tx.Bucket(e.bucket).Cursor()\n\tif last, _ := curs.Last(); last != nil {\n\t\treturn bytesToUint64(last) + 1, nil\n\t}\n\treturn 0, nil\n}\n\n// StoreLog implements the store interface\nfunc (e *Entry) StoreLog(log *ethgo.Log) error {\n\treturn e.StoreLogs([]*ethgo.Log{log})\n}\n\n// StoreLogs implements the store interface\nfunc (e *Entry) StoreLogs(logs []*ethgo.Log) error {\n\ttx, err := e.conn.Begin(true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer tx.Rollback()\n\n\tindx, err := e.LastIndex()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tbucket := tx.Bucket(e.bucket)\n\tfor logIndx, log := range logs {\n\t\tkey := uint64ToBytes(indx + uint64(logIndx))\n\n\t\tval, err := log.MarshalJSON()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := bucket.Put(key, val); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn tx.Commit()\n}\n\n// RemoveLogs implements the store interface\nfunc (e *Entry) RemoveLogs(indx uint64) error {\n\tindxKey := uint64ToBytes(indx)\n\n\ttx, err := e.conn.Begin(true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer tx.Rollback()\n\n\tcurs := tx.Bucket(e.bucket).Cursor()\n\tfor k, _ := curs.Seek(indxKey); k != nil; k, _ = curs.Next() {\n\t\tif err := curs.Delete(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn tx.Commit()\n}\n\n// GetLog implements the store interface\nfunc (e *Entry) GetLog(indx uint64, log *ethgo.Log) error {\n\ttxn, err := e.conn.Begin(false)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer txn.Rollback()\n\n\tbucket := txn.Bucket(e.bucket)\n\tval := bucket.Get(uint64ToBytes(indx))\n\n\tif err := log.UnmarshalJSON(val); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc bytesToUint64(b []byte) uint64 {\n\treturn binary.BigEndian.Uint64(b)\n}\n\nfunc uint64ToBytes(u uint64) []byte {\n\tbuf := make([]byte, 8)\n\tbinary.BigEndian.PutUint64(buf, u)\n\treturn buf\n}\n"
  },
  {
    "path": "tracker/store/boltdb/bolt_store_test.go",
    "content": "package trackerboltdb\n\nimport (\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/umbracle/ethgo/tracker/store\"\n)\n\nfunc setupDB(t *testing.T) (store.Store, func()) {\n\tdir, err := ioutil.TempDir(\"/tmp\", \"boltdb-test\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tpath := filepath.Join(dir, \"test.db\")\n\tstore, err := New(path)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tclose := func() {\n\t\tif err := os.RemoveAll(dir); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\treturn store, close\n}\n\nfunc TestBoltDBStore(t *testing.T) {\n\tstore.TestStore(t, setupDB)\n}\n"
  },
  {
    "path": "tracker/store/inmem/inmem_store.go",
    "content": "package inmem\n\nimport (\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/tracker/store\"\n)\n\nvar _ store.Store = (*InmemStore)(nil)\n\n// InmemStore implements the Store interface.\ntype InmemStore struct {\n\tl       sync.RWMutex\n\tentries map[string]*Entry\n\tkv      map[string]string\n}\n\n// NewInmemStore returns a new in-memory store.\nfunc NewInmemStore() *InmemStore {\n\treturn &InmemStore{\n\t\tentries: map[string]*Entry{},\n\t\tkv:      map[string]string{},\n\t}\n}\n\n// Close implements the store interface\nfunc (i *InmemStore) Close() error {\n\treturn nil\n}\n\n// Get implements the store interface\nfunc (i *InmemStore) Get(k string) (string, error) {\n\ti.l.Lock()\n\tdefer i.l.Unlock()\n\treturn i.kv[string(k)], nil\n}\n\n// ListPrefix implements the store interface\nfunc (i *InmemStore) ListPrefix(prefix string) ([]string, error) {\n\ti.l.Lock()\n\tdefer i.l.Unlock()\n\n\tres := []string{}\n\tfor k, v := range i.kv {\n\t\tif strings.HasPrefix(k, prefix) {\n\t\t\tres = append(res, v)\n\t\t}\n\t}\n\treturn res, nil\n}\n\n// Set implements the store interface\nfunc (i *InmemStore) Set(k, v string) error {\n\ti.l.Lock()\n\tdefer i.l.Unlock()\n\ti.kv[string(k)] = v\n\treturn nil\n}\n\n// GetEntry implements the store interface\nfunc (i *InmemStore) GetEntry(hash string) (store.Entry, error) {\n\ti.l.Lock()\n\tdefer i.l.Unlock()\n\te, ok := i.entries[hash]\n\tif ok {\n\t\treturn e, nil\n\t}\n\te = &Entry{\n\t\tlogs: []*ethgo.Log{},\n\t}\n\ti.entries[hash] = e\n\treturn e, nil\n}\n\n// Entry is a store.Entry implementation\ntype Entry struct {\n\tl    sync.RWMutex\n\tlogs []*ethgo.Log\n}\n\n// LastIndex implements the store interface\nfunc (e *Entry) LastIndex() (uint64, error) {\n\te.l.Lock()\n\tdefer e.l.Unlock()\n\treturn uint64(len(e.logs)), nil\n}\n\n// Logs returns the logs of the inmemory store\nfunc (e *Entry) Logs() []*ethgo.Log {\n\treturn e.logs\n}\n\n// StoreLogs implements the store interface\nfunc (e *Entry) StoreLogs(logs []*ethgo.Log) error {\n\te.l.Lock()\n\tdefer e.l.Unlock()\n\tfor _, log := range logs {\n\t\te.logs = append(e.logs, log)\n\t}\n\treturn nil\n}\n\n// RemoveLogs implements the store interface\nfunc (e *Entry) RemoveLogs(indx uint64) error {\n\te.l.Lock()\n\tdefer e.l.Unlock()\n\te.logs = e.logs[:indx]\n\treturn nil\n}\n\n// GetLog implements the store interface\nfunc (e *Entry) GetLog(indx uint64, log *ethgo.Log) error {\n\t*log = *e.logs[indx]\n\treturn nil\n}\n"
  },
  {
    "path": "tracker/store/inmem/inmem_store_test.go",
    "content": "package inmem\n\nimport (\n\t\"testing\"\n\n\t\"github.com/umbracle/ethgo/tracker/store\"\n)\n\nfunc TestInMemoryStore(t *testing.T) {\n\tstore.TestStore(t, func(t *testing.T) (store.Store, func()) {\n\t\treturn NewInmemStore(), func() {}\n\t})\n}\n"
  },
  {
    "path": "tracker/store/postgresql/postgresql_store.go",
    "content": "package trackerpostgresql\n\nimport (\n\t\"database/sql\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/jmoiron/sqlx\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/tracker/store\"\n\n\t// Enable postgres for sqlx\n\t_ \"github.com/lib/pq\"\n)\n\nvar _ store.Store = (*PostgreSQLStore)(nil)\n\n// PostgreSQLStore is a tracker store implementation that uses PostgreSQL as a backend.\ntype PostgreSQLStore struct {\n\tdb *sqlx.DB\n}\n\n// NewPostgreSQLStore creates a new PostgreSQL store\nfunc NewPostgreSQLStore(endpoint string) (*PostgreSQLStore, error) {\n\tdb, err := sql.Open(\"postgres\", endpoint)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewSQLStore(db, \"postgres\")\n}\n\n// NewSQLStore creates a new store with an sql driver\nfunc NewSQLStore(db *sql.DB, driver string) (*PostgreSQLStore, error) {\n\tsqlxDB := sqlx.NewDb(db, driver)\n\n\t// create the kv database if it does not exists\n\tif _, err := db.Exec(kvSQLSchema); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &PostgreSQLStore{db: sqlxDB}, nil\n}\n\n// Close implements the store interface\nfunc (p *PostgreSQLStore) Close() error {\n\treturn p.db.Close()\n}\n\n// Get implements the store interface\nfunc (p *PostgreSQLStore) Get(k string) (string, error) {\n\tvar out string\n\tif err := p.db.Get(&out, \"SELECT val FROM kv WHERE key=$1\", string(k)); err != nil {\n\t\tif err == sql.ErrNoRows {\n\t\t\treturn \"\", nil\n\t\t}\n\t\treturn \"\", err\n\t}\n\treturn out, nil\n}\n\n// ListPrefix implements the store interface\nfunc (p *PostgreSQLStore) ListPrefix(prefix string) ([]string, error) {\n\tvar out []string\n\tif err := p.db.Select(&out, \"SELECT val FROM kv WHERE key LIKE $1\", string(prefix)+\"%\"); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// Set implements the store interface\nfunc (p *PostgreSQLStore) Set(k, v string) error {\n\tif _, err := p.db.Exec(\"INSERT INTO kv (key, val) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET val = $2\", k, v); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// GetEntry implements the store interface\nfunc (p *PostgreSQLStore) GetEntry(hash string) (store.Entry, error) {\n\ttableName := \"logs_\" + hash\n\tif _, err := p.db.Exec(logSQLSchema(tableName)); err != nil {\n\t\treturn nil, err\n\t}\n\te := &Entry{\n\t\ttable: tableName,\n\t\tdb:    p.db,\n\t}\n\treturn e, nil\n}\n\n// Entry is an store.Entry implementation\ntype Entry struct {\n\ttable string\n\tdb    *sqlx.DB\n}\n\n// LastIndex implements the store interface\nfunc (e *Entry) LastIndex() (uint64, error) {\n\tvar index uint64\n\tif err := e.db.Get(&index, \"SELECT indx FROM \"+e.table+\" ORDER BY indx DESC LIMIT 1\"); err != nil {\n\t\tif err == sql.ErrNoRows {\n\t\t\treturn 0, nil\n\t\t}\n\t\treturn 0, err\n\t}\n\treturn index + 1, nil\n}\n\n// StoreLogs implements the store interface\nfunc (e *Entry) StoreLogs(logs []*ethgo.Log) error {\n\tlastIndex, err := e.LastIndex()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttx, err := e.db.Beginx()\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer tx.Rollback()\n\n\tquery := \"INSERT INTO \" + e.table + \" (indx, tx_index, tx_hash, block_num, block_hash, address, data, topics) VALUES (:indx, :tx_index, :tx_hash, :block_num, :block_hash, :address, :data, :topics)\"\n\n\tfor indx, log := range logs {\n\t\ttopics := []string{}\n\t\tfor _, topic := range log.Topics {\n\t\t\ttopics = append(topics, topic.String())\n\t\t}\n\t\tobj := &logObj{\n\t\t\tIndex:     lastIndex + uint64(indx),\n\t\t\tTxIndex:   log.TransactionIndex,\n\t\t\tTxHash:    log.TransactionHash.String(),\n\t\t\tBlockNum:  log.BlockNumber,\n\t\t\tBlockHash: log.BlockHash.String(),\n\t\t\tAddress:   log.Address.String(),\n\t\t\tTopics:    strings.Join(topics, \",\"),\n\t\t}\n\t\tif log.Data != nil {\n\t\t\tobj.Data = \"0x\" + hex.EncodeToString(log.Data)\n\t\t}\n\n\t\tif _, err := tx.NamedExec(query, obj); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err := tx.Commit(); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// RemoveLogs implements the store interface\nfunc (e *Entry) RemoveLogs(indx uint64) error {\n\tif _, err := e.db.Exec(\"DELETE FROM \"+e.table+\" WHERE indx >= $1\", indx); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// GetLog implements the store interface\nfunc (e *Entry) GetLog(indx uint64, log *ethgo.Log) error {\n\tobj := logObj{}\n\tif err := e.db.Get(&obj, \"SELECT * FROM \"+e.table+\" WHERE indx=$1\", indx); err != nil {\n\t\treturn err\n\t}\n\n\tlog.TransactionIndex = obj.TxIndex\n\tif err := log.TransactionHash.UnmarshalText([]byte(obj.TxHash)); err != nil {\n\t\treturn err\n\t}\n\tlog.BlockNumber = obj.BlockNum\n\tif err := log.BlockHash.UnmarshalText([]byte(obj.BlockHash)); err != nil {\n\t\treturn err\n\t}\n\tif err := log.Address.UnmarshalText([]byte(obj.Address)); err != nil {\n\t\treturn err\n\t}\n\n\tif obj.Topics != \"\" {\n\t\tlog.Topics = []ethgo.Hash{}\n\t\tfor _, item := range strings.Split(obj.Topics, \",\") {\n\t\t\tvar topic ethgo.Hash\n\t\t\tif err := topic.UnmarshalText([]byte(item)); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tlog.Topics = append(log.Topics, topic)\n\t\t}\n\t} else {\n\t\tlog.Topics = nil\n\t}\n\n\tif obj.Data != \"\" {\n\t\tif !strings.HasPrefix(obj.Data, \"0x\") {\n\t\t\treturn fmt.Errorf(\"0x prefix not found in data\")\n\t\t}\n\t\tbuf, err := hex.DecodeString(obj.Data[2:])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlog.Data = buf\n\t} else {\n\t\tlog.Data = nil\n\t}\n\n\treturn nil\n}\n\ntype logObj struct {\n\tIndex     uint64 `db:\"indx\"`\n\tTxIndex   uint64 `db:\"tx_index\"`\n\tTxHash    string `db:\"tx_hash\"`\n\tBlockNum  uint64 `db:\"block_num\"`\n\tBlockHash string `db:\"block_hash\"`\n\tAddress   string `db:\"address\"`\n\tTopics    string `db:\"topics\"`\n\tData      string `db:\"data\"`\n}\n\nvar kvSQLSchema = `\nCREATE TABLE IF NOT EXISTS kv (\n\tkey text unique,\n\tval text\n);\n`\n\nfunc logSQLSchema(name string) string {\n\treturn `\n\tCREATE TABLE IF NOT EXISTS ` + name + ` (\n\t\tindx \t\tnumeric,\n\t\ttx_index \tnumeric,\n\t\ttx_hash \ttext,\n\t\tblock_num \tnumeric,\n\t\tblock_hash \ttext,\n\t\taddress \ttext,\n\t\ttopics \t\ttext,\n\t\tdata \t\ttext\n\t);\n\t`\n}\n"
  },
  {
    "path": "tracker/store/postgresql/postgresql_store_test.go",
    "content": "package trackerpostgresql\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/ory/dockertest\"\n\t\"github.com/umbracle/ethgo/tracker/store\"\n)\n\nfunc setupDB(t *testing.T) (store.Store, func()) {\n\tpool, err := dockertest.NewPool(\"\")\n\tif err != nil {\n\t\tt.Fatalf(\"Could not connect to docker: %s\", err)\n\t}\n\n\tresource, err := pool.Run(\"postgres\", \"latest\", []string{\"POSTGRES_HOST_AUTH_METHOD=trust\"})\n\tif err != nil {\n\t\tt.Fatalf(\"Could not start resource: %s\", err)\n\t}\n\n\tendpoint := fmt.Sprintf(\"postgres://postgres@localhost:%s/postgres?sslmode=disable\", resource.GetPort(\"5432/tcp\"))\n\n\t// wait for the db to be running\n\tif err := pool.Retry(func() error {\n\t\tdb, err := sql.Open(\"postgres\", endpoint)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn db.Ping()\n\t}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcleanup := func() {\n\t\tif err := pool.Purge(resource); err != nil {\n\t\t\tt.Fatalf(\"Could not purge resource: %s\", err)\n\t\t}\n\t}\n\n\tstore, err := NewPostgreSQLStore(endpoint)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn store, cleanup\n}\n\nfunc TestPostgreSQLStore(t *testing.T) {\n\tstore.TestStore(t, setupDB)\n}\n"
  },
  {
    "path": "tracker/store/store.go",
    "content": "package store\n\nimport \"github.com/umbracle/ethgo\"\n\n// Store is a datastore for the tracker\ntype Store interface {\n\t// Get gets a value\n\tGet(k string) (string, error)\n\n\t// ListPrefix lists values by prefix\n\tListPrefix(prefix string) ([]string, error)\n\n\t// Set sets a value\n\tSet(k, v string) error\n\n\t// Close closes the store\n\tClose() error\n\n\t// GetEntry returns a specific entry\n\tGetEntry(hash string) (Entry, error)\n}\n\n// Entry is a filter entry in the store\ntype Entry interface {\n\t// LastIndex returns index of the last stored event\n\tLastIndex() (uint64, error)\n\n\t// StoreLogs stores the web3 logs of the event\n\tStoreLogs(logs []*ethgo.Log) error\n\n\t// RemoveLogs all the logs starting at index 'indx'\n\tRemoveLogs(indx uint64) error\n\n\t// GetLog returns the log at indx\n\tGetLog(indx uint64, log *ethgo.Log) error\n}\n"
  },
  {
    "path": "tracker/store/testing.go",
    "content": "package store\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// SetupDB is a function that creates a backend\ntype SetupDB func(t *testing.T) (Store, func())\n\n// TestStore tests a tracker store\nfunc TestStore(t *testing.T, setup SetupDB) {\n\ttestMultipleStores(t, setup)\n\ttestGetSet(t, setup)\n\ttestRemoveLogs(t, setup)\n\ttestStoreLogs(t, setup)\n\ttestPrefix(t, setup)\n}\n\nfunc testMultipleStores(t *testing.T, setup SetupDB) {\n\tstore, close := setup(t)\n\tdefer close()\n\n\tentry0, err := store.GetEntry(\"0\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tlog := ethgo.Log{\n\t\tBlockNumber: 10,\n\t}\n\tif err := entry0.StoreLogs([]*ethgo.Log{&log}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tentry1, err := store.GetEntry(\"1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tlog = ethgo.Log{\n\t\tBlockNumber: 15,\n\t}\n\tif err := entry1.StoreLogs([]*ethgo.Log{&log}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tindex0, err := entry0.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif index0 != 1 {\n\t\tt.Fatal(\"bad\")\n\t}\n\n\tindex1, err := entry1.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif index1 != 1 {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n\nfunc testPrefix(t *testing.T, setup SetupDB) {\n\tstore, close := setup(t)\n\tdefer close()\n\n\tv1 := \"val1\"\n\tv2 := \"val2\"\n\tv3 := \"val3\"\n\n\t// add same prefix values\n\tif err := store.Set(v1, v1); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := store.Set(v2, v2); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := store.Set(v3, v3); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// add distinct value\n\tif err := store.Set(\"a\", \"b\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcheckPrefix := func(prefix string, expected int) {\n\t\tres, err := store.ListPrefix(prefix)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif len(res) != expected {\n\t\t\tt.Fatalf(\"%d values expected for prefix '%s' but %d found\", expected, string(prefix), len(res))\n\t\t}\n\t}\n\n\tcheckPrefix(\"val\", 3)\n\tcheckPrefix(\"a\", 1)\n\tcheckPrefix(\"b\", 0)\n}\n\nfunc testGetSet(t *testing.T, setup SetupDB) {\n\tstore, close := setup(t)\n\tdefer close()\n\n\tk1 := \"k1\"\n\tv1 := \"v1\"\n\tv2 := \"v2\"\n\n\tres, err := store.Get(k1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(res) != 0 {\n\t\tt.Fatal(\"expected empty\")\n\t}\n\n\t// set the entry\n\tif err := store.Set(k1, v1); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err = store.Get(k1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res != v1 {\n\t\tt.Fatal(\"bad\")\n\t}\n\n\t// update the entry\n\tif err := store.Set(k1, v2); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err = store.Get(k1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res != v2 {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n\nfunc testStoreLogs(t *testing.T, setup SetupDB) {\n\tstore, close := setup(t)\n\tdefer close()\n\n\tentry, err := store.GetEntry(\"1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tindx, err := entry.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indx != 0 {\n\t\tt.Fatal(\"index should be zero\")\n\t}\n\n\tlog := ethgo.Log{\n\t\tBlockNumber: 10,\n\t}\n\tif err := entry.StoreLogs([]*ethgo.Log{&log}); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tindx, err = entry.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indx != 1 {\n\t\tt.Fatal(\"index should be one\")\n\t}\n\n\tvar log2 ethgo.Log\n\tif err := entry.GetLog(0, &log2); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !reflect.DeepEqual(log, log2) {\n\t\tt.Fatal(\"bad\")\n\t}\n\n\t// retrieve entry again\n\tentry1, err := store.GetEntry(\"1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tindx1, err := entry1.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indx1 != indx {\n\t\tt.Fatal(\"bad last index\")\n\t}\n}\n\nfunc testRemoveLogs(t *testing.T, setup SetupDB) {\n\tstore, close := setup(t)\n\tdefer close()\n\n\tlogs := []*ethgo.Log{}\n\tfor i := uint64(0); i < 10; i++ {\n\t\tlogs = append(logs, &ethgo.Log{\n\t\t\tBlockNumber: i,\n\t\t})\n\t}\n\n\tentry, err := store.GetEntry(\"1\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif err := entry.StoreLogs(logs); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif err := entry.RemoveLogs(5); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tindx, err := entry.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indx != 5 {\n\t\tt.Fatal(\"bad\")\n\t}\n\n\t// add again the values\n\tif err := entry.StoreLogs(logs[5:]); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tindx, err = entry.LastIndex()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indx != 10 {\n\t\tt.Fatal(\"bad\")\n\t}\n}\n"
  },
  {
    "path": "tracker/tracker.go",
    "content": "package tracker\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/blocktracker\"\n\t\"github.com/umbracle/ethgo/etherscan\"\n\t\"github.com/umbracle/ethgo/jsonrpc/codec\"\n\t\"github.com/umbracle/ethgo/tracker/store\"\n\t\"github.com/umbracle/ethgo/tracker/store/inmem\"\n)\n\nvar (\n\tdbGenesis   = \"genesis\"\n\tdbChainID   = \"chainID\"\n\tdbLastBlock = \"lastBlock\"\n\tdbFilter    = \"filter\"\n)\n\nconst (\n\tdefaultBatchSize = 100\n)\n\n// BlockTracking defines interface for block tracker implementations\ntype BlockTracking interface {\n\tBlocksBlocked() []*ethgo.Block\n\tAddBlockLocked(block *ethgo.Block) error\n\tMaxBlockBacklog() uint64\n\tInit() error\n\tStart() error\n\tClose() error\n\tSubscribe() chan *blocktracker.BlockEvent\n\tAcquireLock() blocktracker.Lock\n\tLastBlocked() *ethgo.Block\n\tHandleBlockEvent(block *ethgo.Block) (*blocktracker.BlockEvent, error)\n\tLen() int\n}\n\n// FilterConfig is a tracker filter configuration\ntype FilterConfig struct {\n\tAddress []ethgo.Address `json:\"address\"`\n\tTopics  [][]*ethgo.Hash `json:\"topics\"`\n\tStart   uint64\n\tHash    string\n\tAsync   bool\n}\n\nfunc (f *FilterConfig) buildHash() {\n\th := sha256.New()\n\tfor _, i := range f.Address {\n\t\th.Write([]byte(i.String()))\n\t}\n\tfor _, topics := range f.Topics {\n\t\tif topics == nil {\n\t\t\th.Write([]byte(\"empty\"))\n\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, innerTopic := range topics {\n\t\t\tif innerTopic == nil {\n\t\t\t\th.Write([]byte(\"empty\"))\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\th.Write([]byte(innerTopic.String()))\n\t\t}\n\t}\n\tf.Hash = hex.EncodeToString(h.Sum(nil))\n}\n\nfunc (f *FilterConfig) getFilterSearch() *ethgo.LogFilter {\n\tfilter := &ethgo.LogFilter{}\n\tif len(f.Address) != 0 {\n\t\tfilter.Address = f.Address\n\t}\n\tif len(f.Topics) != 0 {\n\t\tfilter.Topics = f.Topics\n\t}\n\treturn filter\n}\n\n// Config is the configuration of the tracker\ntype Config struct {\n\tBatchSize       uint64\n\tBlockTracker    BlockTracking\n\tEtherscanAPIKey string\n\tFilter          *FilterConfig\n\tStore           store.Store\n}\n\ntype ConfigOption func(*Config)\n\nfunc WithBatchSize(b uint64) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.BatchSize = b\n\t}\n}\n\nfunc WithBlockTracker(b BlockTracking) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.BlockTracker = b\n\t}\n}\n\nfunc WithStore(s store.Store) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.Store = s\n\t}\n}\n\nfunc WithFilter(f *FilterConfig) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.Filter = f\n\t}\n}\n\nfunc WithEtherscan(k string) ConfigOption {\n\treturn func(c *Config) {\n\t\tc.EtherscanAPIKey = k\n\t}\n}\n\n// DefaultConfig returns the default tracker config\nfunc DefaultConfig() *Config {\n\treturn &Config{\n\t\tBatchSize:       defaultBatchSize,\n\t\tStore:           inmem.NewInmemStore(),\n\t\tFilter:          &FilterConfig{},\n\t\tEtherscanAPIKey: \"\",\n\t}\n}\n\n// Provider are the eth1x methods required by the tracker\ntype Provider interface {\n\tBlockNumber() (uint64, error)\n\tGetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block, error)\n\tGetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error)\n\tGetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error)\n\tChainID() (*big.Int, error)\n}\n\n// Tracker is a contract event tracker\ntype Tracker struct {\n\tlogger       *log.Logger\n\tprovider     Provider\n\tconfig       *Config\n\tstore        store.Store\n\tentry        store.Entry\n\tpreSyncOnce  sync.Once\n\tblockTracker BlockTracking\n\tsynced       int32\n\tBlockCh      chan *blocktracker.BlockEvent\n\tReadyCh      chan struct{}\n\tSyncCh       chan uint64\n\tEventCh      chan *Event\n\tDoneCh       chan struct{}\n}\n\n// NewTracker creates a new tracker\nfunc NewTracker(provider Provider, opts ...ConfigOption) (*Tracker, error) {\n\tconfig := DefaultConfig()\n\tfor _, opt := range opts {\n\t\topt(config)\n\t}\n\n\tt := &Tracker{\n\t\tprovider:     provider,\n\t\tconfig:       config,\n\t\tBlockCh:      make(chan *blocktracker.BlockEvent, 1),\n\t\tlogger:       log.New(ioutil.Discard, \"\", log.LstdFlags),\n\t\tReadyCh:      make(chan struct{}),\n\t\tstore:        config.Store,\n\t\tblockTracker: config.BlockTracker,\n\t\tDoneCh:       make(chan struct{}, 1),\n\t\tEventCh:      make(chan *Event),\n\t\tSyncCh:       make(chan uint64, 1),\n\t\tsynced:       0,\n\t}\n\tif err := t.setupFilter(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn t, nil\n}\n\n// NewFilter creates a new log filter\nfunc (t *Tracker) setupFilter() error {\n\tif t.config.Filter == nil {\n\t\t// generic config\n\t\tt.config.Filter = &FilterConfig{}\n\t}\n\n\t// generate a random hash if not provided\n\tif t.config.Filter.Hash == \"\" {\n\t\tt.config.Filter.buildHash()\n\t}\n\n\tentry, err := t.store.GetEntry(t.config.Filter.Hash)\n\tif err != nil {\n\t\treturn err\n\t}\n\tt.entry = entry\n\n\t// insert the filter config in the db\n\tfilterKey := dbFilter + \"_\" + t.config.Filter.Hash\n\tdata, err := t.store.Get(filterKey)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif data == \"\" {\n\t\traw, err := json.Marshal(t.config.Filter)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trawStr := hex.EncodeToString(raw)\n\t\tif err := t.store.Set(filterKey, rawStr); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (t *Tracker) Entry() store.Entry {\n\treturn t.entry\n}\n\n// GetLastBlock returns the last block processed for this filter\nfunc (t *Tracker) GetLastBlock() (*ethgo.Block, error) {\n\tbuf, err := t.store.Get(dbLastBlock + \"_\" + t.config.Filter.Hash)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(buf) == 0 {\n\t\treturn nil, nil\n\t}\n\traw, err := hex.DecodeString(buf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tb := &ethgo.Block{}\n\tif err := b.UnmarshalJSON(raw); err != nil {\n\t\treturn nil, err\n\t}\n\treturn b, nil\n}\n\nfunc (t *Tracker) storeLastBlock(b *ethgo.Block) error {\n\tif b.Difficulty == nil {\n\t\tb.Difficulty = big.NewInt(0)\n\t}\n\tbuf, err := b.MarshalJSON()\n\tif err != nil {\n\t\treturn err\n\t}\n\traw := hex.EncodeToString(buf)\n\treturn t.store.Set(dbLastBlock+\"_\"+t.config.Filter.Hash, raw)\n}\n\nfunc (t *Tracker) emitEvent(evnt *Event) {\n\tif evnt == nil {\n\t\treturn\n\t}\n\tif t.config.Filter.Async {\n\t\tselect {\n\t\tcase t.EventCh <- evnt:\n\t\tdefault:\n\t\t}\n\t} else {\n\t\tt.EventCh <- evnt\n\t}\n}\n\n// IsSynced returns true if the filter is synced to head\nfunc (t *Tracker) IsSynced() bool {\n\treturn atomic.LoadInt32(&t.synced) != 0\n}\n\n// Wait waits the filter to finish\nfunc (t *Tracker) Wait() {\n\tt.WaitDuration(0)\n}\n\n// WaitDuration waits for the filter to finish up to duration\nfunc (t *Tracker) WaitDuration(dur time.Duration) error {\n\tif t.IsSynced() {\n\t\treturn nil\n\t}\n\n\tvar waitCh <-chan time.Time\n\tif dur == 0 {\n\t\twaitCh = time.After(dur)\n\t}\n\tselect {\n\tcase <-waitCh:\n\t\treturn fmt.Errorf(\"timeout\")\n\tcase <-t.DoneCh:\n\t}\n\treturn nil\n}\n\nfunc (t *Tracker) findAncestor(block, pivot *ethgo.Block) (uint64, error) {\n\t// block is part of a fork that is not the current head, find a common ancestor\n\t// both block and pivot are at the same height\n\tvar err error\n\n\tfor i := uint64(0); i < t.blockTracker.MaxBlockBacklog(); i++ {\n\t\tif block.Number != pivot.Number {\n\t\t\treturn 0, fmt.Errorf(\"block numbers do not match\")\n\t\t}\n\t\tif block.Hash == pivot.Hash {\n\t\t\t// this is the common ancestor in both\n\t\t\treturn block.Number, nil\n\t\t}\n\t\tblock, err = t.provider.GetBlockByHash(block.ParentHash, false)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t} else if block == nil {\n\t\t\t// if block does not exist (for example reorg happened) GetBlockByNumber will return nil, nil\n\t\t\treturn 0, fmt.Errorf(\"block with hash %s not found\", block.ParentHash)\n\t\t}\n\t\tpivot, err = t.provider.GetBlockByHash(pivot.ParentHash, false)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t} else if pivot == nil {\n\t\t\t// if block does not exist (for example reorg happened) GetBlockByNumber will return nil, nil\n\t\t\treturn 0, fmt.Errorf(\"block/pivot with hash %s not found\", pivot.ParentHash)\n\t\t}\n\t}\n\treturn 0, fmt.Errorf(\"the reorg is bigger than maxBlockBacklog %d\", t.blockTracker.MaxBlockBacklog())\n}\n\nfunc (t *Tracker) emitLogs(typ EventType, logs []*ethgo.Log) {\n\tevnt := &Event{}\n\tif typ == EventAdd {\n\t\tevnt.Added = logs\n\t}\n\tif typ == EventDel {\n\t\tevnt.Removed = logs\n\t}\n\tt.emitEvent(evnt)\n}\n\nfunc tooMuchDataRequestedError(err error) bool {\n\tobj, ok := err.(*codec.ErrorObject)\n\tif !ok {\n\t\treturn false\n\t}\n\tif obj.Message == \"query returned more than 10000 results\" {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (t *Tracker) syncBatch(ctx context.Context, from, to uint64) error {\n\tquery := t.config.Filter.getFilterSearch()\n\n\tbatchSize := t.config.BatchSize\n\tadditiveFactor := uint64(float64(batchSize) * 0.10)\n\n\ti := from\n\nSTART:\n\tdst := min(to, i+batchSize)\n\n\tquery.SetFromUint64(i)\n\tquery.SetToUint64(dst)\n\n\tlogs, err := t.provider.GetLogs(query)\n\tif err != nil {\n\t\tif tooMuchDataRequestedError(err) {\n\t\t\t// multiplicative decrease\n\t\t\tbatchSize = batchSize / 2\n\t\t\tgoto START\n\t\t}\n\t\treturn err\n\t}\n\n\tif t.SyncCh != nil {\n\t\tselect {\n\t\tcase t.SyncCh <- dst:\n\t\tdefault:\n\t\t}\n\t}\n\n\t// add logs to the store\n\tif err := t.entry.StoreLogs(logs); err != nil {\n\t\treturn err\n\t}\n\tt.emitLogs(EventAdd, logs)\n\n\t// update the last block entry\n\tblock, err := t.getBlockByNumber(dst)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := t.storeLastBlock(block); err != nil {\n\t\treturn err\n\t}\n\n\t// check if the execution is over after each query batch\n\tif err := ctx.Err(); err != nil {\n\t\treturn err\n\t}\n\n\ti += batchSize + 1\n\n\t// update the batchSize with additive increase\n\tif batchSize < t.config.BatchSize {\n\t\tbatchSize = min(t.config.BatchSize, batchSize+additiveFactor)\n\t}\n\n\tif i <= to {\n\t\tgoto START\n\t}\n\treturn nil\n}\n\nfunc (t *Tracker) preSyncCheck() error {\n\tvar err error\n\tt.preSyncOnce.Do(func() {\n\t\terr = t.preSyncCheckImpl()\n\t})\n\treturn err\n}\n\nfunc (t *Tracker) preSyncCheckImpl() error {\n\trGenesis, err := t.getBlockByNumber(0)\n\tif err != nil {\n\t\treturn err\n\t}\n\trChainID, err := t.provider.ChainID()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tgenesis, err := t.store.Get(dbGenesis)\n\tif err != nil {\n\t\treturn err\n\t}\n\tchainID, err := t.store.Get(dbChainID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(genesis) != 0 {\n\t\tif genesis != rGenesis.Hash.String() {\n\t\t\treturn fmt.Errorf(\"bad genesis\")\n\t\t}\n\t\tif chainID != rChainID.String() {\n\t\t\treturn fmt.Errorf(\"bad genesis\")\n\t\t}\n\t} else {\n\t\tif err := t.store.Set(dbGenesis, rGenesis.Hash.String()); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := t.store.Set(dbChainID, rChainID.String()); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (t *Tracker) fastTrack(filterConfig *FilterConfig) (*ethgo.Block, error) {\n\t// Try to use first the user provided block if any\n\tif filterConfig.Start != 0 {\n\t\tbb, err := t.getBlockByNumber(filterConfig.Start)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bb, nil\n\t}\n\n\t// Only possible if we filter addresses\n\tif len(filterConfig.Address) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tif t.config.EtherscanAPIKey != \"\" {\n\t\tchainID, err := t.provider.ChainID()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// get the etherscan instance for this chainID\n\t\te, err := etherscan.NewEtherscanFromNetwork(ethgo.Network(chainID.Uint64()), t.config.EtherscanAPIKey)\n\t\tif err != nil {\n\t\t\t// there is no etherscan api for this specific chainid\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tgetAddress := func(addr ethgo.Address) (uint64, error) {\n\t\t\tparams := map[string]string{\n\t\t\t\t\"address\":   addr.String(),\n\t\t\t\t\"fromBlock\": \"0\",\n\t\t\t\t\"toBlock\":   \"latest\",\n\t\t\t}\n\t\t\tvar out []map[string]interface{}\n\t\t\tif err := e.Query(\"logs\", \"getLogs\", &out, params); err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t\tif len(out) == 0 {\n\t\t\t\treturn 0, nil\n\t\t\t}\n\n\t\t\tcc, ok := out[0][\"blockNumber\"].(string)\n\t\t\tif !ok {\n\t\t\t\treturn 0, fmt.Errorf(\"failed to cast blocknumber\")\n\t\t\t}\n\n\t\t\tnum, err := parseUint64orHex(cc)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t\treturn num, nil\n\t\t}\n\n\t\tminBlock := ^uint64(0) // max uint64\n\t\tfor _, addr := range filterConfig.Address {\n\t\t\tnum, err := getAddress(addr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif num < minBlock {\n\t\t\t\tminBlock = num\n\t\t\t}\n\t\t}\n\n\t\tbb, err := t.getBlockByNumber(minBlock - 1)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn bb, nil\n\t}\n\n\treturn nil, nil\n}\n\nfunc (t *Tracker) BatchSync(ctx context.Context) error {\n\tif err := t.preSyncCheck(); err != nil {\n\t\treturn err\n\t}\n\n\tif t.blockTracker == nil {\n\t\t// run a specfic block tracker\n\t\tt.blockTracker = blocktracker.NewBlockTracker(t.provider)\n\t\tif err := t.blockTracker.Init(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tgo t.blockTracker.Start()\n\t\tgo func() {\n\t\t\t// track our stop\n\t\t\t<-ctx.Done()\n\t\t\tt.blockTracker.Close()\n\t\t}()\n\t} else {\n\t\t// just try to init\n\t\tif err := t.blockTracker.Init(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tclose(t.ReadyCh)\n\n\tif err := t.syncImpl(ctx); err != nil {\n\t\treturn err\n\t}\n\n\tselect {\n\tcase t.DoneCh <- struct{}{}:\n\tdefault:\n\t}\n\n\tatomic.StoreInt32(&t.synced, 1)\n\treturn nil\n}\n\n// Sync syncs a specific filter.\n// This can take a long time so should be run concurrently.\nfunc (t *Tracker) Sync(ctx context.Context) error {\n\tif err := t.BatchSync(ctx); err != nil {\n\t\treturn err\n\t}\n\n\t// subscribe and sync\n\tsub := t.blockTracker.Subscribe()\n\tfor {\n\t\tselect {\n\t\tcase evnt := <-sub:\n\t\t\tif err := t.handleBlockEvnt(evnt); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\t}\n\t}\n}\n\nfunc (t *Tracker) syncImpl(ctx context.Context) error {\n\tif err := t.preSyncCheck(); err != nil {\n\t\treturn err\n\t}\n\n\tlock := t.blockTracker.AcquireLock()\n\tdefer func() {\n\t\tif lock.Locked {\n\t\t\tlock.Unlock()\n\t\t}\n\t}()\n\n\t// We only hold the lock when we sync the head (last MaxBackLogs)\n\t// because we want to avoid changes in the head while we sync.\n\t// We will only release the lock if we do a bulk sync since it can\n\t// move the target block for the sync.\n\n\tlock.Lock()\n\tif t.blockTracker.Len() == 0 {\n\t\treturn nil\n\t}\n\n\t// get the current target\n\ttarget := t.blockTracker.LastBlocked()\n\tif target == nil {\n\t\treturn nil\n\t}\n\ttargetNum := target.Number\n\n\tlast, err := t.GetLastBlock()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif last == nil {\n\t\t// Try to fast track to the valid block (if possible)\n\t\tlast, err = t.fastTrack(t.config.Filter)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to fasttrack: %v\", err)\n\t\t}\n\t\tif last != nil {\n\t\t\tif err := t.storeLastBlock(last); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif last.Hash == target.Hash {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\t// There might been a reorg when we stopped syncing last time,\n\t// check that our 'beacon' block matches the one in the chain.\n\t// If that is not the case, we consider beacon-maxBackLog our\n\t// real origin point and remove any logs ahead of that point.\n\n\tvar origin uint64\n\tif last != nil {\n\t\tif last.Number > targetNum {\n\t\t\treturn fmt.Errorf(\"store is more advanced than the chain\")\n\t\t}\n\n\t\tpivot, err := t.getBlockByNumber(last.Number)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif last.Number == targetNum {\n\t\t\torigin = last.Number\n\t\t} else {\n\t\t\torigin = last.Number + 1\n\t\t}\n\n\t\tif pivot.Hash != last.Hash {\n\t\t\tancestor, err := t.findAncestor(last, pivot)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\torigin = ancestor + 1\n\t\t\tlogs, err := t.removeLogs(ancestor+1, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tt.emitLogs(EventDel, logs)\n\n\t\t\tlast, err = t.getBlockByNumber(ancestor)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\tstep := targetNum - origin + 1\n\tif step > t.blockTracker.MaxBlockBacklog() {\n\t\t// we are far (more than maxBackLog) from the target block\n\t\t// Do a bulk sync with the eth_getLogs endpoint and get closer\n\t\t// to the target block.\n\n\t\tfor {\n\t\t\tif origin > targetNum {\n\t\t\t\treturn fmt.Errorf(\"from (%d) higher than to (%d)\", origin, targetNum)\n\t\t\t}\n\t\t\tif targetNum-origin+1 <= t.blockTracker.MaxBlockBacklog() {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// release the lock\n\t\t\tlock.Unlock()\n\n\t\t\tlimit := targetNum - t.blockTracker.MaxBlockBacklog()\n\t\t\tif err := t.syncBatch(ctx, origin, limit); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\torigin = limit + 1\n\n\t\t\t// lock again to reset the target block\n\t\t\tlock.Lock()\n\t\t\ttargetNum = t.blockTracker.LastBlocked().Number\n\t\t}\n\t}\n\n\t// we are still holding the lock on the blocksLock so that we are sure\n\t// that the targetNum has not changed\n\ttrackerBlocks := t.blockTracker.BlocksBlocked()\n\tadded := trackerBlocks[uint64(len(trackerBlocks))-1-(targetNum-origin):]\n\n\tevnt, err := t.doFilter(added, nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif evnt != nil {\n\t\tt.emitEvent(evnt)\n\t}\n\n\t// release the lock on the blocks\n\tlock.Unlock()\n\treturn nil\n}\n\nfunc (t *Tracker) removeLogs(number uint64, hash *ethgo.Hash) ([]*ethgo.Log, error) {\n\tindex, err := t.entry.LastIndex()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif index == 0 {\n\t\treturn nil, nil\n\t}\n\n\tvar remove []*ethgo.Log\n\tfor {\n\t\telemIndex := index - 1\n\n\t\tvar log ethgo.Log\n\t\tif err := t.entry.GetLog(elemIndex, &log); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif log.BlockNumber == number {\n\t\t\tif hash != nil && log.BlockHash != *hash {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif log.BlockNumber < number {\n\t\t\tbreak\n\t\t}\n\t\tremove = append(remove, &log)\n\t\tif elemIndex == 0 {\n\t\t\tindex = 0\n\t\t\tbreak\n\t\t}\n\t\tindex = elemIndex\n\t}\n\n\tif err := t.entry.RemoveLogs(index); err != nil {\n\t\treturn nil, err\n\t}\n\treturn remove, nil\n}\n\nfunc revertLogs(in []*ethgo.Log) (out []*ethgo.Log) {\n\tfor i := len(in) - 1; i >= 0; i-- {\n\t\tout = append(out, in[i])\n\t}\n\treturn\n}\n\nfunc (t *Tracker) handleBlockEvnt(blockEvnt *blocktracker.BlockEvent) error {\n\tif blockEvnt == nil {\n\t\treturn nil\n\t}\n\n\t// emit the block event\n\tselect {\n\tcase t.BlockCh <- blockEvnt:\n\tdefault:\n\t}\n\n\tif t.IsSynced() {\n\t\tevnt, err := t.doFilter(blockEvnt.Added, blockEvnt.Removed)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif evnt != nil {\n\t\t\tt.emitEvent(evnt)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (t *Tracker) doFilter(added []*ethgo.Block, removed []*ethgo.Block) (*Event, error) {\n\tevnt := &Event{}\n\tif len(removed) != 0 {\n\t\tpivot := removed[0]\n\t\tlogs, err := t.removeLogs(pivot.Number, &pivot.Hash)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tevnt.Removed = append(evnt.Removed, revertLogs(logs)...)\n\t}\n\n\tfor _, block := range added {\n\t\t// check logs for this blocks\n\t\tquery := t.config.Filter.getFilterSearch()\n\t\tquery.BlockHash = &block.Hash\n\n\t\t// We check the hash, we need to do a retry to let unsynced nodes get the block\n\t\tvar logs []*ethgo.Log\n\t\tvar err error\n\n\t\tfor i := 0; i < 5; i++ {\n\t\t\tlogs, err = t.provider.GetLogs(query)\n\t\t\tif err == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ttime.Sleep(500 * time.Millisecond)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// add logs to the store\n\t\tif err := t.entry.StoreLogs(logs); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tevnt.Added = append(evnt.Added, logs...)\n\t}\n\n\t// store the last block as the new index\n\tif err := t.storeLastBlock(added[len(added)-1]); err != nil {\n\t\treturn nil, err\n\t}\n\treturn evnt, nil\n}\n\nfunc (t *Tracker) getBlockByNumber(blockNumber uint64) (*ethgo.Block, error) {\n\tblock, err := t.provider.GetBlockByNumber(ethgo.BlockNumber(blockNumber), false)\n\tif err != nil {\n\t\treturn nil, err\n\t} else if block == nil {\n\t\t// if block does not exist (for example reorg happened) GetBlockByNumber will return nil, nil\n\t\treturn nil, fmt.Errorf(\"block with number %d not found\", blockNumber)\n\t}\n\n\treturn block, nil\n}\n\n// EventType is the type of the event\ntype EventType int\n\nconst (\n\t// EventAdd happens when a new event is included in the chain\n\tEventAdd EventType = iota\n\t// EventDel may happen when there is a reorg and a past event is deleted\n\tEventDel\n)\n\n// Event is an event emitted when a new log is included\ntype Event struct {\n\tType    EventType\n\tAdded   []*ethgo.Log\n\tRemoved []*ethgo.Log\n}\n\n// BlockEvent is an event emitted when a new block is included\ntype BlockEvent struct {\n\tType    EventType\n\tAdded   []*ethgo.Block\n\tRemoved []*ethgo.Block\n}\n\nfunc min(i, j uint64) uint64 {\n\tif i < j {\n\t\treturn i\n\t}\n\treturn j\n}\n\nfunc parseUint64orHex(str string) (uint64, error) {\n\tbase := 10\n\tif strings.HasPrefix(str, \"0x\") {\n\t\tstr = str[2:]\n\t\tbase = 16\n\t}\n\treturn strconv.ParseUint(str, base, 64)\n}\n"
  },
  {
    "path": "tracker/tracker_test.go",
    "content": "package tracker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/blocktracker\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n\t\"github.com/umbracle/ethgo/jsonrpc/codec\"\n\t\"github.com/umbracle/ethgo/testutil\"\n\t\"github.com/umbracle/ethgo/tracker/store/inmem\"\n)\n\nfunc testConfig() ConfigOption {\n\treturn func(c *Config) {\n\t\tc.BatchSize = 10\n\t}\n}\n\nfunc testFilter(t *testing.T, provider Provider, filterConfig *FilterConfig) []*ethgo.Log {\n\tfilterConfig.Async = true\n\ttt, _ := NewTracker(provider, WithFilter(filterConfig))\n\n\tctx, cancelFn := context.WithCancel(context.Background())\n\tdefer cancelFn()\n\n\tif err := tt.BatchSync(ctx); err != nil {\n\t\trequire.NoError(t, err)\n\t}\n\treturn tt.entry.(*inmem.Entry).Logs()\n}\n\nfunc TestPolling(t *testing.T) {\n\tt.Skip()\n\n\ts := testutil.NewTestServer(t)\n\n\tclient, _ := jsonrpc.NewClient(s.HTTPAddr())\n\n\tc0 := &testutil.Contract{}\n\tc0.AddEvent(testutil.NewEvent(\"A\").Add(\"uint256\", true).Add(\"uint256\", true))\n\tc0.EmitEvent(\"setA1\", \"A\", \"1\", \"2\")\n\n\t_, addr0, err := s.DeployContract(c0)\n\trequire.NoError(t, err)\n\n\t// send 5 txns\n\tfor i := 0; i < 5; i++ {\n\t\ts.TxnTo(addr0, \"setA1\")\n\t}\n\n\ttt, err := NewTracker(client.Eth())\n\tassert.NoError(t, err)\n\n\tctx, cancelFn := context.WithCancel(context.Background())\n\tdefer cancelFn()\n\n\tgo func() {\n\t\tif err := tt.Sync(ctx); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}()\n\n\t// wait for the bulk sync to finish\n\tfor {\n\t\tselect {\n\t\tcase <-tt.EventCh:\n\t\tcase <-tt.DoneCh:\n\t\t\tgoto EXIT\n\t\tcase <-time.After(1 * time.Second):\n\t\t\tt.Fatal(\"timeout to sync\")\n\t\t}\n\t}\nEXIT:\n\n\t// send another 5 transactions, we have to have another log each time\n\tfor i := 0; i < 5; i++ {\n\t\treceipt, err := s.TxnTo(addr0, \"setA1\")\n\t\trequire.NoError(t, err)\n\n\t\tselect {\n\t\tcase evnt := <-tt.EventCh:\n\t\t\tif !reflect.DeepEqual(evnt.Added, receipt.Logs) {\n\t\t\t\tt.Fatal(\"bad\")\n\t\t\t}\n\t\tcase <-time.After(2 * time.Second): // wait at least the polling interval\n\t\t\tt.Fatal(\"event expected\")\n\t\t}\n\t}\n}\n\nfunc TestFilterIntegration(t *testing.T) {\n\ts := testutil.NewTestServer(t)\n\n\tclient, _ := jsonrpc.NewClient(s.HTTPAddr())\n\n\tc0 := &testutil.Contract{}\n\tc0.AddEvent(testutil.NewEvent(\"A\").Add(\"uint256\", true).Add(\"uint256\", true))\n\tc0.EmitEvent(\"setA1\", \"A\", \"1\", \"2\")\n\n\t_, addr0, err := s.DeployContract(c0)\n\trequire.NoError(t, err)\n\n\t_, addr1, err := s.DeployContract(c0)\n\trequire.NoError(t, err)\n\n\tfor i := 0; i < 20; i++ {\n\t\tif i%2 == 0 {\n\t\t\t_, err := s.TxnTo(addr0, \"setA1\")\n\t\t\trequire.NoError(t, err)\n\t\t} else {\n\t\t\t_, err := s.TxnTo(addr1, \"setA1\")\n\t\t\trequire.NoError(t, err)\n\t\t}\n\t}\n\n\t// filter by address\n\tlogs := testFilter(t, client.Eth(), &FilterConfig{Address: []ethgo.Address{addr0}})\n\trequire.NotEmpty(t, logs)\n\n\t// filter by value\n\ttyp, _ := abi.NewType(\"uint256\")\n\ttopic, _ := abi.EncodeTopic(typ, 1)\n\n\tlogs = testFilter(t, client.Eth(), &FilterConfig{Topics: [][]*ethgo.Hash{nil, {&topic}}})\n\trequire.NotEmpty(t, logs)\n}\n\nfunc TestPreflight(t *testing.T) {\n\tstore := inmem.NewInmemStore()\n\n\tl := testutil.MockList{}\n\tl.Create(0, 100, func(b *testutil.MockBlock) {})\n\n\tm := &testutil.MockClient{}\n\tm.AddScenario(l)\n\n\ttt0, _ := NewTracker(m, testConfig(), WithStore(store))\n\tif err := tt0.preSyncCheckImpl(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// change the genesis hash\n\n\tl0 := testutil.MockList{}\n\tl0.Create(0, 100, func(b *testutil.MockBlock) {\n\t\tb = b.Extra(\"1\")\n\t})\n\n\tm.AddScenario(l0)\n\n\ttt1, _ := NewTracker(m, testConfig(), WithStore(store))\n\tif err := tt1.preSyncCheckImpl(); err == nil {\n\t\tt.Fatal(\"it should fail\")\n\t}\n\n\t// change the chainID\n\n\tm.AddScenario(l)\n\tm.SetChainID(big.NewInt(1))\n\n\ttt2, _ := NewTracker(m, testConfig(), WithStore(store))\n\tif err := tt2.preSyncCheckImpl(); err == nil {\n\t\tt.Fatal(\"it should fail\")\n\t}\n}\n\nfunc TestTrackerSyncerRestarts(t *testing.T) {\n\tstore := inmem.NewInmemStore()\n\tm := &testutil.MockClient{}\n\tl := testutil.MockList{}\n\n\tadvance := func(first, last int, void ...bool) {\n\t\tif len(void) == 0 {\n\t\t\tl.Create(first, last, func(b *testutil.MockBlock) {\n\t\t\t\tif b.GetNum()%5 == 0 {\n\t\t\t\t\tb = b.Log(\"0x1\")\n\t\t\t\t}\n\t\t\t})\n\t\t\tm.AddScenario(l)\n\t\t}\n\n\t\ttt, err := NewTracker(m,\n\t\t\ttestConfig(),\n\t\t\tWithStore(store),\n\t\t\tWithFilter(&FilterConfig{Async: true}),\n\t\t)\n\t\tassert.NoError(t, err)\n\n\t\tgo func() {\n\t\t\tif err := tt.Sync(context.Background()); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t}()\n\n\t\tif err := tt.WaitDuration(2 * time.Second); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tif tt.blockTracker.BlocksBlocked()[0].Number != uint64(last-10) {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t\tif tt.blockTracker.BlocksBlocked()[9].Number != uint64(last-1) {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t\tif !testutil.CompareLogs(l.GetLogs(), tt.entry.(*inmem.Entry).Logs()) {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t}\n\n\t// initial range\n\tadvance(0, 100)\n\n\t// dont advance\n\tadvance(0, 100, true)\n\n\t// advance less than backlog\n\tadvance(100, 105)\n\n\t// advance more than backlog\n\tadvance(105, 150)\n}\n\nfunc testSyncerReconcile(t *testing.T, iniLen, forkNum, endLen int) {\n\t// test that the syncer can reconcile if there is a fork in the saved state\n\tl := testutil.MockList{}\n\tl.Create(0, iniLen, func(b *testutil.MockBlock) {\n\t\tb = b.Log(\"0x01\")\n\t})\n\n\tm := &testutil.MockClient{}\n\tm.AddScenario(l)\n\n\tstore := inmem.NewInmemStore()\n\n\ttt0, err := NewTracker(m,\n\t\ttestConfig(),\n\t\tWithStore(store),\n\t\tWithFilter(&FilterConfig{Async: true}),\n\t)\n\tassert.NoError(t, err)\n\n\tgo func() {\n\t\tif err := tt0.Sync(context.Background()); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}()\n\ttt0.WaitDuration(2 * time.Second)\n\n\t// create a fork at 'forkNum' and continue to 'endLen'\n\tl1 := testutil.MockList{}\n\tl1.Create(0, endLen, func(b *testutil.MockBlock) {\n\t\tif b.GetNum() < forkNum {\n\t\t\tb = b.Log(\"0x01\") // old fork\n\t\t} else {\n\t\t\tif b.GetNum() == forkNum {\n\t\t\t\tb = b.Log(\"0x02\")\n\t\t\t} else {\n\t\t\t\tb = b.Log(\"0x03\")\n\t\t\t}\n\t\t\tb = b.Extra(\"123\") // used to set the new fork\n\t\t}\n\t})\n\n\tm1 := &testutil.MockClient{}\n\tm1.AddScenario(l)\n\tm1.AddScenario(l1)\n\n\ttt1, _ := NewTracker(m1,\n\t\ttestConfig(),\n\t\tWithStore(store),\n\t\tWithFilter(&FilterConfig{Async: true}),\n\t)\n\tgo func() {\n\t\tif err := tt1.Sync(context.Background()); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}()\n\ttt1.WaitDuration(2 * time.Second)\n\n\tlogs := tt1.entry.(*inmem.Entry).Logs()\n\n\tif !testutil.CompareLogs(l1.GetLogs(), logs) {\n\t\tt.Fatal(\"bad\")\n\t}\n\n\t// check the content of the logs\n\n\t// first half\n\tfor i := 0; i < forkNum; i++ {\n\t\tif logs[i].Data[0] != 0x1 {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t}\n\t// fork point\n\tif logs[forkNum].Data[0] != 0x2 {\n\t\tt.Fatal(\"bad\")\n\t}\n\t// second half\n\tfor i := forkNum + 1; i < endLen; i++ {\n\t\tif logs[i].Data[0] != 0x3 {\n\t\t\tt.Fatal(\"bad\")\n\t\t}\n\t}\n}\n\nfunc TestTrackerSyncerReconcile(t *testing.T) {\n\tt.Run(\"Backlog\", func(t *testing.T) {\n\t\ttestSyncerReconcile(t, 50, 45, 55)\n\t})\n\tt.Run(\"Historical\", func(t *testing.T) {\n\t\ttestSyncerReconcile(t, 50, 45, 100)\n\t})\n}\n\nfunc randomInt(min, max int) int {\n\treturn min + rand.Intn(max-min)\n}\n\nfunc testTrackerSyncerRandom(t *testing.T, n int, backlog uint64) {\n\tm := &testutil.MockClient{}\n\tc := 0 // current block\n\tf := 0 // current fork\n\n\tstore := inmem.NewInmemStore()\n\n\tfor i := 0; i < n; i++ {\n\t\t// fmt.Println(\"########################################\")\n\n\t\t// create the new batch of blocks\n\t\tvar forkSize int\n\t\tif randomInt(0, 10) < 3 && c > 10 {\n\t\t\t// add a fork, go back at most maxBacklogSize\n\t\t\tforkSize = randomInt(1, int(backlog))\n\t\t\tc = c - forkSize\n\t\t\tf++\n\t\t}\n\n\t\tforkID := strconv.Itoa(f)\n\n\t\t// add new blocks\n\t\tl := testutil.MockList{}\n\n\t\t// we have to create at least the blocks removed by the fork, otherwise\n\t\t// we may end up going backwards if the forks remove more data than the\n\t\t// advance includes\n\n\t\tstart := forkSize\n\t\tif start == 0 && i == 0 {\n\t\t\tstart = 1 // at least advance one block on the first iteration\n\t\t}\n\t\tnum := randomInt(start, 20)\n\t\tcount := 0\n\n\t\tfor j := c; j < c+num; j++ {\n\t\t\tbb := testutil.Mock(j).Extra(forkID)\n\t\t\tif j != 0 {\n\t\t\t\tcount++\n\t\t\t\tbb = bb.Log(forkID)\n\t\t\t}\n\t\t\tl = append(l, bb)\n\t\t}\n\n\t\tm.AddScenario(l)\n\n\t\t// use a custom block tracker to add specific backlog\n\t\ttracker := blocktracker.NewBlockTracker(m, blocktracker.WithBlockMaxBacklog(backlog))\n\n\t\ttt, _ := NewTracker(m,\n\t\t\ttestConfig(),\n\t\t\tWithStore(store),\n\t\t\tWithBlockTracker(tracker),\n\t\t)\n\n\t\tgo func() {\n\t\t\tif err := tt.Sync(context.Background()); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t}()\n\n\t\tvar added, removed []*ethgo.Log\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase evnt := <-tt.EventCh:\n\t\t\t\tadded = append(added, evnt.Added...)\n\t\t\t\tremoved = append(removed, evnt.Removed...)\n\n\t\t\tcase <-tt.DoneCh:\n\t\t\t\t// no more events to read\n\t\t\t\tgoto EXIT\n\t\t\t}\n\t\t}\n\tEXIT:\n\n\t\t// validate the included logs\n\t\tif len(added) != count {\n\t\t\tt.Fatal(\"bad added logs\")\n\t\t}\n\t\t// validate the removed logs\n\t\tif len(removed) != forkSize {\n\t\t\tt.Fatal(\"bad removed logs\")\n\t\t}\n\n\t\t// validate blocks\n\t\tif blocks := m.GetLastBlocks(backlog); !testutil.CompareBlocks(tt.blockTracker.BlocksBlocked(), blocks) {\n\t\t\t// tracker does not consider block 0 but getLastBlocks does return it, this is only a problem\n\t\t\t// with syncs on chains lower than maxBacklog\n\t\t\tif !testutil.CompareBlocks(blocks[1:], tt.blockTracker.BlocksBlocked()) {\n\t\t\t\tt.Fatal(\"bad blocks\")\n\t\t\t}\n\t\t}\n\t\t// validate logs\n\t\tif logs := m.GetAllLogs(); !testutil.CompareLogs(tt.entry.(*inmem.Entry).Logs(), logs) {\n\t\t\tt.Fatal(\"bad logs\")\n\t\t}\n\n\t\tc += num\n\t}\n}\n\nfunc TestTrackerSyncerRandom(t *testing.T) {\n\trand.Seed(time.Now().UTC().UnixNano())\n\n\tfor i := 0; i < 100; i++ {\n\t\tt.Run(\"\", func(t *testing.T) {\n\t\t\ttestTrackerSyncerRandom(t, 100, uint64(randomInt(2, 10)))\n\t\t})\n\t}\n}\n\nfunc TestTrackerReconcile(t *testing.T) {\n\ttype TestEvent struct {\n\t\tAdded   testutil.MockList\n\t\tRemoved testutil.MockList\n\t}\n\n\ttype Reconcile struct {\n\t\tblock *testutil.MockBlock\n\t\tevent *TestEvent\n\t}\n\n\tcases := []struct {\n\t\tName      string\n\t\tScenario  testutil.MockList\n\t\tHistory   testutil.MockList\n\t\tReconcile []Reconcile\n\t\tExpected  testutil.MockList\n\t}{\n\t\t{\n\t\t\tName: \"Empty history\",\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x1).Log(\"0x1\"),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x1).Log(\"0x1\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: []*testutil.MockBlock{\n\t\t\t\ttestutil.Mock(1).Log(\"0x1\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Repeated header\",\n\t\t\tHistory: []*testutil.MockBlock{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x1),\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: []*testutil.MockBlock{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"New head\",\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x2),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Ignore block already on history\",\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x2),\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Multi Roll back\",\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3).Log(\"0x3\"),\n\t\t\t\ttestutil.Mock(0x4).Log(\"0x4\"),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x30).Parent(0x2).Log(\"0x30\"),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Log(\"0x30\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tRemoved: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x3).Log(\"0x3\"),\n\t\t\t\t\t\t\ttestutil.Mock(0x4).Log(\"0x4\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Log(\"0x30\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Backfills missing blocks\",\n\t\t\tScenario: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\ttestutil.Mock(0x4).Log(\"0x2\"),\n\t\t\t},\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1).Log(\"0x1\"),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x5).Log(\"0x3\"),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\t\t\t\ttestutil.Mock(0x4).Log(\"0x2\"),\n\t\t\t\t\t\t\ttestutil.Mock(0x5).Log(\"0x3\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1).Log(\"0x1\"),\n\t\t\t\ttestutil.Mock(0x2),\n\t\t\t\ttestutil.Mock(0x3),\n\t\t\t\ttestutil.Mock(0x4).Log(\"0x2\"),\n\t\t\t\ttestutil.Mock(0x5).Log(\"0x3\"),\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tName: \"Rolls back and backfills\",\n\t\t\tScenario: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Num(3).Log(\"0x5\"),\n\t\t\t\ttestutil.Mock(0x40).Parent(0x30).Num(4),\n\t\t\t},\n\t\t\tHistory: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2).Log(\"0x3\"),\n\t\t\t\ttestutil.Mock(0x3).Log(\"0x2\"),\n\t\t\t\ttestutil.Mock(0x4).Log(\"0x1\"),\n\t\t\t},\n\t\t\tReconcile: []Reconcile{\n\t\t\t\t{\n\t\t\t\t\tblock: testutil.Mock(0x50).Parent(0x40).Num(5),\n\t\t\t\t\tevent: &TestEvent{\n\t\t\t\t\t\tAdded: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Num(3).Log(\"0x5\"),\n\t\t\t\t\t\t\ttestutil.Mock(0x40).Parent(0x30).Num(4),\n\t\t\t\t\t\t\ttestutil.Mock(0x50).Parent(0x40).Num(5),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tRemoved: testutil.MockList{\n\t\t\t\t\t\t\ttestutil.Mock(0x3).Log(\"0x2\"),\n\t\t\t\t\t\t\ttestutil.Mock(0x4).Log(\"0x1\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExpected: testutil.MockList{\n\t\t\t\ttestutil.Mock(0x1),\n\t\t\t\ttestutil.Mock(0x2).Log(\"0x3\"),\n\t\t\t\ttestutil.Mock(0x30).Parent(0x2).Num(3).Log(\"0x5\"),\n\t\t\t\ttestutil.Mock(0x40).Parent(0x30).Num(4),\n\t\t\t\ttestutil.Mock(0x50).Parent(0x40).Num(5),\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.Name, func(t *testing.T) {\n\t\t\t// safe check for now, we ma need to restart the tracker and mock client for every reconcile scenario?\n\t\t\tif len(c.Reconcile) != 1 {\n\t\t\t\tt.Fatal(\"only one reconcile supported so far\")\n\t\t\t}\n\n\t\t\tm := &testutil.MockClient{}\n\n\t\t\t// add the full scenario with the logs\n\t\t\tm.AddScenario(c.Scenario)\n\n\t\t\t// add the logs of the reconcile block because those are also unknown for the tracker\n\t\t\tm.AddLogs(c.Reconcile[0].block.GetLogs())\n\n\t\t\tstore := inmem.NewInmemStore()\n\n\t\t\tbtracker := blocktracker.NewBlockTracker(m)\n\n\t\t\ttt, err := NewTracker(m, WithStore(store), WithBlockTracker(btracker))\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// important to set a buffer here, otherwise everything is blocked\n\t\t\ttt.EventCh = make(chan *Event, 1)\n\n\t\t\t// set the filter as synced since we only want to\n\t\t\t// try reconciliation\n\t\t\ttt.synced = 1\n\n\t\t\t// build past block history\n\t\t\tfor _, b := range c.History.ToBlocks() {\n\t\t\t\ttt.blockTracker.AddBlockLocked(b)\n\t\t\t}\n\t\t\t// add the history to the store\n\t\t\tfor _, b := range c.History {\n\t\t\t\ttt.entry.StoreLogs(b.GetLogs())\n\t\t\t}\n\n\t\t\tfor _, b := range c.Reconcile {\n\t\t\t\taux, err := tt.blockTracker.HandleBlockEvent(b.block.Block())\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif aux == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif err := tt.handleBlockEvnt(aux); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\n\t\t\t\tvar evnt *Event\n\t\t\t\tselect {\n\t\t\t\tcase evnt = <-tt.EventCh:\n\t\t\t\tcase <-time.After(1 * time.Second):\n\t\t\t\t\tt.Fatal(\"log event timeout\")\n\t\t\t\t}\n\n\t\t\t\t// check logs\n\t\t\t\tif !testutil.CompareLogs(b.event.Added.GetLogs(), evnt.Added) {\n\t\t\t\t\tt.Fatal(\"err\")\n\t\t\t\t}\n\t\t\t\tif !testutil.CompareLogs(b.event.Removed.GetLogs(), evnt.Removed) {\n\t\t\t\t\tt.Fatal(\"err\")\n\t\t\t\t}\n\n\t\t\t\tvar blockEvnt *blocktracker.BlockEvent\n\t\t\t\tselect {\n\t\t\t\tcase blockEvnt = <-tt.BlockCh:\n\t\t\t\tcase <-time.After(1 * time.Second):\n\t\t\t\t\tt.Fatal(\"block event timeout\")\n\t\t\t\t}\n\n\t\t\t\t// check blocks\n\t\t\t\tif !testutil.CompareBlocks(b.event.Added.ToBlocks(), blockEvnt.Added) {\n\t\t\t\t\tt.Fatal(\"err\")\n\t\t\t\t}\n\t\t\t\tif !testutil.CompareBlocks(b.event.Removed.ToBlocks(), blockEvnt.Removed) {\n\t\t\t\t\tt.Fatal(\"err\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// check the post state (logs and blocks) after all the reconcile events\n\t\t\tif !testutil.CompareLogs(tt.entry.(*inmem.Entry).Logs(), c.Expected.GetLogs()) {\n\t\t\t\tt.Fatal(\"bad3\")\n\t\t\t}\n\t\t\tif !testutil.CompareBlocks(tt.blockTracker.BlocksBlocked(), c.Expected.ToBlocks()) {\n\t\t\t\tt.Fatal(\"bad\")\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype mockClientWithLimit struct {\n\tlimit uint64\n\ttestutil.MockClient\n}\n\nfunc (m *mockClientWithLimit) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error) {\n\tif filter.BlockHash != nil {\n\t\treturn m.MockClient.GetLogs(filter)\n\t}\n\tfrom, to := uint64(*filter.From), uint64(*filter.To)\n\tif from > to {\n\t\treturn nil, fmt.Errorf(\"from higher than to\")\n\t}\n\tif to-from > m.limit {\n\t\treturn nil, &codec.ErrorObject{Message: \"query returned more than 10000 results\"}\n\t}\n\t// fallback to the client\n\treturn m.MockClient.GetLogs(filter)\n}\n\nfunc TestTooMuchDataRequested(t *testing.T) {\n\tcount := 0\n\n\t// create 100 blocks with 2 (even) or 5 (odd) logs each\n\tl := testutil.MockList{}\n\tl.Create(0, 100, func(b *testutil.MockBlock) {\n\t\tvar numLogs int\n\t\tif b.GetNum()%2 == 0 {\n\t\t\tnumLogs = 2\n\t\t} else {\n\t\t\tnumLogs = 5\n\t\t}\n\t\tfor i := 0; i < numLogs; i++ {\n\t\t\tcount++\n\t\t\tb.Log(\"0x1\")\n\t\t}\n\t})\n\n\tm := &testutil.MockClient{}\n\tm.AddScenario(l)\n\n\tmm := &mockClientWithLimit{\n\t\tlimit:      3,\n\t\tMockClient: *m,\n\t}\n\n\tconfig := DefaultConfig()\n\tconfig.BatchSize = 11\n\n\ttt, _ := NewTracker(mm,\n\t\tWithFilter(&FilterConfig{Async: true}),\n\t)\n\tif err := tt.BatchSync(context.Background()); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != len(tt.entry.(*inmem.Entry).Logs()) {\n\t\tt.Fatal(\"not the same count\")\n\t}\n}\n"
  },
  {
    "path": "units.go",
    "content": "package ethgo\n\nimport \"math/big\"\n\nfunc convert(val uint64, decimals int64) *big.Int {\n\tv := big.NewInt(int64(val))\n\texp := new(big.Int).Exp(big.NewInt(10), big.NewInt(decimals), nil)\n\treturn v.Mul(v, exp)\n}\n\n// Ether converts a value to the ether unit with 18 decimals\nfunc Ether(i uint64) *big.Int {\n\treturn convert(i, 18)\n}\n\n// Gwei converts a value to the gwei unit with 9 decimals\nfunc Gwei(i uint64) *big.Int {\n\treturn convert(i, 9)\n}\n"
  },
  {
    "path": "wallet/fixtures/wallet_json.json",
    "content": "[\n    {\n        \"wallet\": {\n            \"crypto\": {\n                \"cipher\": \"aes-128-ctr\",\n                \"cipherparams\": {\n                    \"iv\": \"6087dab2f9fdbbfaddc31a909735c1e6\"\n                },\n                \"ciphertext\": \"5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46\",\n                \"kdf\": \"pbkdf2\",\n                \"kdfparams\": {\n                    \"c\": 262144,\n                    \"dklen\": 32,\n                    \"prf\": \"hmac-sha256\",\n                    \"salt\": \"ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd\"\n                },\n                \"mac\": \"517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2\"\n            },\n            \"id\": \"3198bc9c-6672-5ab3-d995-4942343ae5b6\",\n            \"version\": 3\n        },\n        \"password\": \"testpassword\",\n        \"address\": \"0x008AeEda4D805471dF9b2A5B0f38A0C3bCBA786b\"\n    },\n    {\n        \"wallet\": {\n            \"crypto\" : {\n                \"cipher\" : \"aes-128-ctr\",\n                \"cipherparams\" : {\n                    \"iv\" : \"83dbcc02d8ccb40e466191a123791e0e\"\n                },\n                \"ciphertext\" : \"d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c\",\n                \"kdf\" : \"scrypt\",\n                \"kdfparams\" : {\n                    \"dklen\" : 32,\n                    \"n\" : 262144,\n                    \"p\" : 8,\n                    \"r\" : 1,\n                    \"salt\" : \"ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19\"\n                },\n                \"mac\" : \"2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097\"\n            },\n            \"id\" : \"3198bc9c-6672-5ab3-d995-4942343ae5b6\",\n            \"version\" : 3\n        },\n        \"password\": \"testpassword\",\n        \"address\": \"0x008AeEda4D805471dF9b2A5B0f38A0C3bCBA786b\"\n    }\n]"
  },
  {
    "path": "wallet/key.go",
    "content": "package wallet\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"fmt\"\n\n\t\"github.com/btcsuite/btcd/btcec/v2\"\n\tbtcecdsa \"github.com/btcsuite/btcd/btcec/v2/ecdsa\"\n\t\"github.com/umbracle/ethgo\"\n)\n\n// S256 is the secp256k1 elliptic curve\nvar S256 = btcec.S256()\n\nvar _ ethgo.Key = &Key{}\n\n// Key is an implementation of the Key interface with a private key\ntype Key struct {\n\tpriv *btcec.PrivateKey\n\tpub  *btcec.PublicKey\n\taddr ethgo.Address\n}\n\nfunc (k *Key) Address() ethgo.Address {\n\treturn k.addr\n}\n\nfunc (k *Key) MarshallPrivateKey() ([]byte, error) {\n\treturn (*btcec.PrivateKey)(k.priv).Serialize(), nil\n}\n\nfunc (k *Key) SignMsg(msg []byte) ([]byte, error) {\n\treturn k.Sign(ethgo.Keccak256(msg))\n}\n\nfunc (k *Key) Sign(hash []byte) ([]byte, error) {\n\tsig, err := btcecdsa.SignCompact(k.priv, hash, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tterm := byte(0)\n\tif sig[0] == 28 {\n\t\tterm = 1\n\t}\n\treturn append(sig, term)[1:], nil\n}\n\n// NewKey creates a new key with a private key\nfunc NewKey(prv *ecdsa.PrivateKey) (*Key, error) {\n\tvar priv btcec.PrivateKey\n\tif overflow := priv.Key.SetByteSlice(prv.D.Bytes()); overflow || priv.Key.IsZero() {\n\t\treturn nil, fmt.Errorf(\"invalid key: overflow\")\n\t}\n\n\tk := &Key{\n\t\tpriv: &priv,\n\t\tpub:  priv.PubKey(),\n\t\taddr: pubKeyToAddress(priv.PubKey().ToECDSA()),\n\t}\n\treturn k, nil\n}\n\nfunc pubKeyToAddress(pub *ecdsa.PublicKey) (addr ethgo.Address) {\n\tb := ethgo.Keccak256(elliptic.Marshal(S256, pub.X, pub.Y)[1:])\n\tcopy(addr[:], b[12:])\n\treturn\n}\n\n// GenerateKey generates a new key based on the secp256k1 elliptic curve.\nfunc GenerateKey() (*Key, error) {\n\tpriv, err := ecdsa.GenerateKey(S256, rand.Reader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewKey(priv)\n}\n\nfunc EcrecoverMsg(msg, signature []byte) (ethgo.Address, error) {\n\treturn Ecrecover(ethgo.Keccak256(msg), signature)\n}\n\nfunc Ecrecover(hash, signature []byte) (ethgo.Address, error) {\n\tpub, err := RecoverPubkey(signature, hash)\n\tif err != nil {\n\t\treturn ethgo.Address{}, err\n\t}\n\treturn pubKeyToAddress(pub), nil\n}\n\nfunc RecoverPubkey(signature, hash []byte) (*ecdsa.PublicKey, error) {\n\tsize := len(signature)\n\tterm := byte(27)\n\tif signature[size-1] == 1 {\n\t\tterm = 28\n\t}\n\n\tsig := append([]byte{term}, signature[:size-1]...)\n\tpub, _, err := btcecdsa.RecoverCompact(sig, hash)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn pub.ToECDSA(), nil\n}\n"
  },
  {
    "path": "wallet/key_test.go",
    "content": "package wallet\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestKeySign(t *testing.T) {\n\tkey, err := GenerateKey()\n\tassert.NoError(t, err)\n\n\tmsg := []byte(\"hello world\")\n\tsignature, err := key.SignMsg(msg)\n\tassert.NoError(t, err)\n\n\taddr, err := EcrecoverMsg(msg, signature)\n\tassert.NoError(t, err)\n\tassert.Equal(t, addr, key.addr)\n}\n"
  },
  {
    "path": "wallet/signer.go",
    "content": "package wallet\n\nimport (\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/fastrlp\"\n)\n\ntype Signer interface {\n\t// RecoverSender returns the sender to the transaction\n\tRecoverSender(tx *ethgo.Transaction) (ethgo.Address, error)\n\n\t// SignTx signs a transaction\n\tSignTx(tx *ethgo.Transaction, key ethgo.Key) (*ethgo.Transaction, error)\n}\n\ntype EIP1155Signer struct {\n\tchainID uint64\n}\n\nfunc NewEIP155Signer(chainID uint64) *EIP1155Signer {\n\treturn &EIP1155Signer{chainID: chainID}\n}\n\nfunc (e *EIP1155Signer) RecoverSender(tx *ethgo.Transaction) (ethgo.Address, error) {\n\tv := new(big.Int).SetBytes(tx.V).Uint64()\n\tif v > 1 {\n\t\tv -= 27\n\t\tif v > 1 {\n\t\t\tv -= e.chainID * 2\n\t\t\tv -= 8\n\t\t}\n\t}\n\n\tsig, err := encodeSignature(tx.R, tx.S, byte(v))\n\tif err != nil {\n\t\treturn ethgo.Address{}, err\n\t}\n\taddr, err := Ecrecover(signHash(tx, e.chainID), sig)\n\tif err != nil {\n\t\treturn ethgo.Address{}, err\n\t}\n\treturn addr, nil\n}\n\nfunc trimBytesZeros(b []byte) []byte {\n\tvar i int\n\tfor i = 0; i < len(b); i++ {\n\t\tif b[i] != 0x0 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn b[i:]\n}\n\nfunc (e *EIP1155Signer) SignTx(tx *ethgo.Transaction, key ethgo.Key) (*ethgo.Transaction, error) {\n\thash := signHash(tx, e.chainID)\n\n\tsig, err := key.Sign(hash)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvv := uint64(sig[64])\n\tif tx.Type == 0 {\n\t\tvv = vv + 35 + e.chainID*2\n\t}\n\n\ttx.R = trimBytesZeros(sig[:32])\n\ttx.S = trimBytesZeros(sig[32:64])\n\ttx.V = new(big.Int).SetUint64(vv).Bytes()\n\treturn tx, nil\n}\n\nfunc signHash(tx *ethgo.Transaction, chainID uint64) []byte {\n\ta := fastrlp.DefaultArenaPool.Get()\n\tdefer fastrlp.DefaultArenaPool.Put(a)\n\n\tv := a.NewArray()\n\n\tif tx.Type != ethgo.TransactionLegacy {\n\t\t// either dynamic and access type\n\t\tv.Set(a.NewBigInt(new(big.Int).SetUint64(chainID)))\n\t}\n\n\tv.Set(a.NewUint(tx.Nonce))\n\n\tif tx.Type == ethgo.TransactionDynamicFee {\n\t\t// dynamic fee uses\n\t\tv.Set(a.NewBigInt(tx.MaxPriorityFeePerGas))\n\t\tv.Set(a.NewBigInt(tx.MaxFeePerGas))\n\t} else {\n\t\t// legacy and access type use gas price\n\t\tv.Set(a.NewUint(tx.GasPrice))\n\t}\n\n\tv.Set(a.NewUint(tx.Gas))\n\tif tx.To == nil {\n\t\tv.Set(a.NewNull())\n\t} else {\n\t\tv.Set(a.NewCopyBytes((*tx.To)[:]))\n\t}\n\tv.Set(a.NewBigInt(tx.Value))\n\tv.Set(a.NewCopyBytes(tx.Input))\n\n\tif tx.Type != ethgo.TransactionLegacy {\n\t\t// either dynamic and access type\n\t\taccessList, err := tx.AccessList.MarshalRLPWith(a)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tv.Set(accessList)\n\t}\n\n\t// EIP155\n\tif chainID != 0 && tx.Type == ethgo.TransactionLegacy {\n\t\tv.Set(a.NewUint(chainID))\n\t\tv.Set(a.NewUint(0))\n\t\tv.Set(a.NewUint(0))\n\t}\n\n\tdst := v.MarshalTo(nil)\n\n\t// append the tx type byte\n\tif tx.Type != ethgo.TransactionLegacy {\n\t\tdst = append([]byte{byte(tx.Type)}, dst...)\n\t}\n\treturn ethgo.Keccak256(dst)\n}\n\nfunc encodeSignature(R, S []byte, V byte) ([]byte, error) {\n\tsig := make([]byte, 65)\n\tcopy(sig[32-len(R):32], R)\n\tcopy(sig[64-len(S):64], S)\n\tsig[64] = V\n\treturn sig, nil\n}\n"
  },
  {
    "path": "wallet/signer_test.go",
    "content": "package wallet\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n\t\"pgregory.net/rapid\"\n)\n\nfunc TestSigner_SignAndRecover(t *testing.T) {\n\trapid.Check(t, func(t *rapid.T) {\n\t\t// fill in common types for a transaction\n\t\ttxn := &ethgo.Transaction{}\n\n\t\tif rapid.Bool().Draw(t, \"to\") {\n\t\t\tto := ethgo.BytesToAddress(rapid.SliceOf(rapid.Byte()).Draw(t, \"to_addr\"))\n\t\t\ttxn.To = &to\n\t\t}\n\n\t\ttxType := rapid.IntRange(0, 2).Draw(t, \"tx type\")\n\n\t\t// fill in specific fields depending on the type\n\t\t// of the transaction.\n\t\ttxn.Type = ethgo.TransactionType(txType)\n\t\tif txn.Type == ethgo.TransactionDynamicFee {\n\t\t\tmaxFeePerGas := rapid.Int64Range(1, 1000000000).Draw(t, \"maxFeePerGas\")\n\t\t\ttxn.MaxFeePerGas = big.NewInt(maxFeePerGas)\n\t\t\tmaxPriorityFeePerGas := rapid.Int64Range(1, 1000000000).Draw(t, \"maxPriorityFeePerGas\")\n\t\t\ttxn.MaxPriorityFeePerGas = big.NewInt(maxPriorityFeePerGas)\n\t\t} else {\n\t\t\tgasPrice := rapid.Uint64Range(1, 1000000000).Draw(t, \"gasPrice\")\n\t\t\ttxn.GasPrice = gasPrice\n\t\t}\n\n\t\t// signer is from a random chain\n\t\tchainId := rapid.Uint64().Draw(t, \"chainId\")\n\t\tsigner := NewEIP155Signer(chainId)\n\n\t\tkey, err := GenerateKey()\n\t\trequire.NoError(t, err)\n\n\t\tsignedTxn, err := signer.SignTx(txn, key)\n\t\trequire.NoError(t, err)\n\n\t\t// recover the sender\n\t\tsender, err := signer.RecoverSender(signedTxn)\n\t\trequire.NoError(t, err)\n\n\t\trequire.Equal(t, sender, key.Address())\n\t})\n}\n\nfunc TestSigner_EIP1155(t *testing.T) {\n\tsigner1 := NewEIP155Signer(1337)\n\n\taddr0 := ethgo.Address{0x1}\n\tkey, err := GenerateKey()\n\tassert.NoError(t, err)\n\n\ttxn := &ethgo.Transaction{\n\t\tTo:       &addr0,\n\t\tValue:    big.NewInt(10),\n\t\tGasPrice: 0,\n\t}\n\ttxn, err = signer1.SignTx(txn, key)\n\tassert.NoError(t, err)\n\n\tfrom, err := signer1.RecoverSender(txn)\n\tassert.NoError(t, err)\n\tassert.Equal(t, from, key.addr)\n}\n\nfunc TestTrimBytesZeros(t *testing.T) {\n\tassert.Equal(t, trimBytesZeros([]byte{0x1, 0x2}), []byte{0x1, 0x2})\n\tassert.Equal(t, trimBytesZeros([]byte{0x0, 0x1}), []byte{0x1})\n\tassert.Equal(t, trimBytesZeros([]byte{0x0, 0x0}), []byte{})\n}\n"
  },
  {
    "path": "wallet/wallet_hd.go",
    "content": "package wallet\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strings\"\n\n\t\"github.com/btcsuite/btcd/btcutil/hdkeychain\"\n\t\"github.com/btcsuite/btcd/chaincfg\"\n\t\"github.com/tyler-smith/go-bip39\"\n)\n\ntype DerivationPath []uint32\n\n// 0x800000\nvar decVal = big.NewInt(2147483648)\n\n// DefaultDerivationPath is the default derivation path for Ethereum addresses\nvar DefaultDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}\n\nfunc (d *DerivationPath) Derive(master *hdkeychain.ExtendedKey) (*ecdsa.PrivateKey, error) {\n\tvar err error\n\tkey := master\n\tfor _, n := range *d {\n\t\tkey, err = key.Derive(n)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tpriv, err := key.ECPrivKey()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn priv.ToECDSA(), nil\n}\n\nfunc parseDerivationPath(path string) (*DerivationPath, error) {\n\tparts := strings.Split(path, \"/\")\n\tif len(parts) == 0 {\n\t\treturn nil, fmt.Errorf(\"no derivation path\")\n\t}\n\n\t// clean all the parts of any trim spaces\n\tfor indx := range parts {\n\t\tparts[indx] = strings.TrimSpace(parts[indx])\n\t}\n\n\t// first part has to be an 'm'\n\tif parts[0] != \"m\" {\n\t\treturn nil, fmt.Errorf(\"first has to be m\")\n\t}\n\n\tresult := DerivationPath{}\n\tfor _, p := range parts[1:] {\n\t\tval := new(big.Int)\n\t\tif strings.HasSuffix(p, \"'\") {\n\t\t\tp = strings.TrimSuffix(p, \"'\")\n\t\t\tval.Add(val, decVal)\n\t\t}\n\n\t\tbigVal, ok := new(big.Int).SetString(p, 0)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"invalid path\")\n\t\t}\n\t\tval.Add(val, bigVal)\n\n\t\t// TODO, limit to uint32\n\t\tif !val.IsUint64() {\n\t\t\treturn nil, fmt.Errorf(\"bad\")\n\t\t}\n\t\tresult = append(result, uint32(val.Uint64()))\n\t}\n\n\treturn &result, nil\n}\n\nfunc NewWalletFromMnemonic(mnemonic string) (*Key, error) {\n\tseed, err := bip39.NewSeedWithErrorChecking(mnemonic, \"\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tmasterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpriv, err := DefaultDerivationPath.Derive(masterKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewKey(priv)\n}\n"
  },
  {
    "path": "wallet/wallet_hd_test.go",
    "content": "package wallet\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWallet_Mnemonic(t *testing.T) {\n\t_, err := NewWalletFromMnemonic(\"sound practice disease erupt basket pumpkin truck file gorilla behave find exchange napkin boy congress address city net prosper crop chair marine chase seven\")\n\tassert.NoError(t, err)\n}\n\nfunc TestWallet_MnemonicDerivationPath(t *testing.T) {\n\tcases := []struct {\n\t\tpath       string\n\t\tderivation DerivationPath\n\t}{\n\t\t{\"m/44'/60'/0'/0\", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}},\n\t\t{\"m/44'/60'/0'/128\", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 128}},\n\t}\n\n\tfor _, c := range cases {\n\t\tpath, err := parseDerivationPath(c.path)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, *path, c.derivation)\n\t}\n}\n"
  },
  {
    "path": "wallet/wallet_json.go",
    "content": "package wallet\n\nimport (\n\t\"io/ioutil\"\n\n\t\"github.com/umbracle/ethgo/keystore\"\n)\n\nfunc NewJSONWalletFromFile(path string, password string) (*Key, error) {\n\tdata, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewJSONWalletFromContent(data, password)\n}\n\nfunc NewJSONWalletFromContent(content []byte, password string) (*Key, error) {\n\tdst, err := keystore.DecryptV3(content, password)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tkey, err := NewWalletFromPrivKey(dst)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn key, nil\n}\n"
  },
  {
    "path": "wallet/wallet_json_test.go",
    "content": "package wallet\n\nimport (\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWallet_JSON(t *testing.T) {\n\traw, err := ioutil.ReadFile(\"./fixtures/wallet_json.json\")\n\tassert.NoError(t, err)\n\n\tvar cases []struct {\n\t\tWallet   json.RawMessage\n\t\tPassword string\n\t\tAddress  string\n\t}\n\tassert.NoError(t, json.Unmarshal(raw, &cases))\n\n\tfor _, c := range cases {\n\t\tkey, err := NewJSONWalletFromContent(c.Wallet, c.Password)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, key.Address().String(), c.Address)\n\t}\n}\n"
  },
  {
    "path": "wallet/wallet_priv.go",
    "content": "package wallet\n\nimport (\n\t\"crypto/ecdsa\"\n\n\t\"github.com/btcsuite/btcd/btcec/v2\"\n)\n\nfunc ParsePrivateKey(buf []byte) (*ecdsa.PrivateKey, error) {\n\tprv, _ := btcec.PrivKeyFromBytes(buf)\n\treturn prv.ToECDSA(), nil\n}\n\nfunc NewWalletFromPrivKey(p []byte) (*Key, error) {\n\tpriv, err := ParsePrivateKey(p)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn NewKey(priv)\n}\n"
  },
  {
    "path": "wallet/wallet_priv_test.go",
    "content": "package wallet\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWallet_Priv(t *testing.T) {\n\tkey, err := GenerateKey()\n\tassert.NoError(t, err)\n\n\traw, err := key.MarshallPrivateKey()\n\tassert.NoError(t, err)\n\n\tkey1, err := NewWalletFromPrivKey(raw)\n\tassert.NoError(t, err)\n\n\tassert.Equal(t, key.addr, key1.addr)\n}\n"
  },
  {
    "path": "website/README.md",
    "content": "\n# Website\n\n## Usage\n\n```\n$ npm install\n$ npm run dev\n```\n"
  },
  {
    "path": "website/components/eip.jsx",
    "content": "\nimport Link from 'next/link'\n\nexport default function EIPLink({children, num}) {\n    return <Link href={`https://github.com/ethereum/EIPs/blob/master/EIPS/eip-${num}.md`}>{children}</Link>\n}\n"
  },
  {
    "path": "website/components/godoc.jsx",
    "content": "\nimport Link from 'next/link'\n\nconst goDocRef = \"https://pkg.go.dev/github.com/umbracle/ethgo/\"\n\nexport default function GodocLink({children, href}) {\n    return <Link href={`${goDocRef}${href}`}>{children}</Link>\n}\n"
  },
  {
    "path": "website/components/primitives.jsx",
    "content": "\nimport Link from 'next/link'\nimport GodocLink from \"./godoc\"\n\nfunction Address({text='Address'}) {\n    return <GodocLink href='#Address'>{`(${text})`}</GodocLink>\n}\n\nfunction Hash({text='Hash'}) {\n    return <GodocLink href='#Hash'>{`(${text})`}</GodocLink>\n}\n\nfunction Block() {\n    return <GodocLink href='#Block'>{'(Block)'}</GodocLink>\n}\n\nfunction Blocktag() {\n    return <Link href={'/jsonrpc#block-tag'}>{'(BlockTag)'}</Link>\n}\n\nfunction ABI() {\n    return <Link href={'/abi'}>{'(ABI)'}</Link>\n}\n\nfunction Transaction() {\n    return <GodocLink href='#Transaction'>{'(Transaction)'}</GodocLink>\n}\n\nfunction Receipt() {\n    return <GodocLink href='#Receipt'>{'(Receipt)'}</GodocLink>\n}\n\nfunction LogFilter() {\n    return <GodocLink href='#LogFilter'>{'(LogFilter)'}</GodocLink>\n}\n\nfunction Log({text='Log'}) {\n    return <GodocLink href='#Log'>{`(${text})`}</GodocLink>\n}\n\nexport {\n    Address,\n    Hash,\n    Block,\n    Blocktag,\n    Transaction,\n    Receipt,\n    ABI,\n    Log,\n    LogFilter,\n}\n"
  },
  {
    "path": "website/next.config.js",
    "content": "// next.config.js\nconst withNextra = require('nextra')({\n    theme: 'nextra-theme-docs',\n    themeConfig: './theme.config.js',\n})\nmodule.exports = withNextra()"
  },
  {
    "path": "website/package.json",
    "content": "{\n  \"dependencies\": {\n    \"next\": \"^12.0.9\",\n    \"nextra\": \"^2.0.0-alpha.23\",\n    \"nextra-theme-docs\": \"^2.0.0-alpha.23\",\n    \"prism-react-renderer\": \"^1.2.1\",\n    \"prismjs\": \"^1.26.0\",\n    \"react\": \"^17.0.2\",\n    \"react-dom\": \"^17.0.2\"\n  },\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\",\n    \"start\": \"next start\"\n  }\n}\n"
  },
  {
    "path": "website/pages/_app.js",
    "content": "import 'nextra-theme-docs/style.css'\n\nimport Prism from 'prism-react-renderer/prism'\n(typeof global !== \"undefined\" ? global : window).Prism = Prism\nrequire(\"prismjs/components/prism-go\")\n\nimport Head from 'next/head';\n\nconst prod = process.env.NODE_ENV === 'production'\n\nexport default function Nextra({ Component, pageProps }) {\n  return (\n    <>\n      <Head>\n        {prod &&\n          <script defer data-domain=\"ethgoproject.io\" src=\"https://plausible.io/js/script.js\"></script>\n        }\n      </Head>\n      <Component {...pageProps} />\n    </>\n  )\n}\n"
  },
  {
    "path": "website/pages/abi.mdx",
    "content": "\n# Application Binary interface\n\nTo use the library import:\n\n```go\n\"github.com/umbracle/ethgo/abi\"\n```\n\nDeclare basic objects:\n\n```go\ntyp, err := abi.NewType(\"uint256\")\n```\n\nor \n\n```go\ntyp = abi.MustNewType(\"uint256\")\n```\n\nand use it to encode/decode the data:\n\n```go\nnum := big.NewInt(1)\n\nencoded, err := typ.Encode(num)\nif err != nil {\n    panic(err)\n}\n\ndecoded, err := typ.Decode(encoded) // decoded as interface\nif err != nil {\n    panic(err)\n}\n\nnum2 := decoded.(*big.Int)\nfmt.Println(num.Cmp(num2) == 0) // num == num2\n```\n\nYou can also codify structs as Solidity tuples:\n\n```go\nimport (\n\t\"fmt\"\n    \n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"math/big\"\n)\n\nfunc main() {\n\ttyp := abi.MustNewType(\"tuple(address a, uint256 b)\")\n\n\ttype Obj struct {\n\t\tA ethgo.Address\n\t\tB *big.Int\n\t}\n\tobj := &Obj{\n\t\tA: ethgo.Address{0x1},\n\t\tB: big.NewInt(1),\n\t}\n\n\t// Encode\n\tencoded, err := typ.Encode(obj)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Decode output into a map\n\tres, err := typ.Decode(encoded)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Decode into a struct\n\tvar obj2 Obj\n\tif err := typ.DecodeStruct(encoded, &obj2); err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res)\n\tfmt.Println(obj)\n}\n```\n\n## Testing\n\nThe ABI codifier uses randomized tests with e2e integration tests with a real Geth client to ensure that the codification is correct and provides the same results as the AbiEncoder from Solidity. \n"
  },
  {
    "path": "website/pages/cli/4byte.mdx",
    "content": "\n# 4byte\n\nThe `4byte` command resolve a function or event bytes signature to its full name using the [4byte](https://www.4byte.directory/) API.\n\n## Usage\n\n```shell\n$ ethgo 4byte 0xddf252ad\n```"
  },
  {
    "path": "website/pages/cli/abigen.mdx",
    "content": "\n# Abigen\n\nThe `abigen` command generates bindings to interact with smart contracts using Go. It requires as input the ABI specification of the smart contract in JSON format.\n\n## Usage\n\n```shell\n$ ethgo abigen --source ./erc20.json --package erc20\n```\n\n## Options\n\n- `source`: Path of the ABI contract file.\n- `package`: Name of the Go package.\n- `output`: Output directory. It defaults to the current location.\n\n## Output\n\nIt generates two output files.\n\n- `[name].go`: It contains the bindings for the contract.\n- `[name]_artifacts.go`. It contains the artifacts for the contract (ABI and deploy binary).\n"
  },
  {
    "path": "website/pages/cli/ens_resolve.mdx",
    "content": "\n# Ens resolve\n\nThe `ens resolve <name>` command resolves an ENS name to its Ethereum address.\n\n## Usage\n\n```shell\n$ ethgo ens resolve umbracle.eth [--provider https://mainnet.infura.io...]\n```\n\n## Options\n\n- `provider`: URL of the JSON-RPC endpoint to resolve queries (default=`http://localhost:8545`). It can also be set with the `JSONRPC_PROVIDER` environment variable.\n"
  },
  {
    "path": "website/pages/cli/meta.json",
    "content": "{\n    \"abigen\": \"Abigen\",\n    \"version\": \"Version\",\n    \"ens_resolve\": \"Ens Resolve\"\n}"
  },
  {
    "path": "website/pages/cli/version.mdx",
    "content": "\n# Version\n\nThe `version` command outputs the version of the Ethgo binary.\n\n## Usage\n\n```shell\n$ ethgo version\n```\n"
  },
  {
    "path": "website/pages/contract.mdx",
    "content": "\nimport GoDocLink from '../components/godoc'\nimport EIPLink from '../components/eip'\nimport {Address, ABI} from '../components/primitives'\n\n# Contract\n\nThe <GoDocLink href=\"contract#Contract\">Contract</GoDocLink> struct represents a deployed Solidity contract.\n\nTo instantiate a `Contract` object use:\n\n```go\ncontract.NewContract(addr, abi)\n```\n\nwith:\n\n- `addr` <Address/>: Address of the contract.\n- `abi` <ABI/>: ABI of the contract.\n\nBy default, it connects to the `https://localhost:8545` JsonRPC endpoint.\n\n## Options\n\nBesides `addr` and `abi`, you can use the option pattern to parametrize the contract, the available options are:\n\n- <GoDocLink href=\"contract#WithJsonRPCEndpoint\">WithJsonRPCEndpoint</GoDocLink>: JsonRPC url of the endpoint to connect with.\n- <GoDocLink href=\"contract#WithJsonRPCClient\">WithJsonRPCClient</GoDocLink>: [`JsonRPC`](/jsonrpc) object to make rpc calls. It takes preference over an address from `WithAddress`.\n- <GoDocLink href=\"contract#WithSigner\">WithSigner</GoDocLink>: [`Signer`](/signers/signer) object to send transactions or use a custom `from` address.\n- <GoDocLink href=\"contract#WithProvider\">WithProvider</GoDocLink>: Custom <GoDocLink href=\"contract#NodeProvider\">NodeProvider</GoDocLink> implementation to resolve calls and transactions.\n- <GoDocLink href=\"contract#WithEIP1559\">WithEIP1559</GoDocLink>: Send transactions with EIP-1559 pricing.\n\n## Examples\n\nCheck [examples](https://github.com/umbracle/ethgo/tree/master/examples) for a list of examples on how to interact with a smart contract.\n\n### Call a contract\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nfunc handleErr(err error) {\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// call a contract\nfunc main() {\n\tvar functions = []string{\n\t\t\"function totalSupply() view returns (uint256)\",\n\t}\n\n\tabiContract, err := abi.NewABIFromList(functions)\n\thandleErr(err)\n\n\t// Matic token\n\taddr := ethgo.HexToAddress(\"0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0\")\n\n\tclient, err := jsonrpc.NewClient(\"https://mainnet.infura.io\")\n\thandleErr(err)\n\n\tc := contract.NewContract(addr, abiContract, contract.WithJsonRPC(client.Eth()))\n\tres, err := c.Call(\"totalSupply\", ethgo.Latest)\n\thandleErr(err)\n\n\tfmt.Printf(\"TotalSupply: %s\", res[\"totalSupply\"].(*big.Int))\n}\n```\n\n## Abigen\n\nOne small limitation of `Contract` is that works with `interface` objects since the input and outputs of a smart contract are arbitrary. As an alternative, you can use [Abigen](./cli/abigen) to generate Go bindings that wrap the `Contract` object and provide native and typed Go functions to interact with the contracts.\n\nBy default, `ethgo` includes builtin `abigen` contracts for `ens` and `erc20` tokens.\n"
  },
  {
    "path": "website/pages/index.mdx",
    "content": "\n# Introduction\n\n`Ethgo` is a lightweight SDK in Go to interact with Ethereum compatible blockchains.\n"
  },
  {
    "path": "website/pages/integrations/4byte.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\n\n# 4Byte\n\n[4Byte](https://www.4byte.directory/) is a public directory that indexes signatures for Ethereum functions and events.\n\nRun <GoDocLink href=\"4byte#Resolve\">Resolve</GoDocLink> to resolve a signature in string format to its name:\n\n```go\npackage main\n\nimport (\n    fourbyte \"github.com/umbracle/ethgo/4byte\"\n)\n\nfunc main() {\n    found, err := fourbyte.Resolve(\"0xddf252ad\")\n    if err != nil {\n        panic(err)\n    }\n    // Transfer(address,address,uint256)\n}\n```\n"
  },
  {
    "path": "website/pages/integrations/ens.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../../components/primitives'\n\n# Ethereum Name Service (ENS)\n\nThe Ethereum Name Service ([ENS](https://ens.domains/)) is a distributed, open, and extensible naming system based on the Ethereum blockchain.\n\nThe <GoDocLink href=\"ens#ENS\">ENS</GoDocLink> object on the `ens` package is a module that abstracts the interaction with the ENS registry.\n\n```go\npackage main\n\nimport (\n    \"github.com/umbracle/ethgo/ens\"\n)\n\nfunc main() {\n\tensMod, err := ens.NewENS(ens.WithAddress(\"https://mainnet.infura.io\"))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n```\n\nIt will default to `0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e` as the address for the ENS registry when connecting with one of the official Ethereum networks. However, this can be parametrized at creation time. This module also requires a JsonRPC connection to make the calls to the ENS registry contract.\n\n## Options\n\n- <GoDocLink href=\"ens#WithAddress\">WithAddress</GoDocLink>: JsonRPC url of the endpoint to connect with.\n- <GoDocLink href=\"ens#WithClient\">WithClient</GoDocLink>: [`JsonRPC`](/jsonrpc) object to make rpc calls. It takes preference over an address from `WithAddress`.\n- <GoDocLink href=\"ens#WithResolver\">WithResolver</GoDocLink>: Custom resolver address to use rather than the default one.\n\n## Resolve\n\n<GoDocLink href=\"ens#ENS.Resolve\">Resolve</GoDocLink> resolves an ENS name to its registered address.\n\n```go\nensMod.Resolve(\"umbracle.eth\")\n```\n\nInput:\n\n- `name` (string): ENS name to resolve.\n\nOutput:\n\n- `address` <Address/>: Ethereum address that resolves to the input name.\n"
  },
  {
    "path": "website/pages/integrations/etherscan.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\nimport {Log, Address, Hash, Blocktag, Block, Transaction, Receipt, LogFilter} from '../../components/primitives'\n\n# Etherscan\n\n[Etherscan](https://etherscan.io/) is a block explorer and it implements some read compatible endpoint with the [JsonRPC](/jsonrpc) spec. It requires an [apiKey](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics) to use the service and not be rate limited.\n\nCreate an instance of Etherscan from a network id:\n\n```go\npackage main\n\nimport (\n    \"github.com/umbracle/ethgo/etherscan\"\n    \"github.com/umbracle/ethgo\"\n)\n\nfunc main() {\n    ethscan, err := etherscan.NewEtherscanFromNetwork(ethgo.Mainnet, \"apiKey\")\n}\n```\n\nThe package will resolve the name of the network to the specific endpoint in Etherscan, at this point it only works for `Mainnet`, `Ropsten`, `Rinkeby` and `Goerli`.\n\nFor a custom url use:\n\n```go\nethscan, err := etherscan.NewEtherscan(\"https://api.polygonscan.com\", \"apiKey\")\n```\n\n## BlockNumber\n\n<GoDocLink href=\"etherscan#Etherscan.BlockNumber\">BlockNumber</GoDocLink> returns the current block number.\n\n```go\nnum, err := ethscan.BlockNumber()\n```\n\nOutput\n\n- `num` (`uint64`): Last block number.\n\n## GetBlockByNumber\n\n<GoDocLink href=\"etherscan#Etherscan.GetBlockByNumber\">GetBlockByNumber</GoDocLink> returns a specific block by its number.\n\n```go\nblock, err := ethscan.GetBlockByNumber(ethgo.BlockNumber(100), true)\n```\n\nInput:\n\n- `block number` <Blocktag/>: Block number selection\n- `full` (`bool`): Whether to return the full block with transactions.\n\nOutput:\n\n- `block`: (): Block object\n\n## GetContractCode\n\n<GoDocLink href=\"etherscan#Etherscan.GetContractCode\">GetContractCode</GoDocLink> returns the contract of a given address (if any).\n\n```go\ncode, err := ethscan.GetContractCode(address)\n```\n\nInput:\n\n- `address` <Address/>: Address of the contract.\n\nOutput:\n\n- `code` (`[]byte`): Code of the contract.\n\n## GetLogs\n\n<GoDocLink href=\"etherscan#Etherscan.GetLogs\">GetLogs</GoDocLink> returns the logs given a log filter.\n\n```go\nfilter := &ethgo.LogFilter{\n    Address: []ethgo.Address{\n        ethgo.HexToAddress(\"...\"),\n    },\n}\nlogs, err := ethscan.GetLogs(filter)\n```\n\nInput:\n\n- `filter` <LogFilter/>: Filter for the logs to return.\n\nOutput:\n\n- `logs` <Log text=\"[]Log\"/>: List of logs that match the filter.\n\n## GasPrice\n\n<GoDocLink href=\"etherscan#Etherscan.GasPrice\">GasPrice</GoDocLink> returns the gas price of the latest block.\n\nOutput:\n\n- `gasPrice` (`uint64`): Gas price of the latest block.\n"
  },
  {
    "path": "website/pages/integrations/meta.json",
    "content": "{\n    \"ens\": \"Ethereum Name Service\",\n    \"etherscan\": \"Etherscan\"\n}"
  },
  {
    "path": "website/pages/jsonrpc/eth.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../../components/primitives'\n\n# Ethereum\n\n## GetCode\n\n<GoDocLink href=\"jsonrpc#Eth.GetCode\">GetCode</GoDocLink> returns code at a given address.\n\n```go\ncode, err := client.Eth().GetCode(address, block)\n```\n\n<b>Params</b>:\n\n- `address` <Address/>: Address of the contract to query.\n- `block` <Blocktag/>: Block reference to query the data.\n\n<b>Output</b>:\n\n- `code` `([]byte)`: Bytecode of the contract.\n\n## Accounts\n\n<GoDocLink href=\"jsonrpc#Eth.Accounts\">Accounts</GoDocLink> returns a list of addresses owned by client. This endpoint is not enabled in infrastructure providers.\n\n```go\naccounts, err := client.Eth().Accounts()\n```\n\n<b>Output</b>:\n\n- `accounts` <Address text=\"[]Address\"/>: List of addresses registered in the client. \n\n## GetStorageAt\n\n<GoDocLink href=\"jsonrpc#Eth.GetStorageAt\">GetStorageAt</GoDocLink> returns the value from a storage position at a given address.\n\n```go\nstorage, err := client.Eth().GetStorageAt(addr, slot, block)\n```\n\n<b>Params</b>:\n\n- `addr` <Address />: Address to query.\n- `slot` <Hash />: Slot storage for the address.\n- `block` <Blocktag/>: Block reference to query the data.\n\n<b>Output</b>:\n\n- `storage` `([]byte)`: Content of the storage.\n\n## BlockNumber\n\n<GoDocLink href=\"jsonrpc#Eth.BlockNumber\">BlockNumber</GoDocLink> returns the number of most recent block. \n\n```go\nnumber, err := client.Eth().BlockNumber()\n```\n\n<b>Output</b>:\n\n- `number` (`uint`): Number of the most recent block.\n\n## GetBlockByNumber\n\n<GoDocLink href=\"jsonrpc#Eth.GetBlockByNumber\">GetBlockByNumber</GoDocLink> returns information about a block by block number. \n\n```go\nblock, err := client.Eth().GetBlockByNumber(num, full)\n```\n\n<b>Params</b>:\n\n- `number` (`uint`): Number of the block to query.\n- `full` (`bool`): Whether the ouput block should include transactions.\n\n<b>Output</b>:\n\n- `block` <Block/>: Block queried.\n\n## GetBlockByHash\n\n<GoDocLink href=\"jsonrpc#Eth.GetBlockByHash\">GetBlockByHash</GoDocLink> returns information about a block by hash. \n\n```go\nblock, err := client.Eth().GetBlockByHash(hash, full)\n```\n\n<b>Params</b>:\n\n- `hash` <Hash />: Hash of the block to query.\n- `full` (`bool`): Whether the ouput block should include transactions.\n\n<b>Output</b>:\n\n- `block` <Block/>: Block queried.\n\n## GetTransactionByHash\n\n<GoDocLink href=\"jsonrpc#Eth.GetTransactionByHash\">GetTransactionByHash</GoDocLink> returns a transaction by his hash  \n\n```go\ntransaction, err := client.Eth().GetTransactionByHash(hash)\n```\n\n<b>Params</b>:\n\n- `hash` <Hash />: Hash of the transaction to query.\n\n<b>Output</b>:\n\n- `transaction` <Transaction/>: Transaction being queried.\n\n## SendRawTransaction\n\n<GoDocLink href=\"jsonrpc#Eth.SendRawTransaction\">SendRawTransaction</GoDocLink> creates new message call transaction or a contract creation for signed transactions.\n\n```go\nhash, err := client.Eth().SendRawTransaction(transaction)\n```\n\n<b>Params</b>:\n\n- `transaction` `([]byte)`: Signed transaction and encoded in RLP format.\n\n<b>Output</b>:\n\n- `hash` <Hash/>: Hash of the transaction created.\n\n## GetTransactionReceipt\n\n<GoDocLink href=\"jsonrpc#Eth.GetTransactionReceipt\">GetTransactionReceipt</GoDocLink> returns the receipt of a transaction by transaction hash.\n\n```go\nreceipt, err := client.Eth().GetTransactionReceipt(hash)\n```\n\n<b>Params</b>:\n\n- `hash` <Hash/>: Hash of the transaction being queried.\n\n<b>Output</b>:\n\n- `receipt` <Receipt/>: receipt being queried.\n\n## GetNonce\n\n<GoDocLink href=\"jsonrpc#Eth.GetNonce\">GetNonce</GoDocLink> returns the number of transactions sent from an address.\n\n```go\nnonce, err := client.Eth().GetNonce(address)\n```\n\n<b>Params</b>:\n\n- `address` <Address/>: address of the account to query.\n\n<b>Output</b>:\n\n- `nonce` `(uint64)`: next valid nonce for the account.\n\n## GetBalance \n\n<GoDocLink href=\"jsonrpc#Eth.GetBalance\">GetBalance</GoDocLink> returns the balance of the account of given address.\n\n```go\nbalance, err := client.Eth().GetBalance(address)\n```\n\n<b>Params</b>:\n\n- `address` <Address/>: address of the account to query.\n\n<b>Output</b>:\n\n- `balance` `(big.Int)`: balance of the account in big format.\n\n## GasPrice\n\n<GoDocLink href=\"jsonrpc#Eth.GasPrice\">GasPrice</GoDocLink> returns the current price per gas in wei.\n\n```go\nprice, err := client.Eth().GasPrice()\n```\n\n<b>Output</b>:\n\n- `price` `(big.Int)`: gas price in wei.\n"
  },
  {
    "path": "website/pages/jsonrpc/index.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../../components/primitives'\n\n# JsonRPC\n\nEthereum uses `JsonRPC` as the main interface to interact with the client and the network.\n\n## Overview\n\n```go\npackage main\n\nimport (\n\t\"github.com/umbracle/ethgo/jsonrpc\"\n)\n\nfunc main() {\n\tclient, err := jsonrpc.NewClient(\"https://mainnet.infura.io\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n```\n\n`Ethgo` supports different transport protocols besides `http` depending on the endpoint:\n\nUse the endpoint with `wss://` prefix to connect with [`websockets`](https://en.wikipedia.org/wiki/WebSocket):\n\n```go\nclient, err := jsonrpc.NewClient(\"wss://mainnet.infura.io\")\n```\n\nor the endpoint with `ipc://` prefix to use [`ipc`](https://en.wikipedia.org/wiki/Inter-process_communication):\n\n```go\nclient, err := jsonrpc.NewClient(\"ipc://path/geth.ipc\")\n```\n\n## Endpoints\n\nOnce the JsonRPC client has been created, the endpoints are available on different namespaces following the spec:\n\n```go\neth := client.Eth()\n```\n\nThe available namespaces are:\n\n- [Eth](./jsonrpc/eth): Ethereum network endpoints.\n- [Net](./jsonrpc/net): Client information.\n\n## Block tag\n\nSome endpoints of the `eth` namespace can be queried at a specific block. There exists three ways to specify this block:\n\n- `number` or `tag` <GoDocLink href=\"#BlockNumber\">(BlockNumber)</GoDocLink>: integer block number or the tag `latest`, `pending` or `earliest`.\n\n- `hash` <Hash/>: hash of the block.\n"
  },
  {
    "path": "website/pages/jsonrpc/meta.json",
    "content": "{\n    \"index\": \"Overview\",\n    \"eth\": \"Eth\",\n    \"net\": \"Net\"\n}"
  },
  {
    "path": "website/pages/jsonrpc/net.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../../components/primitives'\n\n# Net\n\n## PeerCount\n\n<GoDocLink href=\"jsonrpc#Net.PeerCount\">PeerCount</GoDocLink> returns number of peers currently connected to the client.\n\n```go\ncount, err := client.Net().PeerCount()\n```\n\n<b>Output</b>:\n\n- `count` `(uint64)`: Number of peers connected.\n"
  },
  {
    "path": "website/pages/meta.json",
    "content": "{\n    \"index\": \"Introduction\",\n    \"jsonrpc\": \"JsonRPC\",\n    \"abi\": \"Application Binary Interface\",\n    \"signers\": \"Signers\",\n    \"contract\": \"Contract\",\n    \"integrations\": \"Integrations\",\n    \"cli\": \"Command Line Interface\"\n}"
  },
  {
    "path": "website/pages/signers/signer.mdx",
    "content": "\n# Signers\n\nThe `Signer` represents an abstract entity that can sign arbitrary messages.\n\n```go\ntype Key interface {\n\tAddress() Address\n\tSign(hash []byte) ([]byte, error)\n}\n```\n"
  },
  {
    "path": "website/pages/signers/wallet.mdx",
    "content": "\nimport GoDocLink from '../../components/godoc'\n\n# Wallet\n\nThe `wallet` package is an implementation of the [Signer](./signer) interface for an ECDSA private key and it represents an Ethereum account. It supports loading the private key from different mediums.\n\n## Random\n\nCreate a random key:\n\n```go\nkey, err := wallet.GenerateKey()\n```\n\n## Mnemonic\n\nCreate the key from a mnemonic phrase:\n\n```go\nmnemonic := \"\"\nkey, err := wallet.NewWalletFromMnemonic(mnemonic)\n```\n\n## PrivateKey\n\nCreate the key from a private key (in bytes):\n\n```go\nkey, err := wallet.NewWalletFromPrivKey([]byte{})\n```\n\n## Hardware file\n\nCreate the key from an encrypted JSON wallet following the [keystore](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) format.\n\n```go\nkey, err := wallet.NewJSONWalletFromFile(\"./file.json\")\n```\n"
  },
  {
    "path": "website/theme.config.js",
    "content": "export default {\n    projectLink: 'https://github.com/umbracle/ethgo', // GitHub link in the navbar\n    docsRepositoryBase: 'https://github.com/umbracle/ethgo/tree/master/website/pages', // base URL for the docs repository\n    titleSuffix: ' – Ethgo',\n    nextLinks: true,\n    prevLinks: true,\n    search: false,\n    customSearch: null, // customizable, you can use algolia for example\n    darkMode: true,\n    footer: true,\n    footerText: (\n      <>\n        Powered by <a href=\"https://umbracle.io\">Umbracle</a>\n      </>\n    ),\n    footerEditLink: `Edit this page on GitHub`,\n    floatTOC: true,\n    logo: (\n        <>\n          <span className=\"mr-2 font-extrabold hidden md:inline\">Ethgo</span>\n          <span className=\"text-gray-600 font-normal hidden md:inline\">\n            Go Ethereum SDK\n          </span>\n        </>\n    ),\n    head: (\n        <>\n            <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n            <meta name=\"description\" content=\"Ethgo: lightweight Go Ethereum SDK\" />\n            <meta name=\"og:title\" content=\"Ethgo: lightweight Go Ethereum SDK\" />\n        </>\n    ),\n}"
  }
]