This commit is contained in:
Christoc90 2026-02-28 18:46:32 +00:00 committed by GitHub
commit e72a63904b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2367 changed files with 527584 additions and 301704 deletions

View file

@ -0,0 +1,27 @@
on:
workflow_dispatch:
### Note we cannot use cron-triggered builds right now, Gitea seems to have
### a few bugs in that area. So this workflow is scheduled using an external
### triggering mechanism and workflow_dispatch.
#
# schedule:
# - cron: '0 15 * * *'
jobs:
azure-cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Run cleanup script
run: |
go run build/ci.go purge -store gethstore/builds -days 14
env:
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}

View file

@ -0,0 +1,46 @@
on:
push:
tags:
- "v*"
workflow_dispatch:
### Note we cannot use cron-triggered builds right now, Gitea seems to have
### a few bugs in that area. So this workflow is scheduled using an external
### triggering mechanism and workflow_dispatch.
#
# schedule:
# - cron: '0 16 * * *'
jobs:
ppa:
name: PPA Upload
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Show environment
run: |
env
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install deb toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot
- name: Add launchpad to known_hosts
run: |
echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
- name: Run ci.go
run: |
go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
env:
PPA_SIGNING_KEY: ${{ secrets.PPA_SIGNING_KEY }}
PPA_SSH_KEY: ${{ secrets.PPA_SSH_KEY }}

View file

@ -0,0 +1,200 @@
on:
push:
branches:
- "master"
tags:
- "v*"
workflow_dispatch:
jobs:
linux-intel:
name: Linux Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install cross toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
- name: Build (amd64)
run: |
go run build/ci.go install -static -arch amd64 -dlgo
- name: Create/upload archive (amd64)
run: |
go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -f build/bin/*
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Build (386)
run: |
go run build/ci.go install -static -arch 386 -dlgo
- name: Create/upload archive (386)
run: |
go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -f build/bin/*
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
linux-arm:
name: Linux Build (arm)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install cross toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
ln -s /usr/include/asm-generic /usr/include/asm
- name: Build (arm64)
run: |
go run build/ci.go install -static -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- name: Create/upload archive (arm64)
run: |
go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -fr build/bin/*
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Run build (arm5)
run: |
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
env:
GOARM: "5"
- name: Create/upload archive (arm5)
run: |
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
env:
GOARM: "5"
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Run build (arm6)
run: |
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
env:
GOARM: "6"
- name: Create/upload archive (arm6)
run: |
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -fr build/bin/*
env:
GOARM: "6"
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Run build (arm7)
run: |
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
env:
GOARM: "7"
- name: Create/upload archive (arm7)
run: |
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -fr build/bin/*
env:
GOARM: "7"
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
keeper:
name: Keeper Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install cross toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
- name: Build (amd64)
run: |
go run build/ci.go keeper -dlgo
windows:
name: Windows Build
runs-on: "win-11"
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
# Note: gcc.exe only works properly if the corresponding bin/ directory is
# contained in PATH.
- name: "Build (amd64)"
shell: cmd
run: |
set PATH=%GETH_MINGW%\bin;%PATH%
go run build/ci.go install -dlgo -arch amd64 -cc %GETH_MINGW%\bin\gcc.exe
env:
GETH_MINGW: 'C:\msys64\mingw64'
- name: "Build (386)"
shell: cmd
run: |
set PATH=%GETH_MINGW%\bin;%PATH%
go run build/ci.go install -dlgo -arch 386 -cc %GETH_MINGW%\bin\gcc.exe
env:
GETH_MINGW: 'C:\msys64\mingw32'
docker:
name: Docker Image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Run docker build
env:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
run: |
go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 -upload

47
.github/CODEOWNERS vendored
View file

@ -1,22 +1,33 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
accounts/usbwallet @karalabe
accounts/scwallet @gballet
accounts/abi @gballet @MariusVanDerWijden
cmd/clef @holiman
cmd/puppeth @karalabe
consensus @karalabe
core/ @karalabe @holiman @rjl493456442
eth/ @karalabe @holiman @rjl493456442
graphql/ @gballet
les/ @zsfelfoldi @rjl493456442
light/ @zsfelfoldi @rjl493456442
mobile/ @karalabe @ligi
node/ @fjl @renaynay
accounts/usbwallet/ @gballet
accounts/scwallet/ @gballet
accounts/abi/ @gballet @MariusVanDerWijden
beacon/engine/ @MariusVanDerWijden @lightclient @fjl
beacon/light/ @zsfelfoldi
beacon/merkle/ @zsfelfoldi
beacon/types/ @zsfelfoldi @fjl
beacon/params/ @zsfelfoldi @fjl
cmd/evm/ @MariusVanDerWijden @lightclient
core/state/ @rjl493456442
crypto/ @gballet @jwasinger @fjl
core/ @rjl493456442
eth/ @rjl493456442
eth/catalyst/ @MariusVanDerWijden @lightclient @fjl @jwasinger
eth/tracers/ @s1na
ethclient/ @fjl
ethdb/ @rjl493456442
event/ @fjl
trie/ @rjl493456442 @gballet
triedb/ @rjl493456442
core/tracing/ @s1na
graphql/ @s1na
internal/ethapi/ @fjl @s1na @lightclient
internal/era/ @lightclient
miner/ @MariusVanDerWijden @fjl @rjl493456442
node/ @fjl
p2p/ @fjl @zsfelfoldi
rpc/ @fjl @holiman
p2p/simulations @fjl
p2p/protocols @fjl
p2p/testing @fjl
signer/ @holiman
rlp/ @fjl
params/ @fjl @gballet @rjl493456442 @zsfelfoldi
rpc/ @fjl

View file

@ -30,11 +30,11 @@ Please make sure your contributions adhere to our coding guidelines:
Before you submit a feature request, please check and make sure that it isn't
possible through some other means. The JavaScript-enabled console is a powerful
feature in the right hands. Please check our
[Wiki page](https://github.com/ethereum/go-ethereum/wiki) for more info
[Geth documentation page](https://geth.ethereum.org/docs/) for more info
and help.
## Configuration, dependencies, and tests
Please see the [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide)
for more details on configuring your environment, managing project dependencies
and testing procedures.

View file

@ -9,6 +9,7 @@ assignees: ''
#### System information
Geth version: `geth version`
CL client & version: e.g. lighthouse/nimbus/prysm@v1.0.0
OS & Version: Windows/Linux/OSX
Commit hash : (if `develop`)
@ -26,3 +27,5 @@ Commit hash : (if `develop`)
````
[backtrace]
````
When submitting logs: please submit them as text and not screenshots.

99
.github/workflows/go.yml vendored Normal file
View file

@ -0,0 +1,99 @@
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
jobs:
lint:
name: Lint
runs-on: [self-hosted-ghr, size-s-x64]
steps:
- uses: actions/checkout@v4
with:
submodules: false
# Cache build tools to avoid downloading them each time
- uses: actions/cache@v4
with:
path: build/cache
key: ${{ runner.os }}-build-tools-cache-${{ hashFiles('build/checksums.txt') }}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.25
cache: false
- name: Run linters
run: |
go run build/ci.go lint
go run build/ci.go check_generate
go run build/ci.go check_baddeps
keeper:
name: Keeper Builds
needs: test
runs-on: [self-hosted-ghr, size-l-x64]
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
cache: false
- name: Build
run: go run build/ci.go keeper
test-32bit:
name: "32bit tests"
needs: test
runs-on: [self-hosted-ghr, size-l-x64]
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
cache: false
- name: Install cross toolchain
run: |
sudo apt-get update
sudo apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
- name: Build
run: go run build/ci.go test -arch 386 -short -p 8
test:
name: Test
needs: lint
runs-on: [self-hosted-ghr, size-l-x64]
strategy:
matrix:
go:
- '1.25'
- '1.24'
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
cache: false
- name: Run tests
run: go run build/ci.go test -p 8

83
.github/workflows/validate_pr.yml vendored Normal file
View file

@ -0,0 +1,83 @@
name: PR Format Validation
on:
pull_request:
types: [opened, edited, synchronize]
jobs:
validate-pr:
runs-on: ubuntu-latest
steps:
- name: Check for Spam PR
uses: actions/github-script@v7
with:
script: |
const prTitle = context.payload.pull_request.title;
const spamRegex = /^(feat|chore|fix)(\(.*\))?\s*:/i;
if (spamRegex.test(prTitle)) {
// Leave a comment explaining why
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: `## PR Closed as Spam
This PR was automatically closed because the title format \`feat:\`, \`fix:\`, or \`chore:\` is commonly associated with spam contributions.
If this is a legitimate contribution, please:
1. Review our contribution guidelines
2. Use the correct PR title format: \`directory, ...: description\`
3. Open a new PR with the proper title format
Thank you for your understanding.`
});
// Close the PR
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
state: 'closed'
});
core.setFailed('PR closed as spam due to suspicious title format');
return;
}
console.log('✅ PR passed spam check');
- name: Checkout repository
uses: actions/checkout@v4
- name: Check PR Title Format
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const prTitle = context.payload.pull_request.title;
const titleRegex = /^([\w\s,{}/.]+): .+/;
if (!titleRegex.test(prTitle)) {
core.setFailed(`PR title "${prTitle}" does not match required format: directory, ...: description`);
return;
}
const match = prTitle.match(titleRegex);
const dirPart = match[1];
const directories = dirPart.split(',').map(d => d.trim());
const missingDirs = [];
for (const dir of directories) {
const fullPath = path.join(process.env.GITHUB_WORKSPACE, dir);
if (!fs.existsSync(fullPath)) {
missingDirs.push(dir);
}
}
if (missingDirs.length > 0) {
core.setFailed(`The following directories in the PR title do not exist: ${missingDirs.join(', ')}`);
return;
}
console.log('✅ PR title format is valid');

36
.gitignore vendored
View file

@ -4,16 +4,11 @@
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile ~/.gitignore_global
/tmp
*/**/*un~
*/**/*.test
*un~
.DS_Store
*/**/.DS_Store
.ethtest
*/**/*tx_database*
*/**/*dapps*
build/_vendor/pkg
#*
.#*
@ -28,22 +23,37 @@ build/_vendor/pkg
/build/bin/
/geth*.zip
# used by the build/ci.go archive + upload tool
/geth*.tar.gz
/geth*.tar.gz.sig
/geth*.tar.gz.asc
/geth*.zip.sig
/geth*.zip.asc
# travis
profile.tmp
profile.cov
# IdeaIDE
.idea
*.iml
# VS Code
.vscode
# dashboard
/dashboard/assets/flow-typed
/dashboard/assets/node_modules
/dashboard/assets/stats.json
/dashboard/assets/bundle.js
/dashboard/assets/bundle.js.map
/dashboard/assets/package-lock.json
tests/spec-tests/
**/yarn-error.log
# binaries
cmd/abidump/abidump
cmd/abigen/abigen
cmd/blsync/blsync
cmd/clef/clef
cmd/devp2p/devp2p
cmd/era/era
cmd/ethkey/ethkey
cmd/evm/evm
cmd/geth/geth
cmd/rlpdump/rlpdump
cmd/workload/workload
cmd/keeper/keeper

5
.gitmodules vendored
View file

@ -1,3 +1,8 @@
[submodule "tests"]
path = tests/testdata
url = https://github.com/ethereum/tests
shallow = true
[submodule "evm-benchmarks"]
path = tests/evm-benchmarks
url = https://github.com/ipsilon/evm-benchmarks
shallow = true

View file

@ -1,50 +1,96 @@
# This file configures github.com/golangci/golangci-lint.
version: '2'
run:
timeout: 3m
tests: true
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true
skip-files:
- core/genesis_alloc.go
linters:
disable-all: true
default: none
enable:
- deadcode
- goconst
- goimports
- gosimple
- bidichk
- copyloopvar
- durationcheck
- gocheckcompilerdirectives
- govet
- ineffassign
- mirror
- misspell
# - staticcheck
- reassign
- revive # only certain checks enabled
- staticcheck
- unconvert
# - unused
- varcheck
linters-settings:
gofmt:
simplify: true
goconst:
min-len: 3 # minimum length of string constant
min-occurrences: 6 # minimum number of occurrences
issues:
exclude-rules:
- path: crypto/blake2b/
linters:
- deadcode
- path: crypto/bn256/cloudflare
linters:
- deadcode
- path: p2p/discv5/
linters:
- deadcode
- path: core/vm/instructions_test.go
linters:
- goconst
- path: cmd/faucet/
linters:
- deadcode
- unused
- usetesting
- whitespace
### linters we tried and will not be using:
###
# - structcheck # lots of false positives
# - errcheck #lot of false positives
# - contextcheck
# - errchkjson # lots of false positives
# - errorlint # this check crashes
# - exhaustive # silly check
# - makezero # false positives
# - nilerr # several intentional
settings:
staticcheck:
checks:
# disable Quickfixes
- -QF1*
revive:
enable-all-rules: false
# here we enable specific useful rules
# see https://golangci-lint.run/usage/linters/#revive for supported rules
rules:
- name: receiver-naming
severity: warning
disabled: false
exclude:
- ''
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- deadcode
- staticcheck
path: crypto/bn256/cloudflare/optate.go
- linters:
- revive
path: crypto/bn256/
- path: cmd/utils/flags.go
text: "SA1019: cfg.TxLookupLimit is deprecated: use 'TransactionHistory' instead."
- path: cmd/utils/flags.go
text: "SA1019: ethconfig.Defaults.TxLookupLimit is deprecated: use 'TransactionHistory' instead."
- path: internal/build/pgp.go
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
- path: core/vm/contracts.go
text: 'SA1019: "golang.org/x/crypto/ripemd160" is deprecated: RIPEMD-160 is a legacy hash and should not be used for new applications.'
- path: (.+)\.go$
text: 'SA1019: event.TypeMux is deprecated: use Feed'
- path: (.+)\.go$
text: 'SA1019: strings.Title is deprecated'
- path: (.+)\.go$
text: 'SA1019: strings.Title has been deprecated since Go 1.18 and an alternative has been available since Go 1.0: The rule Title uses for word boundaries does not handle Unicode punctuation properly. Use golang.org/x/text/cases instead.'
- path: (.+)\.go$
text: 'SA1029: should not use built-in type string as key for value'
paths:
- core/genesis_alloc.go
- third_party$
- builtin$
- examples$
formatters:
enable:
- goimports
settings:
gofmt:
simplify: true
exclusions:
generated: lax
paths:
- core/genesis_alloc.go
- third_party$
- builtin$
- examples$

369
.mailmap
View file

@ -1,123 +1,312 @@
Jeffrey Wilcke <jeffrey@ethereum.org>
Jeffrey Wilcke <jeffrey@ethereum.org> <geffobscura@gmail.com>
Jeffrey Wilcke <jeffrey@ethereum.org> <obscuren@obscura.com>
Jeffrey Wilcke <jeffrey@ethereum.org> <obscuren@users.noreply.github.com>
Aaron Buchwald <aaron.buchwald56@gmail.com>
Viktor Trón <viktor.tron@gmail.com>
Aaron Kumavis <kumavis@users.noreply.github.com>
Joseph Goulden <joegoulden@gmail.com>
Abel Nieto <abel.nieto90@gmail.com>
Abel Nieto <abel.nieto90@gmail.com> <anietoro@uwaterloo.ca>
Nick Savers <nicksavers@gmail.com>
Adrian Sutton <adrian@oplabs.co>
Adrian Sutton <adrian@oplabs.co> <adrian@symphonious.net>
Maran Hidskes <maran.hidskes@gmail.com>
Afri Schoedon <58883403+q9f@users.noreply.github.com>
Afri Schoedon <5chdn@users.noreply.github.com> <58883403+q9f@users.noreply.github.com>
Taylor Gerring <taylor.gerring@gmail.com>
Taylor Gerring <taylor.gerring@gmail.com> <taylor.gerring@ethereum.org>
Alec Perseghin <aperseghin@gmail.com>
Aleksey Smyrnov <i@soar.name>
Alex Leverington <alex@ethdev.com>
Alex Leverington <alex@ethdev.com> <subtly@users.noreply.github.com>
Alex Pozhilenkov <alex_pozhilenkov@adoriasoft.com>
Alex Pozhilenkov <alex_pozhilenkov@adoriasoft.com> <leshiy12345678@gmail.com>
Alexey Akhunov <akhounov@gmail.com>
Alon Muroch <alonmuroch@gmail.com>
Andrei Silviu Dragnea <andreidragnea.dev@gmail.com>
Andrei Silviu Dragnea <andreidragnea.dev@gmail.com> <andreisilviudragnea@gmail.com>
Andrey Petrov <shazow@gmail.com>
Andrey Petrov <shazow@gmail.com> <andrey.petrov@shazow.net>
Arkadiy Paronyan <arkadiy@ethdev.com>
Armin Braun <me@obrown.io>
Aron Fischer <github@aron.guru> <homotopycolimit@users.noreply.github.com>
Austin Roberts <code@ausiv.com>
Austin Roberts <code@ausiv.com> <git@ausiv.com>
Bas van Kervel <bas@ethdev.com>
Bas van Kervel <bas@ethdev.com> <basvankervel@ziggo.nl>
Bas van Kervel <bas@ethdev.com> <basvankervel@gmail.com>
Bas van Kervel <bas@ethdev.com> <bas-vk@users.noreply.github.com>
Sven Ehlert <sven@ethdev.com>
Vitalik Buterin <v@buterin.com>
Marian Oancea <contact@siteshop.ro>
Christoph Jentzsch <jentzsch.software@gmail.com>
Heiko Hees <heiko@heiko.org>
Alex Leverington <alex@ethdev.com>
Alex Leverington <alex@ethdev.com> <subtly@users.noreply.github.com>
Zsolt Felföldi <zsfelfoldi@gmail.com>
Gavin Wood <i@gavwood.com>
Martin Becze <mjbecze@gmail.com>
Martin Becze <mjbecze@gmail.com> <wanderer@users.noreply.github.com>
Dimitry Khokhlov <winsvega@mail.ru>
Roman Mandeleil <roman.mandeleil@gmail.com>
Alec Perseghin <aperseghin@gmail.com>
Alon Muroch <alonmuroch@gmail.com>
Arkadiy Paronyan <arkadiy@ethdev.com>
Jae Kwon <jkwon.work@gmail.com>
Aaron Kumavis <kumavis@users.noreply.github.com>
Nick Dodson <silentcicero@outlook.com>
Jason Carver <jacarver@linkedin.com>
Jason Carver <jacarver@linkedin.com> <ut96caarrs@snkmail.com>
Joseph Chow <ethereum@outlook.com>
Joseph Chow <ethereum@outlook.com> ethers <TODO>
Enrique Fynn <enriquefynn@gmail.com>
Vincent G <caktux@gmail.com>
RJ Catalano <catalanor0220@gmail.com>
RJ Catalano <catalanor0220@gmail.com> <rj@erisindustries.com>
Nchinda Nchinda <nchinda2@gmail.com>
Aron Fischer <github@aron.guru> <homotopycolimit@users.noreply.github.com>
Vlad Gluhovsky <gluk256@users.noreply.github.com>
Ville Sundell <github@solarius.fi>
Elliot Shepherd <elliot@identitii.com>
Yohann Léon <sybiload@gmail.com>
Gregg Dourgarian <greggd@tempworks.com>
Boqin Qin <bobbqqin@bupt.edu.cn>
Boqin Qin <bobbqqin@bupt.edu.cn> <Bobbqqin@gmail.com>
Casey Detrio <cdetrio@gmail.com>
Jens Agerberg <github@agerberg.me>
Charlotte <tqpcharlie@proton.me>
Charlotte <tqpcharlie@proton.me> <Zachinquarantine@protonmail.com>
Charlotte <tqpcharlie@proton.me> <zachinquarantine@yahoo.com>
Nick Johnson <arachnid@notdot.net>
Cheng Li <lob4tt@gmail.com>
Henning Diedrich <hd@eonblast.com>
Henning Diedrich <hd@eonblast.com> Drake Burroughs <wildfyre@hotmail.com>
Chris Ziogas <ziogaschr@gmail.com>
Chris Ziogas <ziogaschr@gmail.com> <ziogas_chr@hotmail.com>
Christoph Jentzsch <jentzsch.software@gmail.com>
Daniel Liu <liudaniel@qq.com>
Daniel Liu <liudaniel@qq.com> <139250065@qq.com>
Diederik Loerakker <proto@protolambda.com>
Dimitry Khokhlov <winsvega@mail.ru>
Ha ĐANG <dvietha@gmail.com>
Domino Valdano <dominoplural@gmail.com>
Domino Valdano <dominoplural@gmail.com> <jeff@okcupid.com>
Edgar Aroutiounian <edgar.factorial@gmail.com>
Elliot Shepherd <elliot@identitii.com>
Enrique Fynn <enriquefynn@gmail.com>
Enrique Fynn <me@enriquefynn.com>
Enrique Fynn <me@enriquefynn.com> <enriquefynn@gmail.com>
Ernesto del Toro <ernesto.deltoro@gmail.com>
Ernesto del Toro <ernesto.deltoro@gmail.com> <ernestodeltoro@users.noreply.github.com>
Everton Fraga <ev@ethereum.org>
Felix Lange <fjl@twurst.com>
Felix Lange <fjl@twurst.com> <fjl@users.noreply.github.com>
Максим Чусовлянов <mchusovlianov@gmail.com>
Louis Holbrook <dev@holbrook.no>
Louis Holbrook <dev@holbrook.no> <nolash@users.noreply.github.com>
Thomas Bocek <tom@tomp2p.net>
Victor Tran <vu.tran54@gmail.com>
Justin Drake <drakefjustin@gmail.com>
Frank Wang <eternnoir@gmail.com>
Gary Rong <garyrong0905@gmail.com>
Gavin Wood <i@gavwood.com>
Gregg Dourgarian <greggd@tempworks.com>
guangwu <guoguangwu@magic-shield.com>
guangwu <guoguangwu@magic-shield.com> <guoguangwug@gmail.com>
Guillaume Ballet <gballet@gmail.com>
Guillaume Ballet <gballet@gmail.com> <3272758+gballet@users.noreply.github.com>
Guillaume Nicolas <guin56@gmail.com>
Hanjiang Yu <delacroix.yu@gmail.com>
Hanjiang Yu <delacroix.yu@gmail.com> <42531996+de1acr0ix@users.noreply.github.com>
Heiko Hees <heiko@heiko.org>
Henning Diedrich <hd@eonblast.com>
Henning Diedrich <hd@eonblast.com> Drake Burroughs <wildfyre@hotmail.com>
henridf <henri@dubfer.com>
henridf <henri@dubfer.com> <henridf@gmail.com>
Hwanjo Heo <34005989+hwanjo@users.noreply.github.com>
Ikko Eltociear Ashimine <eltociear@gmail.com>
Iskander (Alex) Sharipov <quasilyte@gmail.com>
Iskander (Alex) Sharipov <quasilyte@gmail.com> <i.sharipov@corp.vk.com>
Jae Kwon <jkwon.work@gmail.com>
James Prestwich <james@prestwi.ch>
James Prestwich <james@prestwi.ch> <10149425+prestwich@users.noreply.github.com>
Janoš Guljaš <janos@resenje.org> <janos@users.noreply.github.com>
Janoš Guljaš <janos@resenje.org> Janos Guljas <janos@resenje.org>
Jared Wasinger <j-wasinger@hotmail.com>
Jason Carver <jacarver@linkedin.com>
Jason Carver <jacarver@linkedin.com> <ut96caarrs@snkmail.com>
Javier Peletier <jm@epiclabs.io>
Javier Peletier <jm@epiclabs.io> <jpeletier@users.noreply.github.com>
Jeffrey Wilcke <jeffrey@ethereum.org>
Jeffrey Wilcke <jeffrey@ethereum.org> <geffobscura@gmail.com>
Jeffrey Wilcke <jeffrey@ethereum.org> <obscuren@obscura.com>
Jeffrey Wilcke <jeffrey@ethereum.org> <obscuren@users.noreply.github.com>
Jens Agerberg <github@agerberg.me>
Jeremy Schlatter <jeremy.schlatter@gmail.com>
Jeremy Schlatter <jeremy.schlatter@gmail.com> <jeremy@jeremyschlatter.com>
John Chase <68833933+joohhnnn@users.noreply.github.com>
Joseph Chow <ethereum@outlook.com>
Joseph Chow <ethereum@outlook.com> ethers <TODO>
Joseph Goulden <joegoulden@gmail.com>
Justin Drake <drakefjustin@gmail.com>
Karl Bartel <karl.bartel@clabs.co>
Karl Bartel <karl.bartel@clabs.co> <karl@karl.berlin>
Kenso Trabing <ktrabing@acm.org>
Kenso Trabing <ktrabing@acm.org> <kenso.trabing@bloomwebsite.com>
Liyi Guo <102356659+colinlyguo@users.noreply.github.com>
lmittmann <3458786+lmittmann@users.noreply.github.com>
lmittmann <3458786+lmittmann@users.noreply.github.com> <lmittmann@users.noreply.github.com>
Liang Ma <liangma@liangbit.com>
Liang Ma <liangma@liangbit.com> <liangma.ul@gmail.com>
Louis Holbrook <dev@holbrook.no>
Louis Holbrook <dev@holbrook.no> <nolash@users.noreply.github.com>
makcandrov <makcandrov@proton.me>
makcandrov <makcandrov@proton.me> <108467407+makcandrov@users.noreply.github.com>
Maran Hidskes <maran.hidskes@gmail.com>
Marian Oancea <contact@siteshop.ro>
Martin Becze <mjbecze@gmail.com>
Martin Becze <mjbecze@gmail.com> <wanderer@users.noreply.github.com>
Martin Holst Swende <martin@swende.se>
Martin Lundfall <martin.lundfall@protonmail.com>
Marius van der Wijden <m.vanderwijden@live.de>
Marius van der Wijden <m.vanderwijden@live.de> <115323661+vdwijden@users.noreply.github.com>
Matt Garnett <lightclient@protonmail.com>
Matt Garnett <lightclient@protonmail.com> <14004106+lightclient@users.noreply.github.com>
Matthew Halpern <matthalp@gmail.com>
Matthew Halpern <matthalp@gmail.com> <matthalp@google.com>
meowsbits <b5c6@protonmail.com>
meowsbits <b5c6@protonmail.com> <45600330+meowsbits@users.noreply.github.com>
Michael Riabzev <michael@starkware.co>
Michael de Hoog <michael.dehoog@gmail.com>
Michael de Hoog <michael.dehoog@gmail.com> <michael.dehoog@coinbase.com>
Nchinda Nchinda <nchinda2@gmail.com>
Nebojsa Urosevic <nebojsa94@users.noreply.github.com>
nedifi <103940716+nedifi@users.noreply.github.com>
Nick Dodson <silentcicero@outlook.com>
Nick Johnson <arachnid@notdot.net>
Nick Savers <nicksavers@gmail.com>
Nishant Das <nishdas93@gmail.com>
Nishant Das <nishdas93@gmail.com> <nish1993@hotmail.com>
Olivier Hervieu <olivier.hervieu@gmail.com>
Pascal Dierich <pascal@merkleplant.xyz>
Pascal Dierich <pascal@merkleplant.xyz> <pascal@pascaldierich.com>
Paweł Bylica <chfast@gmail.com>
Paweł Bylica <chfast@gmail.com> <pawel@ethereum.org>
RJ Catalano <catalanor0220@gmail.com>
RJ Catalano <catalanor0220@gmail.com> <rj@erisindustries.com>
Ralph Caraveo <deckarep@gmail.com>
Rene Lubov <41963722+renaynay@users.noreply.github.com>
Robert Zaremba <robert@zaremba.ch>
Robert Zaremba <robert@zaremba.ch> <robert.zaremba@scale-it.pl>
Roberto Bayardo <bayardo@alum.mit.edu>
Roberto Bayardo <bayardo@alum.mit.edu> <roberto.bayardo@coinbase.com>
Roman Mandeleil <roman.mandeleil@gmail.com>
Sebastian Stammler <seb@oplabs.co>
Sebastian Stammler <seb@oplabs.co> <stammler.s@gmail.com>
Seungbae Yu <dbadoy4874@gmail.com>
Seungbae Yu <dbadoy4874@gmail.com> <72970043+dbadoy@users.noreply.github.com>
Sina Mahmoodi <1591639+s1na@users.noreply.github.com>
Steve Milk <wangpeculiar@gmail.com>
Steve Milk <wangpeculiar@gmail.com> <915337710@qq.com>
Sorin Neacsu <sorin.neacsu@gmail.com>
Sorin Neacsu <sorin.neacsu@gmail.com> <sorin@users.noreply.github.com>
Sven Ehlert <sven@ethdev.com>
Taylor Gerring <taylor.gerring@gmail.com>
Taylor Gerring <taylor.gerring@gmail.com> <taylor.gerring@ethereum.org>
Thomas Bocek <tom@tomp2p.net>
tianyeyouyou <tianyeyouyou@gmail.com>
tianyeyouyou <tianyeyouyou@gmail.com> <150894831+tianyeyouyou@users.noreply.github.com>
Tim Cooijmans <timcooijmans@gmail.com>
ucwong <ethereum2k@gmail.com>
ucwong <ethereum2k@gmail.com> <ucwong@126.com>
Valentin Wüstholz <wuestholz@gmail.com>
Valentin Wüstholz <wuestholz@gmail.com> <wuestholz@users.noreply.github.com>
Armin Braun <me@obrown.io>
Victor Tran <vu.tran54@gmail.com>
Ernesto del Toro <ernesto.deltoro@gmail.com>
Ernesto del Toro <ernesto.deltoro@gmail.com> <ernestodeltoro@users.noreply.github.com>
Viktor Trón <viktor.tron@gmail.com>
Ville Sundell <github@solarius.fi>
Vincent G <caktux@gmail.com>
Vitalik Buterin <v@buterin.com>
Vlad Gluhovsky <gluk256@gmail.com>
Vlad Gluhovsky <gluk256@gmail.com> <gluk256@users.noreply.github.com>
Wenshao Zhong <wzhong20@uic.edu>
Wenshao Zhong <wzhong20@uic.edu> <11510383@mail.sustc.edu.cn>
Wenshao Zhong <wzhong20@uic.edu> <374662347@qq.com>
Will Villanueva <hello@willvillanueva.com>
Xiaobing Jiang <s7v7nislands@gmail.com>
Xudong Liu <33193253+r1cs@users.noreply.github.com>
Yohann Léon <sybiload@gmail.com>
yzb <335357057@qq.com>
yzb <335357057@qq.com> <flyingyzb@gmail.com>
Ziyuan Zhong <zzy.albert@163.com>
Zsolt Felföldi <zsfelfoldi@gmail.com>
Максим Чусовлянов <mchusovlianov@gmail.com>

View file

@ -1,230 +0,0 @@
language: go
go_import_path: github.com/ethereum/go-ethereum
sudo: false
jobs:
allow_failures:
- stage: build
os: osx
go: 1.14.x
env:
- azure-osx
- azure-ios
- cocoapods-ios
include:
# This builder only tests code linters on latest version of Go
- stage: lint
os: linux
dist: xenial
go: 1.15.x
env:
- lint
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go lint
# This builder does the Ubuntu PPA upload
- stage: build
if: type = push
os: linux
dist: xenial
go: 1.15.x
env:
- ubuntu-ppa
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
addons:
apt:
packages:
- devscripts
- debhelper
- dput
- fakeroot
- python-bzrlib
- python-paramiko
script:
- echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
- go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
# This builder does the Linux Azure uploads
- stage: build
if: type = push
os: linux
dist: xenial
sudo: required
go: 1.15.x
env:
- azure-linux
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
addons:
apt:
packages:
- gcc-multilib
script:
# Build for the primary platforms that Trusty can manage
- go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go install -dlgo -arch 386
- go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# Switch over GCC to cross compilation (breaks 386, hence why do it here only)
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- sudo ln -s /usr/include/asm-generic /usr/include/asm
- GOARM=5 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- GOARM=6 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- GOARM=7 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabihf-gcc
- GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# This builder does the Linux Azure MIPS xgo uploads
- stage: build
if: type = push
os: linux
dist: xenial
services:
- docker
go: 1.15.x
env:
- azure-linux-mips
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go xgo --alltools -- --targets=linux/mips --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mips; do mv -f "${bin}" "${bin/-linux-mips/}"; done
- go run build/ci.go archive -arch mips -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go xgo --alltools -- --targets=linux/mipsle --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mipsle; do mv -f "${bin}" "${bin/-linux-mipsle/}"; done
- go run build/ci.go archive -arch mipsle -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go xgo --alltools -- --targets=linux/mips64 --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mips64; do mv -f "${bin}" "${bin/-linux-mips64/}"; done
- go run build/ci.go archive -arch mips64 -type tar -signer LINUX_SIGNING_KEY signify SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go xgo --alltools -- --targets=linux/mips64le --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mips64le; do mv -f "${bin}" "${bin/-linux-mips64le/}"; done
- go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# This builder does the Android Maven and Azure uploads
- stage: build
if: type = push
os: linux
dist: xenial
addons:
apt:
packages:
- oracle-java8-installer
- oracle-java8-set-default
language: android
android:
components:
- platform-tools
- tools
- android-15
- android-19
- android-24
env:
- azure-android
- maven-android
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
before_install:
- curl https://dl.google.com/go/go1.15.5.linux-amd64.tar.gz | tar -xz
- export PATH=`pwd`/go/bin:$PATH
- export GOROOT=`pwd`/go
- export GOPATH=$HOME/go
script:
# Build the Android archive and upload it to Maven Central and Azure
- curl https://dl.google.com/android/repository/android-ndk-r19b-linux-x86_64.zip -o android-ndk-r19b.zip
- unzip -q android-ndk-r19b.zip && rm android-ndk-r19b.zip
- mv android-ndk-r19b $ANDROID_HOME/ndk-bundle
- mkdir -p $GOPATH/src/github.com/ethereum
- ln -s `pwd` $GOPATH/src/github.com/ethereum/go-ethereum
- go run build/ci.go aar -signer ANDROID_SIGNING_KEY -signify SIGNIFY_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
# This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads
- stage: build
if: type = push
os: osx
go: 1.15.x
env:
- azure-osx
- azure-ios
- cocoapods-ios
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# Build the iOS framework and upload it to CocoaPods and Azure
- gem uninstall cocoapods -a -x
- gem install cocoapods
- mv ~/.cocoapods/repos/master ~/.cocoapods/repos/master.bak
- sed -i '.bak' 's/repo.join/!repo.join/g' $(dirname `gem which cocoapods`)/cocoapods/sources_manager.rb
- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git clone --depth=1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master && pod setup --verbose; fi
- xctool -version
- xcrun simctl list
# Workaround for https://github.com/golang/go/issues/23749
- export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
- go run build/ci.go xcode -signer IOS_SIGNING_KEY -signify SIGNIFY_KEY -deploy trunk -upload gethstore/builds
# These builders run the tests
- stage: build
os: linux
arch: amd64
dist: xenial
go: 1.15.x
env:
- GO111MODULE=on
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- stage: build
if: type = pull_request
os: linux
arch: arm64
dist: xenial
go: 1.15.x
env:
- GO111MODULE=on
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- stage: build
os: linux
dist: xenial
go: 1.14.x
env:
- GO111MODULE=on
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
# This builder does the Azure archive purges to avoid accumulating junk
- stage: build
if: type = cron
os: linux
dist: xenial
go: 1.15.x
env:
- azure-purge
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go purge -store gethstore/builds -days 14

98
AGENTS.md Normal file
View file

@ -0,0 +1,98 @@
# AGENTS
## Guidelines
- **Keep changes minimal and focused.** Only modify code directly related to the task at hand. Do not refactor unrelated code, rename existing variables or functions for style, or bundle unrelated fixes into the same commit or PR.
- **Do not add, remove, or update dependencies** unless the task explicitly requires it.
## Pre-Commit Checklist
Before every commit, run **all** of the following checks and ensure they pass:
### 1. Formatting
Before committing, always run `gofmt` and `goimports` on all modified files:
```sh
gofmt -w <modified files>
goimports -w <modified files>
```
### 2. Build All Commands
Verify that all tools compile successfully:
```sh
make all
```
This builds all executables under `cmd/`, including `keeper` which has special build requirements.
### 3. Tests
While iterating during development, use `-short` for faster feedback:
```sh
go run ./build/ci.go test -short
```
Before committing, run the full test suite **without** `-short` to ensure all tests pass, including the Ethereum execution-spec tests and all state/block test permutations:
```sh
go run ./build/ci.go test
```
### 4. Linting
```sh
go run ./build/ci.go lint
```
This runs additional style checks. Fix any issues before committing.
### 5. Generated Code
```sh
go run ./build/ci.go check_generate
```
Ensures that all generated files (e.g., `gen_*.go`) are up to date. If this fails, first install the required code generators by running `make devtools`, then run the appropriate `go generate` commands and include the updated files in your commit.
### 6. Dependency Hygiene
```sh
go run ./build/ci.go check_baddeps
```
Verifies that no forbidden dependencies have been introduced.
## Commit Message Format
Commit messages must be prefixed with the package(s) they modify, followed by a short lowercase description:
```
<package(s)>: description
```
Examples:
- `core/vm: fix stack overflow in PUSH instruction`
- `eth, rpc: make trace configs optional`
- `cmd/geth: add new flag for sync mode`
Use comma-separated package names when multiple areas are affected. Keep the description concise.
## Pull Request Title Format
PR titles follow the same convention as commit messages:
```
<list of modified paths>: description
```
Examples:
- `core/vm: fix stack overflow in PUSH instruction`
- `core, eth: add arena allocator support`
- `cmd/geth, internal/ethapi: refactor transaction args`
- `trie/archiver: streaming subtree archival to fix OOM`
Use the top-level package paths, comma-separated if multiple areas are affected. Only mention the directories with functional changes, interface changes that trickle all over the codebase should not generate an exhaustive list. The description should be a short, lowercase summary of the change.

548
AUTHORS
View file

@ -1,325 +1,772 @@
# This is the official list of go-ethereum authors for copyright purposes.
0xbeny <55846654+0xbeny@users.noreply.github.com>
0xbstn <bastien-bouge@hotmail.fr>
0xe3b0c4 <110295932+0xe3b0c4@users.noreply.github.com>
6543 <6543@obermui.de>
6xiaowu9 <736518585@qq.com>
a e r t h <aerth@users.noreply.github.com>
Aaron Buchwald <aaron.buchwald56@gmail.com>
Aaron Chen <aaronchen.lisp@gmail.com>
Aaron Kumavis <kumavis@users.noreply.github.com>
Aayush Rajasekaran <arajasek94@gmail.com>
Abel Nieto <abel.nieto90@gmail.com>
Abel Nieto <anietoro@uwaterloo.ca>
Abirdcfly <fp544037857@gmail.com>
Adam Babik <a.babik@designfortress.com>
Adam Schmideg <adamschmideg@users.noreply.github.com>
Aditya <adityasripal@gmail.com>
Aditya Arora <arora.aditya520@gmail.com>
Adrian Sutton <adrian@oplabs.co>
Adrià Cidre <adria.cidre@gmail.com>
Afanasii Kurakin <afanasy@users.noreply.github.com>
Afri Schoedon <5chdn@users.noreply.github.com>
Agustin Armellini Fischer <armellini13@gmail.com>
Ahmet Avci <ahmetabdullahavci07@gmail.com>
Ahyun <urbanart2251@gmail.com>
Airead <fgh1987168@gmail.com>
Alan Chen <alanchchen@users.noreply.github.com>
Alejandro Isaza <alejandro.isaza@gmail.com>
Aleksey Smyrnov <i@soar.name>
Ales Katona <ales@coinbase.com>
alex <152680487+bodhi-crypo@users.noreply.github.com>
Alex Beregszaszi <alex@rtfs.hu>
Alex Gartner <github@agartner.com>
Alex Leverington <alex@ethdev.com>
Alex Mazalov <mazalov@gmail.com>
Alex Mylonas <alex.a.mylonas@gmail.com>
Alex Pozhilenkov <alex_pozhilenkov@adoriasoft.com>
Alex Prut <1648497+alexprut@users.noreply.github.com>
Alex Stokes <r.alex.stokes@gmail.com>
Alex Wu <wuyiding@gmail.com>
Alexander Mint <webinfo.alexander@gmail.com>
Alexander van der Meij <alexandervdm@users.noreply.github.com>
Alexander Yastrebov <yastrebov.alex@gmail.com>
Alexandre Van de Sande <alex.vandesande@ethdev.com>
Alexey Akhunov <akhounov@gmail.com>
Alexey Shekhirin <a.shekhirin@gmail.com>
alexwang <39109351+dipingxian2@users.noreply.github.com>
Alfie John <alfiedotwtf@users.noreply.github.com>
Ali Atiia <42751398+aliatiia@users.noreply.github.com>
Ali Hajimirza <Ali92hm@users.noreply.github.com>
Alvaro Sevilla <alvarosevilla95@gmail.com>
am2rican5 <am2rican5@gmail.com>
Amin Talebi <talebi242@gmail.com>
AMIR <31338382+amiremohamadi@users.noreply.github.com>
AmitBRD <60668103+AmitBRD@users.noreply.github.com>
Anatole <62328077+a2br@users.noreply.github.com>
Andre Patta <andre_luis@outlook.com>
Andrea Franz <andrea@gravityblast.com>
Andrey Petrov <andrey.petrov@shazow.net>
Andrei Kostakov <bps@dzen.ws>
Andrei Maiboroda <andrei@ethereum.org>
Andrei Silviu Dragnea <andreidragnea.dev@gmail.com>
Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com>
Andrey Petrov <shazow@gmail.com>
Andryanau Kanstantsin <andrianov.dev@yandex.by>
ANOTHEL <anothel1@naver.com>
Antoine Rondelet <rondelet.antoine@gmail.com>
Antoine Toulme <atoulme@users.noreply.github.com>
Anton Evangelatov <anton.evangelatov@gmail.com>
Antonio Salazar Cardozo <savedfastcool@gmail.com>
Antony Denyer <email@antonydenyer.co.uk>
Anusha <63559942+anusha-ctrl@users.noreply.github.com>
Arba Sasmoyo <arba.sasmoyo@gmail.com>
Armani Ferrante <armaniferrante@berkeley.edu>
Armin Braun <me@obrown.io>
Aron Fischer <github@aron.guru>
Arran Schlosberg <519948+ARR4N@users.noreply.github.com>
ArtificialPB <matej.berger@hotmail.com>
Artyom Aminov <artjoma@users.noreply.github.com>
atsushi-ishibashi <atsushi.ishibashi@finatext.com>
Austin Roberts <code@ausiv.com>
ayeowch <ayeowch@gmail.com>
b00ris <b00ris@mail.ru>
b1ackd0t <blackd0t@protonmail.com>
bailantaotao <Edwin@maicoin.com>
baizhenxuan <nkbai@163.com>
Bala Murali Krishna Komatireddy <krishna192reddy@gmail.com>
Balaji Shetty Pachai <32358081+balajipachai@users.noreply.github.com>
Balint Gabor <balint.g@gmail.com>
baptiste-b-pegasys <85155432+baptiste-b-pegasys@users.noreply.github.com>
Bas van Kervel <bas@ethdev.com>
Benjamin Brent <benjamin@benjaminbrent.com>
Benjamin Prosnitz <bprosnitz@gmail.com>
benma <mbencun@gmail.com>
Benoit Verkindt <benoit.verkindt@gmail.com>
Bin <49082129+songzhibin97@users.noreply.github.com>
Binacs <bin646891055@gmail.com>
bitcoin-lightning <153181187+AtomicInnovation321@users.noreply.github.com>
bk <5810624+bkellerman@users.noreply.github.com>
bloonfield <bloonfield@163.com>
bnovil <lzqcn2000@126.com>
Bo <bohende@gmail.com>
Bo Ye <boy.e.computer.1982@outlook.com>
Bob Glickstein <bobg@users.noreply.github.com>
Boqin Qin <bobbqqin@bupt.edu.cn>
BorkBorked <107079055+BorkBorked@users.noreply.github.com>
Brandon Harden <b.harden92@gmail.com>
Brandon Liu <lzqcn2000@126.com>
Brent <bmperrea@gmail.com>
Brian Schroeder <bts@gmail.com>
Brion <4777457+cifer76@users.noreply.github.com>
Bruno Škvorc <bruno@skvorc.me>
buddho <galaxystroller@gmail.com>
bugmaker9371 <167614621+bugmaker9371@users.noreply.github.com>
C. Brown <hackdom@majoolr.io>
Caesar Chad <BLUE.WEB.GEEK@gmail.com>
cam-schultz <78878559+cam-schultz@users.noreply.github.com>
Casey Detrio <cdetrio@gmail.com>
caseylove <casey4love@foxmail.com>
CDsigma <cdsigma271@gmail.com>
Cedrick <Cedrickentrep@gmail.com>
Ceelog <chenwei@ceelog.org>
Ceyhun Onur <ceyhun.onur@avalabs.org>
chabashilah <doumodoumo@gmail.com>
changhong <changhong.yu@shanbay.com>
Charles Cooper <cooper.charles.m@gmail.com>
Charlotte <tqpcharlie@proton.me>
Chase Wright <mysticryuujin@gmail.com>
Chawin Aiemvaravutigul <nick41746@hotmail.com>
Chen Quan <terasum@163.com>
chen4903 <108803001+chen4903@users.noreply.github.com>
Cheng Li <lob4tt@gmail.com>
chenglin <910372762@qq.com>
chenyufeng <yufengcode@gmail.com>
Chirag Garg <38765776+DeVil2O@users.noreply.github.com>
chirag-bgh <76247491+chirag-bgh@users.noreply.github.com>
Chris Pacia <ctpacia@gmail.com>
Chris Ziogas <ziogaschr@gmail.com>
Christian Muehlhaeuser <muesli@gmail.com>
Christina <156356273+cratiu222@users.noreply.github.com>
Christoph Jentzsch <jentzsch.software@gmail.com>
Christopher Harrison <31964100+chrischarlesharrison@users.noreply.github.com>
chuwt <weitaochu@gmail.com>
cocoyeal <150209682+cocoyeal@users.noreply.github.com>
cong <ackratos@users.noreply.github.com>
Connor Stein <connor.stein@mail.mcgill.ca>
Corey Lin <514971757@qq.com>
courtier <derinilter@gmail.com>
cpusoft <cpusoft@live.com>
crazeteam <164632007+crazeteam@users.noreply.github.com>
Crispin Flowerday <crispin@bitso.com>
croath <croathliu@gmail.com>
cui <523516579@qq.com>
cui fliter <imcusg@gmail.com>
cuinix <65650185+cuinix@users.noreply.github.com>
Curith <oiooj@qq.com>
cygaar <97691933+cygaar@users.noreply.github.com>
Dan Cline <6798349+Rjected@users.noreply.github.com>
Dan DeGreef <dan.degreef@gmail.com>
Dan Kinsley <dan@joincivil.com>
Dan Laine <daniel.laine@avalabs.org>
Dan Sosedoff <dan.sosedoff@gmail.com>
danceratopz <danceratopz@gmail.com>
Daniel A. Nagy <nagy.da@gmail.com>
Daniel Fernandes <711733+daferna@users.noreply.github.com>
Daniel Katzan <108216499+dkatzan@users.noreply.github.com>
Daniel Knopik <107140945+dknopik@users.noreply.github.com>
Daniel Liu <liudaniel@qq.com>
Daniel Perez <daniel@perez.sh>
Daniel Sloof <goapsychadelic@gmail.com>
Danno Ferrin <danno@numisight.com>
Danyal Prout <me@dany.al>
Darioush Jalali <darioush.jalali@avalabs.org>
Darrel Herbst <dherbst@gmail.com>
Darren Kelly <107671032+darrenvechain@users.noreply.github.com>
dashangcun <907225865@qq.com>
Dave Appleton <calistralabs@gmail.com>
Dave McGregor <dave.s.mcgregor@gmail.com>
David Cai <davidcai1993@yahoo.com>
David Dzhalaev <72649244+DavidRomanovizc@users.noreply.github.com>
David Huie <dahuie@gmail.com>
David Murdoch <187813+davidmurdoch@users.noreply.github.com>
David Theodore <29786815+infosecual@users.noreply.github.com>
ddl <ddl196526@163.com>
Dean Eigenmann <7621705+decanus@users.noreply.github.com>
Delweng <delweng@gmail.com>
Denver <aeharvlee@gmail.com>
Derek Chiang <me@derekchiang.com>
Derek Gottfrid <derek@codecubed.com>
deterclosed <164524498+deterclosed@users.noreply.github.com>
Devon Bear <itsdevbear@berachain.com>
Di Peng <pendyaaa@gmail.com>
Diederik Loerakker <proto@protolambda.com>
Diego Siqueira <DiSiqueira@users.noreply.github.com>
Diep Pham <mrfavadi@gmail.com>
Dimitris Apostolou <dimitris.apostolou@icloud.com>
dipingxian2 <39109351+dipingxian2@users.noreply.github.com>
divergencetech <94644849+divergencetech@users.noreply.github.com>
dknopik <107140945+dknopik@users.noreply.github.com>
dm4 <sunrisedm4@gmail.com>
Dmitrij Koniajev <dimchansky@gmail.com>
Dmitry Shulyak <yashulyak@gmail.com>
Dmitry Zenovich <dzenovich@gmail.com>
Domino Valdano <dominoplural@gmail.com>
Domino Valdano <jeff@okcupid.com>
DongXi Huang <418498589@qq.com>
Dragan Milic <dragan@netice9.com>
dragonvslinux <35779158+dragononcrypto@users.noreply.github.com>
Dylan Vassallo <dylan.vassallo@hotmail.com>
easyfold <137396765+easyfold@users.noreply.github.com>
Edgar Aroutiounian <edgar.factorial@gmail.com>
Eduard S <eduardsanou@posteo.net>
Egon Elbre <egonelbre@gmail.com>
Elad <theman@elad.im>
Eli <elihanover@yahoo.com>
Elias Naur <elias.naur@gmail.com>
Elias Rad <146735585+nnsW3@users.noreply.github.com>
Elliot Shepherd <elliot@identitii.com>
Emil <mursalimovemeel@gmail.com>
emile <emile@users.noreply.github.com>
Enrique Fynn <enriquefynn@gmail.com>
Emmanuel T Odeke <odeke@ualberta.ca>
Eng Zer Jun <engzerjun@gmail.com>
Enrique Fynn <me@enriquefynn.com>
Enrique Ortiz <hi@enriqueortiz.dev>
EOS Classic <info@eos-classic.io>
Erichin <erichinbato@gmail.com>
Ernesto del Toro <ernesto.deltoro@gmail.com>
Ethan Buchman <ethan@coinculture.info>
ethersphere <thesw@rm.eth>
Eugene Lepeico <eugenelepeico@gmail.com>
Eugene Valeyev <evgen.povt@gmail.com>
Evangelos Pappas <epappas@evalonlabs.com>
Everton Fraga <ev@ethereum.org>
Evgeny <awesome.observer@yandex.com>
Evgeny Danilenko <6655321@bk.ru>
evgk <evgeniy.kamyshev@gmail.com>
Evolution404 <35091674+Evolution404@users.noreply.github.com>
Exca-DK <85954505+Exca-DK@users.noreply.github.com>
EXEC <execvy@gmail.com>
Fabian Vogelsteller <fabian@frozeman.de>
Fabio Barone <fabio.barone.co@gmail.com>
Fabio Berger <fabioberger1991@gmail.com>
FaceHo <facehoshi@gmail.com>
felipe <fselmo2@gmail.com>
Felipe Strozberg <48066928+FelStroz@users.noreply.github.com>
Felix Lange <fjl@twurst.com>
Ferenc Szabo <frncmx@gmail.com>
ferhat elmas <elmas.ferhat@gmail.com>
Ferran Borreguero <ferranbt@protonmail.com>
Fiisio <liangcszzu@163.com>
Fire Man <55934298+basdevelop@users.noreply.github.com>
FletcherMan <fanciture@163.com>
flowerofdream <775654398@qq.com>
fomotrader <82184770+fomotrader@users.noreply.github.com>
Ford <153042616+guerrierindien@users.noreply.github.com>
ForLina <471133417@qq.com>
Frank Szendzielarz <33515470+FrankSzendzielarz@users.noreply.github.com>
Frank Wang <eternnoir@gmail.com>
Franklin <mr_franklin@126.com>
Freeman Jiang <freeman.jiang.ca@gmail.com>
Furkan KAMACI <furkankamaci@gmail.com>
Fuyang Deng <dengfuyang@outlook.com>
GagziW <leon.stanko@rwth-aachen.de>
Gary Rong <garyrong0905@gmail.com>
Gautam Botrel <gautam.botrel@gmail.com>
Gealber Morales <48373523+Gealber@users.noreply.github.com>
George Ma <164313692+availhang@users.noreply.github.com>
George Ornbo <george@shapeshed.com>
georgehao <haohongfan@gmail.com>
gitglorythegreat <t4juu3@proton.me>
Giuseppe Bertone <bertone.giuseppe@gmail.com>
Greg Colvin <greg@colvin.org>
Gregg Dourgarian <greggd@tempworks.com>
Gregory Markou <16929357+GregTheGreek@users.noreply.github.com>
guangwu <guoguangwu@magic-shield.com>
Guido Vranken <guidovranken@users.noreply.github.com>
Guifel <toowik@gmail.com>
Guilherme Salgado <gsalgado@gmail.com>
Guillaume Ballet <gballet@gmail.com>
Guillaume Michel <guillaumemichel@users.noreply.github.com>
Guillaume Nicolas <guin56@gmail.com>
GuiltyMorishita <morilliantblue@gmail.com>
Guruprasad Kamath <48196632+gurukamath@users.noreply.github.com>
Gus <yo@soygus.com>
Gustav Simonsson <gustav.simonsson@gmail.com>
Gustavo Silva <GustavoRSSilva@users.noreply.github.com>
Gísli Kristjánsson <gislik@hamstur.is>
Ha ĐANG <dvietha@gmail.com>
HackyMiner <hackyminer@gmail.com>
hadv <dvietha@gmail.com>
Halimao <1065621723@qq.com>
Hanjiang Yu <delacroix.yu@gmail.com>
Hao Bryan Cheng <haobcheng@gmail.com>
Hao Duan <duanhao0814@gmail.com>
haoran <159284258+hr98w@users.noreply.github.com>
Haotian <51777534+tmelhao@users.noreply.github.com>
HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Harry Dutton <me@bytejedi.com>
Harry Kalodner <harry.kalodner@gmail.com>
haryu703 <34744512+haryu703@users.noreply.github.com>
hattizai <hattizai@gmail.com>
Hendrik Hofstadt <hendrik@nexantic.com>
Henning Diedrich <hd@eonblast.com>
henopied <13500516+henopied@users.noreply.github.com>
henridf <henri@dubfer.com>
Henry <101552941+henry-0@users.noreply.github.com>
hero5512 <lvshuaino@gmail.com>
holisticode <holistic.computing@gmail.com>
Hongbin Mao <hello2mao@gmail.com>
Hsien-Tang Kao <htkao@pm.me>
hsyodyssey <47173566+hsyodyssey@users.noreply.github.com>
Hteev Oli <gethorz@proton.me>
Husam Ibrahim <39692071+HusamIbrahim@users.noreply.github.com>
Hwanjo Heo <34005989+hwanjo@users.noreply.github.com>
hydai <z54981220@gmail.com>
hyhnet <cyrusyun@qq.com>
hyunchel <3271191+hyunchel@users.noreply.github.com>
Hyung-Kyu Hqueue Choi <hyungkyu.choi@gmail.com>
Hyunsoo Shin (Lake) <hyunsooda@kaist.ac.kr>
hzysvilla <ecjgvmhc@gmail.com>
Håvard Anda Estensen <haavard.ae@gmail.com>
Ian Macalinao <me@ian.pw>
Ian Norden <iannordenn@gmail.com>
Icarus Wu <icaruswu66@qq.com>
icodezjb <icodezjb@163.com>
ids <tonyhaha163@163.com>
Ignacio Hagopian <jsign.uy@gmail.com>
Ikko Eltociear Ashimine <eltociear@gmail.com>
Ilan Gitter <8359193+gitteri@users.noreply.github.com>
imalasong <55082705+imalasong@users.noreply.github.com>
ImanSharaf <78227895+ImanSharaf@users.noreply.github.com>
imulmat4 <117636097+imulmat4@users.noreply.github.com>
Inphi <mlaw2501@gmail.com>
int88 <106391185+int88@users.noreply.github.com>
Isidoro Ghezzi <isidoro.ghezzi@icloud.com>
Iskander (Alex) Sharipov <quasilyte@gmail.com>
Ivan Aracki <aracki.ivan@gmail.com>
Ivan Bogatyy <bogatyi@gmail.com>
Ivan Daniluk <ivan.daniluk@gmail.com>
Ivo Georgiev <ivo@strem.io>
j2gg0s <j2gg0s@gmail.com>
jacksoom <lifengliu1994@gmail.com>
jackyin <648588267@qq.com>
Jae Kwon <jkwon.work@gmail.com>
Jakub Freebit <49676311+jakub-freebit@users.noreply.github.com>
James Prestwich <james@prestwi.ch>
Jamie Pitts <james.pitts@gmail.com>
Janos Guljas <janos@resenje.org>
Janoš Guljaš <janos@users.noreply.github.com>
Janko Simonovic <simonovic86@gmail.com>
Janoš Guljaš <janos@resenje.org>
Jared Wasinger <j-wasinger@hotmail.com>
Jason Carver <jacarver@linkedin.com>
Javier Peletier <jm@epiclabs.io>
Javier Peletier <jpeletier@users.noreply.github.com>
Javier Sagredo <jasataco@gmail.com>
Jay <codeholic.arena@gmail.com>
Jay Guo <guojiannan1101@gmail.com>
Jaynti Kanani <jdkanani@gmail.com>
Jeff Prestes <jeffprestes@gmail.com>
Jeff R. Allen <jra@nella.org>
Jeff Wentworth <jeff@curvegrid.com>
Jeffery Robert Walsh <rlxrlps@gmail.com>
Jeffrey Wilcke <jeffrey@ethereum.org>
Jens Agerberg <github@agerberg.me>
Jens W <8270201+DragonDev1906@users.noreply.github.com>
Jeremy McNevin <jeremy.mcnevin@optum.com>
Jeremy Schlatter <jeremy.schlatter@gmail.com>
Jerzy Lasyk <jerzylasyk@gmail.com>
Jesse Tane <jesse.tane@gmail.com>
Jia Chenhui <jiachenhui1989@gmail.com>
Jim McDonald <Jim@mcdee.net>
jin <35813306+lochjin@users.noreply.github.com>
jk-jeongkyun <45347815+jeongkyun-oh@users.noreply.github.com>
jkcomment <jkcomment@gmail.com>
Joe Netti <joe@netti.dev>
JoeGruffins <34998433+JoeGruffins@users.noreply.github.com>
Joel Burget <joelburget@gmail.com>
John C. Vernaleo <john@netpurgatory.com>
John Chase <68833933+joohhnnn@users.noreply.github.com>
John Difool <johndifoolpi@gmail.com>
John Hilliard <jhilliard@polygon.technology>
John Xu <dyxushuai@gmail.com>
Johns Beharry <johns@peakshift.com>
Jolly Zhao <zhaolei@pm.me>
Jonas <felberj@users.noreply.github.com>
Jonathan Brown <jbrown@bluedroplet.com>
Jonathan Chappelow <chappjc@users.noreply.github.com>
Jonathan Gimeno <jgimeno@gmail.com>
Jonathan Otto <jonathan.otto@gmail.com>
JoranHonig <JoranHonig@users.noreply.github.com>
Jordan Krage <jmank88@gmail.com>
Jorge <jorgeacortes@users.noreply.github.com>
Jorropo <jorropo.pgm@gmail.com>
Joseph Chow <ethereum@outlook.com>
Joseph Cook <33655003+jmcook1186@users.noreply.github.com>
Joshua Colvin <jcolvin@offchainlabs.com>
Joshua Gutow <jbgutow@gmail.com>
jovijovi <mageyul@hotmail.com>
jp-imx <109574657+jp-imx@users.noreply.github.com>
jtakalai <juuso.takalainen@streamr.com>
JU HYEONG PARK <dkdkajej@gmail.com>
Julian Y <jyap808@users.noreply.github.com>
Justin Clark-Casey <justincc@justincc.org>
Justin Dhillon <justin.singh.dhillon@gmail.com>
Justin Drake <drakefjustin@gmail.com>
jwasinger <j-wasinger@hotmail.com>
Justin Traglia <95511699+jtraglia@users.noreply.github.com>
Justus <jus@gtsbr.org>
KAI <35927054+ThreeAndTwo@users.noreply.github.com>
kaliubuntu0206 <139627505+kaliubuntu0206@users.noreply.github.com>
Karl Bartel <karl.bartel@clabs.co>
Karol Chojnowski <karolchojnowski95@gmail.com>
Kawashima <91420903+sscodereth@users.noreply.github.com>
kazak <alright-epsilon8h@icloud.com>
ken10100147 <sunhongping@kanjian.com>
Kenji Siu <kenji@isuntv.com>
Kenso Trabing <kenso.trabing@bloomwebsite.com>
Kenso Trabing <ktrabing@acm.org>
Kero <keroroxx520@gmail.com>
kevaundray <kevtheappdev@gmail.com>
Kevin <denk.kevin@web.de>
kevin.xu <cming.xu@gmail.com>
Kiarash Hajian <133909368+kiarash8112@users.noreply.github.com>
KibGzr <kibgzr@gmail.com>
kiel barry <kiel.j.barry@gmail.com>
kilic <onurkilic1004@gmail.com>
kimmylin <30611210+kimmylin@users.noreply.github.com>
Kitten King <53072918+kittenking@users.noreply.github.com>
knarfeh <hejun1874@gmail.com>
Kobi Gurkan <kobigurk@gmail.com>
Koichi Shiraishi <zchee.io@gmail.com>
komika <komika@komika.org>
Konrad Feldmeier <konrad@brainbot.com>
Kosuke Taniguchi <73885532+TaniguchiKosuke@users.noreply.github.com>
Kris Shinn <raggamuffin.music@gmail.com>
Kristofer Peterson <svenski123@users.noreply.github.com>
Kumar Anirudha <mail@anirudha.dev>
Kurkó Mihály <kurkomisi@users.noreply.github.com>
Kushagra Sharma <ksharm01@gmail.com>
Kwuaint <34888408+kwuaint@users.noreply.github.com>
Kyuntae Ethan Kim <ethan.kyuntae.kim@gmail.com>
ledgerwatch <akhounov@gmail.com>
Lee Bousfield <ljbousfield@gmail.com>
Lefteris Karapetsas <lefteris@refu.co>
Leif Jurvetson <leijurv@gmail.com>
Leo Shklovskii <leo@thermopylae.net>
LeoLiao <leofantast@gmail.com>
Leon <316032931@qq.com>
levisyin <150114626+levisyin@users.noreply.github.com>
Lewis Marshall <lewis@lmars.net>
lhendre <lhendre2@gmail.com>
Liang Ma <liangma.ul@gmail.com>
Li Dongwei <lidw1988@126.com>
Liang Ma <liangma@liangbit.com>
Liang ZOU <liang.d.zou@gmail.com>
libby kent <viskovitzzz@gmail.com>
libotony <liboliqi@gmail.com>
LieutenantRoger <dijsky_2015@hotmail.com>
ligi <ligi@ligi.de>
lilasxie <thanklilas@163.com>
Lindlof <mikael@lindlof.io>
Lio李欧 <lionello@users.noreply.github.com>
Liyi Guo <102356659+colinlyguo@users.noreply.github.com>
llkhacquan <3724362+llkhacquan@users.noreply.github.com>
lmittmann <3458786+lmittmann@users.noreply.github.com>
lorenzo <31852651+lorenzo-dev1@users.noreply.github.com>
Lorenzo Manacorda <lorenzo@kinvolk.io>
Louis Holbrook <dev@holbrook.no>
Luca Zeug <luclu@users.noreply.github.com>
Lucas <lucaslg360@gmail.com>
Lucas Hendren <lhendre2@gmail.com>
Luozhu <70309026+LuozhuZhang@users.noreply.github.com>
lwh <lwhile521@gmail.com>
lzhfromustc <43191155+lzhfromustc@users.noreply.github.com>
Maciej Kulawik <10907694+magicxyyz@users.noreply.github.com>
Madhur Shrimal <madhur.shrimal@gmail.com>
Magicking <s@6120.eu>
makcandrov <makcandrov@proton.me>
manlio <manlio.poltronieri@gmail.com>
Manoj Kumar <mnjkmr398@gmail.com>
Maran Hidskes <maran.hidskes@gmail.com>
Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com>
Marcus Baldassarre <baldassarremarcus@gmail.com>
Marek Kotewicz <marek.kotewicz@gmail.com>
Mariano Cortesi <mcortesi@gmail.com>
Mario Vega <marioevz@gmail.com>
Marius G <90795310+bearpebble@users.noreply.github.com>
Marius Kjærstad <sandakersmann@users.noreply.github.com>
Marius van der Wijden <m.vanderwijden@live.de>
Mark <markya0616@gmail.com>
Mark Rushakoff <mark.rushakoff@gmail.com>
Mark Tyneway <mark.tyneway@gmail.com>
mark.lin <mark@maicoin.com>
markus <55011443+mdymalla@users.noreply.github.com>
Marquis Shanahan <29431502+9547@users.noreply.github.com>
Martin Alex Philip Dawson <u1356770@gmail.com>
Martin Holst Swende <martin@swende.se>
Martin Klepsch <martinklepsch@googlemail.com>
Martin Lundfall <martin.lundfall@protonmail.com>
Martin Michlmayr <tbm@cyrius.com>
Martin Redmond <21436+reds@users.noreply.github.com>
maskpp <maskpp266@gmail.com>
Mason Fischer <mason@kissr.co>
Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com>
Mats Julian Olsen <mats@plysjbyen.net>
Matt Garnett <lightclient@protonmail.com>
Matt K <1036969+mkrump@users.noreply.github.com>
Matthew Di Ferrante <mattdf@users.noreply.github.com>
Matthew Halpern <matthalp@gmail.com>
Matthew Halpern <matthalp@google.com>
Matthew Wampler-Doty <matthew.wampler.doty@gmail.com>
Matthieu Vachon <matt@streamingfast.io>
Max Sistemich <mafrasi2@googlemail.com>
Maxim Zhiburt <zhiburt@gmail.com>
Maximilian Meister <mmeister@suse.de>
me020523 <me020523@gmail.com>
Melvin Junhee Woo <melvin.woo@groundx.xyz>
meowsbits <b5c6@protonmail.com>
Micah Zoltu <micah@zoltu.net>
Michael de Hoog <michael.dehoog@gmail.com>
Michael Forney <mforney@mforney.org>
Michael Riabzev <michael@starkware.co>
Michael Ruminer <michael.ruminer+github@gmail.com>
michael1011 <me@michael1011.at>
Miguel Mota <miguelmota2@gmail.com>
Mike Burr <mburr@nightmare.com>
Mikel Cortes <45786396+cortze@users.noreply.github.com>
Mikhail Mikheev <mmvsha73@gmail.com>
Mikhail Vazhnov <michael.vazhnov@gmail.com>
miles <66052478+miles-six@users.noreply.github.com>
Miles Chen <fearlesschenc@gmail.com>
milesvant <milesvant@gmail.com>
minh-bq <97180373+minh-bq@users.noreply.github.com>
Mio <mshimmeris@gmail.com>
Miro <mirokuratczyk@users.noreply.github.com>
Miya Chen <miyatlchen@gmail.com>
mmsqe <mavis@crypto.com>
Mobin Mohanan <47410557+tr1sm0s1n@users.noreply.github.com>
Mohanson <mohanson@outlook.com>
moomin <67548026+nothingmin@users.noreply.github.com>
mr_franklin <mr_franklin@126.com>
Mskxn <118117161+Mskxn@users.noreply.github.com>
Mudit Gupta <guptamudit@ymail.com>
Mymskmkt <1847234666@qq.com>
Nalin Bhardwaj <nalinbhardwaj@nibnalin.me>
nand2 <nicolas@deschildre.fr>
Nathan <Nathan.l@nodereal.io>
Nathan Jo <162083209+qqqeck@users.noreply.github.com>
Natsu Kagami <natsukagami@gmail.com>
Naveen <116692862+naveen-imtb@users.noreply.github.com>
Nchinda Nchinda <nchinda2@gmail.com>
Nebojsa Urosevic <nebojsa94@users.noreply.github.com>
necaremus <necaremus@gmail.com>
nedifi <103940716+nedifi@users.noreply.github.com>
needkane <604476380@qq.com>
Newt6611 <45097780+Newt6611@users.noreply.github.com>
Ng Wei Han <47109095+weiihann@users.noreply.github.com>
Nguyen Kien Trung <trung.n.k@gmail.com>
Nguyen Sy Thanh Son <thanhson1085@gmail.com>
Nic Jansma <nic@nicj.net>
Nicholas <nicholas.zhaoyu@gmail.com>
Nick Dodson <silentcicero@outlook.com>
Nick Johnson <arachnid@notdot.net>
Nicola Cocchiaro <3538109+ncocchiaro@users.noreply.github.com>
Nicolas Feignon <nfeignon@gmail.com>
Nicolas Gotchac <ngotchac@gmail.com>
Nicolas Guillaume <gunicolas@sqli.com>
Nikhil Suri <nikhilsuri@comcast.net>
Nikita Kozhemyakin <enginegl.ec@gmail.com>
Nikola Madjarevic <nikola.madjarevic@gmail.com>
Nilesh Trivedi <nilesh@hypertrack.io>
Nimrod Gutman <nimrod.gutman@gmail.com>
Nishant Das <nishdas93@gmail.com>
njupt-moon <1015041018@njupt.edu.cn>
nkbai <nkbai@163.com>
noam-alchemy <76969113+noam-alchemy@users.noreply.github.com>
nobody <ddean2009@163.com>
noel <72006780+0x00Duke@users.noreply.github.com>
Noman <noman@noman.land>
norwnd <112318969+norwnd@users.noreply.github.com>
nujabes403 <nujabes403@gmail.com>
Nye Liu <nyet@nyet.org>
Obtuse7772 <117080049+Obtuse7772@users.noreply.github.com>
Oleg Kovalov <iamolegkovalov@gmail.com>
Oli Bye <olibye@users.noreply.github.com>
Oliver Tale-Yazdi <oliver@perun.network>
Olivier Hervieu <olivier.hervieu@gmail.com>
openex <openexkevin@gmail.com>
Or Neeman <oneeman@gmail.com>
oseau <harbin.kyang@gmail.com>
Osoro Bironga <fanosoro@gmail.com>
Osuke <arget-fee.free.dgm@hotmail.co.jp>
panicalways <113693386+panicalways@users.noreply.github.com>
Pantelis Peslis <pespantelis@gmail.com>
Parithosh Jayanthi <parithosh@indenwolken.xyz>
Park Changwan <pcw109550@gmail.com>
Pascal Dierich <pascal@merkleplant.xyz>
Patrick O'Grady <prohb125@gmail.com>
Pau <pau@dabax.net>
Paul <41552663+molecula451@users.noreply.github.com>
Paul Berg <hello@paulrberg.com>
Paul Lange <palango@users.noreply.github.com>
Paul Litvak <litvakpol@012.net.il>
Paul-Armand Verhaegen <paularmand.verhaegen@gmail.com>
Paulo L F Casaretto <pcasaretto@gmail.com>
Pawan Dhananjay <pawandhananjay@gmail.com>
Paweł Bylica <chfast@gmail.com>
Pedro Gomes <otherview@gmail.com>
Pedro Pombeiro <PombeirP@users.noreply.github.com>
persmor <166146971+persmor@users.noreply.github.com>
Peter (bitfly) <1674920+peterbitfly@users.noreply.github.com>
Peter Broadhurst <peter@themumbles.net>
peter cresswell <pcresswell@gmail.com>
Peter Pratscher <pratscher@gmail.com>
Peter Simard <petesimard56@gmail.com>
Peter Straus <153843855+krauspt@users.noreply.github.com>
Petr Mikusek <petr@mikusek.info>
phenix3443 <phenix3443@gmail.com>
Philip Schlump <pschlump@gmail.com>
Pierre Neter <pierreneter@gmail.com>
Pierre R <p.rousset@gmail.com>
piersy <pierspowlesland@gmail.com>
PilkyuJung <anothel1@naver.com>
protolambda <proto@protolambda.com>
Piotr Dyraga <piotr.dyraga@keep.network>
ploui <64719999+ploui@users.noreply.github.com>
PolyMa <151764357+polymaer@users.noreply.github.com>
Preston Van Loon <preston@prysmaticlabs.com>
Prince Sinha <sinhaprince013@gmail.com>
psogv0308 <psogv0308@gmail.com>
puhtaytow <18026645+puhtaytow@users.noreply.github.com>
Péter Szilágyi <peterke@gmail.com>
qcrao <qcrao91@gmail.com>
qd-ethan <31876119+qdgogogo@users.noreply.github.com>
Qian Bin <cola.tin.com@gmail.com>
qiuhaohao <trouserrr@gmail.com>
Qt <golang.chen@gmail.com>
Quentin McGaw <quentin.mcgaw@gmail.com>
Quest Henkart <qhenkart@gmail.com>
Rachel Bousfield <nfranks@protonmail.com>
Rachel Franks <nfranks@protonmail.com>
Rafael Matias <rafael@skyle.net>
Raghav Sood <raghavsood@gmail.com>
Rajaram Gaunker <zimbabao@gmail.com>
Ralph Caraveo <deckarep@gmail.com>
Ralph Caraveo III <deckarep@gmail.com>
Ramesh Nair <ram@hiddentao.com>
rangzen <public@l-homme.com>
reinerRubin <tolstov.georgij@gmail.com>
Rene Lubov <41963722+renaynay@users.noreply.github.com>
rhaps107 <dod-source@yandex.ru>
Ricardo Catalinas Jiménez <r@untroubled.be>
Ricardo Domingos <ricardohsd@gmail.com>
Richard Hart <richardhart92@gmail.com>
RichΛrd <info@richardramos.me>
Rick <rick.no@groundx.xyz>
RJ Catalano <catalanor0220@gmail.com>
Rob <robert@rojotek.com>
Rob Mulholand <rmulholand@8thlight.com>
Robert Zaremba <robert.zaremba@scale-it.pl>
Robert Zaremba <robert@zaremba.ch>
Roberto Bayardo <bayardo@alum.mit.edu>
Roc Yu <rociiu0112@gmail.com>
Roman Krasiuk <rokrassyuk@gmail.com>
Roman Mazalov <83914728+gopherxyz@users.noreply.github.com>
Ross <9055337+Chadsr@users.noreply.github.com>
Rossen Krastev <rosen4obg@gmail.com>
Roy Crihfield <roy@manteia.ltd>
Runchao Han <elvisage941102@gmail.com>
Ruohui Wang <nomaru@outlook.com>
Russ Cox <rsc@golang.org>
Ryan Schneider <ryanleeschneider@gmail.com>
Ryan Tinianov <tinianov@live.com>
ryanc414 <ryan@tokencard.io>
Rémy Roy <remyroy@remyroy.com>
S. Matthew English <s-matthew-english@users.noreply.github.com>
salanfe <salanfe@users.noreply.github.com>
Sam <39165351+Xia-Sam@users.noreply.github.com>
Saman H. Pasha <51169592+saman-pasha@users.noreply.github.com>
Sammy Libre <7374093+sammy007@users.noreply.github.com>
Samuel Marks <samuelmarks@gmail.com>
Sanghee Choi <32831939+pengin7384@users.noreply.github.com>
SangIlMo <156392700+SangIlMo@users.noreply.github.com>
sanskarkhare <sanskarkhare47@gmail.com>
SanYe <kumakichi@users.noreply.github.com>
Sarlor <kinsleer@outlook.com>
Sasuke1964 <neilperry1964@gmail.com>
Satpal <28562234+SatpalSandhu61@users.noreply.github.com>
Saulius Grigaitis <saulius@necolt.com>
Sean <darcys22@gmail.com>
Sheldon <11510383@mail.sustc.edu.cn>
Sheldon <374662347@qq.com>
seayyyy <163325936+seay404@users.noreply.github.com>
Sebastian Stammler <seb@oplabs.co>
Serhat Şevki Dinçer <jfcgauss@gmail.com>
Seungbae Yu <dbadoy4874@gmail.com>
Seungmin Kim <a7965344@gmail.com>
Shane Bammel <sjb933@gmail.com>
shawn <36943337+lxex@users.noreply.github.com>
shigeyuki azuchi <azuchi@chaintope.com>
Shihao Xia <charlesxsh@hotmail.com>
Shiming <codingmylife@gmail.com>
Shiming Zhang <wzshiming@hotmail.com>
Shintaro Kaneko <kaneshin0120@gmail.com>
shiqinfeng1 <150627601@qq.com>
Shivam Sandbhor <shivam.sandbhor@gmail.com>
shivhg <shivhg@gmail.com>
Shuai Qi <qishuai231@gmail.com>
Shude Li <islishude@gmail.com>
Shunsuke Watanabe <ww.shunsuke@gmail.com>
shuo <shuoli84@gmail.com>
silence <wangsai.silence@qq.com>
Simon Jentzsch <simon@slock.it>
Sina Mahmoodi <1591639+s1na@users.noreply.github.com>
sixdays <lj491685571@126.com>
sjlee1125 <47561537+sjlee1125@users.noreply.github.com>
SjonHortensius <SjonHortensius@users.noreply.github.com>
Slava Karpenko <slavikus@gmail.com>
slumber1122 <slumber1122@gmail.com>
Smilenator <yurivanenko@yandex.ru>
soc1c <soc1c@users.noreply.github.com>
Sorin Neacsu <sorin.neacsu@gmail.com>
Sparty <vignesh.crysis@gmail.com>
Stein Dekker <dekker.stein@gmail.com>
Stephen Flynn <ssflynn@gmail.com>
Stephen Guo <stephen.fire@gmail.com>
Steve Gattuso <steve@stevegattuso.me>
Steve Milk <wangpeculiar@gmail.com>
Steve Ruckdashel <steve.ruckdashel@gmail.com>
Steve Waldman <swaldman@mchange.com>
Steven E. Harris <seh@panix.com>
Steven Roose <stevenroose@gmail.com>
stompesi <stompesi@gmail.com>
stormpang <jialinpeng@vip.qq.com>
storyicon <storyicon@foxmail.com>
strykerin <dacosta.pereirafabio@gmail.com>
sudeep <sudeepdino008@gmail.com>
SuiYuan <165623542+suiyuan1314@users.noreply.github.com>
Sungwoo Kim <git@sung-woo.kim>
sunxiaojun2014 <sunxiaojun-xy@360.cn>
Suriyaa Sundararuban <isc.suriyaa@gmail.com>
Sylvain Laurent <s@6120.eu>
Szupingwang <cara4bear@gmail.com>
tactical_retreat <tactical0retreat@gmail.com>
Taeguk Kwon <xornrbboy@gmail.com>
Taeik Lim <sibera21@gmail.com>
taiking <c.tsujiyan727@gmail.com>
tamirms <tamir@trello.com>
Tangui Clairet <tangui.clairet@gmail.com>
Tatsuya Shimoda <tacoo@users.noreply.github.com>
Taylor Gerring <taylor.gerring@gmail.com>
TColl <38299499+TColl@users.noreply.github.com>
terasum <terasum@163.com>
tgyKomgo <52910426+tgyKomgo@users.noreply.github.com>
Thabokani <149070269+Thabokani@users.noreply.github.com>
Thad Guidry <thadguidry@gmail.com>
therainisme <therainisme@qq.com>
Thomas Bocek <tom@tomp2p.net>
thomasmodeneis <thomas.modeneis@gmail.com>
thumb8432 <thumb8432@gmail.com>
Ti Zhou <tizhou1986@gmail.com>
tia-99 <67107070+tia-99@users.noreply.github.com>
tianyeyouyou <tianyeyouyou@gmail.com>
Tien Nguyen <116023870+htiennv@users.noreply.github.com>
Tim Cooijmans <timcooijmans@gmail.com>
TinyFoxy <tiny.fox@foxmail.com>
Tobias Hildebrandt <79341166+tobias-hildebrandt@users.noreply.github.com>
tokikuch <msmania@users.noreply.github.com>
Tom <45168162+tomdever@users.noreply.github.com>
Tosh Camille <tochecamille@gmail.com>
trillo <trillo8652@gmail.com>
Tristan-Wilson <87238672+Tristan-Wilson@users.noreply.github.com>
trocher <trooocher@proton.me>
tsarpaul <Litvakpol@012.net.il>
TY <45994721+tylerK1294@users.noreply.github.com>
Tyler Chambers <2775339+tylerchambers@users.noreply.github.com>
tylerni7 <tylerni7@gmail.com>
tzapu <alex@tzapu.com>
ucwong <ethereum2k@gmail.com>
uji <49834542+uji@users.noreply.github.com>
ult-bobonovski <alex@ultiledger.io>
Undefinedor <wanghao@imwh.net>
Ursulafe <152976968+Ursulafe@users.noreply.github.com>
Valentin Trinqué <ValentinTrinque@users.noreply.github.com>
Valentin Wüstholz <wuestholz@gmail.com>
Vedhavyas Singareddi <vedhavyas.singareddi@gmail.com>
Victor Farazdagi <simple.square@gmail.com>
@ -330,40 +777,101 @@ Ville Sundell <github@solarius.fi>
vim88 <vim88vim88@gmail.com>
Vincent G <caktux@gmail.com>
Vincent Serpoul <vincent@serpoul.com>
Vinod Damle <vdamle@users.noreply.github.com>
Vitalik Buterin <v@buterin.com>
Vitaly Bogdanov <vsbogd@gmail.com>
Vitaly V <vvelikodny@gmail.com>
Vivek Anand <vivekanand1101@users.noreply.github.com>
Vlad <gluk256@gmail.com>
Vlad Bokov <razum2um@mail.ru>
Vlad Gluhovsky <gluk256@users.noreply.github.com>
Vlad Gluhovsky <gluk256@gmail.com>
VM <112189277+sysvm@users.noreply.github.com>
vuittont60 <81072379+vuittont60@users.noreply.github.com>
wangjingcun <wangjingcun@aliyun.com>
wangyifan <wangyifan@uchicago.edu>
Ward Bradt <wardbradt5@gmail.com>
Water <44689567+codeoneline@users.noreply.github.com>
wbt <wbt@users.noreply.github.com>
Wei Tang <acc@pacna.org>
weimumu <934657014@qq.com>
Wenbiao Zheng <delweng@gmail.com>
Wenshao Zhong <wzhong20@uic.edu>
Wihan de Beer <debeerwihan@gmail.com>
Will Villanueva <hello@willvillanueva.com>
William Morriss <wjmelements@gmail.com>
William Setzer <bootstrapsetzer@gmail.com>
williambannas <wrschwartz@wpi.edu>
willian.eth <willian@ufpa.br>
winniehere <winnie050812@qq.com>
winterjihwan <113398351+winterjihwan@users.noreply.github.com>
wuff1996 <33193253+wuff1996@users.noreply.github.com>
Wuxiang <wuxiangzhou2010@gmail.com>
Xiaobing Jiang <s7v7nislands@gmail.com>
xiaodong <81516175+javaandfly@users.noreply.github.com>
xiekeyang <xiekeyang@users.noreply.github.com>
xinbenlv <zzn@zzn.im>
xincaosu <xincaosu@126.com>
xinluyin <31590468+xinluyin@users.noreply.github.com>
xiyang <90125263+JBossBC@users.noreply.github.com>
Xudong Liu <33193253+r1cs@users.noreply.github.com>
xwjack <XWJACK@users.noreply.github.com>
yahtoo <yahtoo.ma@gmail.com>
Yang Hau <vulxj0j8j8@gmail.com>
YaoZengzeng <yaozengzeng@zju.edu.cn>
ycyraum <ycyraum@fastmail.com>
YH-Zhou <yanhong.zhou05@gmail.com>
Yier <90763233+yierx@users.noreply.github.com>
Yihau Chen <a122092487@gmail.com>
yihuang <huang@crypto.com>
Yohann Léon <sybiload@gmail.com>
Yoichi Hirai <i@yoichihirai.com>
Yole <007yuyue@gmail.com>
Yondon Fu <yondon.fu@gmail.com>
yong <33920876+yzhaoyu@users.noreply.github.com>
YOSHIDA Masanori <masanori.yoshida@gmail.com>
yoza <yoza.is12s@gmail.com>
ysh0566 <ysh0566@qq.com>
yudrywet <166895665+yudrywet@users.noreply.github.com>
yujinpark <petere123123@gmail.com>
yukionfire <yukionfire@qq.com>
yumiel yoomee1313 <yumiel.ko@groundx.xyz>
Yusup <awklsgrep@gmail.com>
yutianwu <wzxingbupt@gmail.com>
ywzqwwt <39263032+ywzqwwt@users.noreply.github.com>
yzb <335357057@qq.com>
zaccoding <zaccoding725@gmail.com>
Zach <zach.ramsay@gmail.com>
zah <zahary@gmail.com>
Zahoor Mohamed <zahoor@zahoor.in>
Zak Cole <zak@beattiecole.com>
zcheng9 <zcheng9@hawk.iit.edu>
zeim839 <50573884+zeim839@users.noreply.github.com>
zer0to0ne <36526113+zer0to0ne@users.noreply.github.com>
zgfzgf <48779939+zgfzgf@users.noreply.github.com>
Zhang Zhuo <mycinbrin@gmail.com>
zhangsoledad <787953403@qq.com>
zhaochonghe <41711151+zhaochonghe@users.noreply.github.com>
zhen peng <505380967@qq.com>
Zhenguo Niu <Niu.ZGlinux@gmail.com>
Zheyuan He <ecjgvmhc@gmail.com>
Zhihao Lin <3955922+kkqy@users.noreply.github.com>
zhiqiangxu <652732310@qq.com>
Zhou Zhiyao <ZHOU0250@e.ntu.edu.sg>
Ziyuan Zhong <zzy.albert@163.com>
Zoe Nolan <github@zoenolan.org>
zoereco <158379334+zoereco@users.noreply.github.com>
Zoo <zoosilence@gmail.com>
Zoro <40222601+BabyHalimao@users.noreply.github.com>
Zou Guangxian <zouguangxian@gmail.com>
Zsolt Felföldi <zsfelfoldi@gmail.com>
Łukasz Kurowski <crackcomm@users.noreply.github.com>
Łukasz Zimnoch <lukaszzimnoch1994@gmail.com>
ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com>
Максим Чусовлянов <mchusovlianov@gmail.com>
かげ <47621124+ronething-bot@users.noreply.github.com>
スパイク <1311798+spkjp@users.noreply.github.com>
大彬 <hz_stb@163.com>
沉风 <myself659@users.noreply.github.com>
牛晓婕 <30611384+niuxiaojie81@users.noreply.github.com>
贺鹏飞 <hpf@hackerful.cn>
陈佳 <chenjiablog@gmail.com>
유용환 <33824408+eric-yoo@users.noreply.github.com>

View file

@ -1,10 +1,20 @@
# Build Geth in a stock Go builder container
FROM golang:1.15-alpine as builder
# Support setting various labels on the final image
ARG COMMIT=""
ARG VERSION=""
ARG BUILDNUM=""
RUN apk add --no-cache make gcc musl-dev linux-headers git
# Build Geth in a stock Go builder container
FROM golang:1.26-alpine AS builder
RUN apk add --no-cache gcc musl-dev linux-headers git
# Get dependencies - will also be cached if we won't change go.mod/go.sum
COPY go.mod /go-ethereum/
COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download
ADD . /go-ethereum
RUN cd /go-ethereum && make geth
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
# Pull Geth into a second stage deploy alpine container
FROM alpine:latest
@ -14,3 +24,10 @@ COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/
EXPOSE 8545 8546 30303 30303/udp
ENTRYPOINT ["geth"]
# Add some metadata labels to help programmatic image consumption
ARG COMMIT=""
ARG VERSION=""
ARG BUILDNUM=""
LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM"

View file

@ -1,10 +1,27 @@
# Build Geth in a stock Go builder container
FROM golang:1.15-alpine as builder
# Support setting various labels on the final image
ARG COMMIT=""
ARG VERSION=""
ARG BUILDNUM=""
RUN apk add --no-cache make gcc musl-dev linux-headers git
# Build Geth in a stock Go builder container
FROM golang:1.26-alpine AS builder
RUN apk add --no-cache gcc musl-dev linux-headers git
# Get dependencies - will also be cached if we won't change go.mod/go.sum
COPY go.mod /go-ethereum/
COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download
ADD . /go-ethereum
RUN cd /go-ethereum && make all
# This is not strictly necessary, but it matches the "Dockerfile" steps, thus
# makes it so that under certain circumstances, the docker layer can be cached,
# and the builder can jump to the next (build all) command, with the go cache fully loaded.
#
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
RUN cd /go-ethereum && go run build/ci.go install -static
# Pull all binaries into a second stage deploy alpine container
FROM alpine:latest
@ -13,3 +30,10 @@ RUN apk add --no-cache ca-certificates
COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/
EXPOSE 8545 8546 30303 30303/udp
# Add some metadata labels to help programmatic image consumption
ARG COMMIT=""
ARG VERSION=""
ARG BUILDNUM=""
LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM"

145
Makefile
View file

@ -2,147 +2,62 @@
# with Go source code. If you know what GOPATH is then you probably
# don't need to bother with make.
.PHONY: geth android ios geth-cross evm all test clean
.PHONY: geth-linux geth-linux-386 geth-linux-amd64 geth-linux-mips64 geth-linux-mips64le
.PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
.PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64
.PHONY: geth-windows geth-windows-386 geth-windows-amd64
.PHONY: geth evm all test lint fmt clean devtools help
GOBIN = ./build/bin
GO ?= latest
GORUN = env GO111MODULE=on go run
GORUN = go run
#? geth: Build geth.
geth:
$(GORUN) build/ci.go install ./cmd/geth
@echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth."
#? evm: Build evm.
evm:
$(GORUN) build/ci.go install ./cmd/evm
@echo "Done building."
@echo "Run \"$(GOBIN)/evm\" to launch evm."
#? all: Build all packages and executables.
all:
$(GORUN) build/ci.go install
android:
$(GORUN) build/ci.go aar --local
@echo "Done building."
@echo "Import \"$(GOBIN)/geth.aar\" to use the library."
@echo "Import \"$(GOBIN)/geth-sources.jar\" to add javadocs"
@echo "For more info see https://stackoverflow.com/questions/20994336/android-studio-how-to-attach-javadoc"
ios:
$(GORUN) build/ci.go xcode --local
@echo "Done building."
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
#? test: Run the tests.
test: all
$(GORUN) build/ci.go test
#? lint: Run certain pre-selected linters.
lint: ## Run linters.
$(GORUN) build/ci.go lint
#? fmt: Ensure consistent code formatting.
fmt:
gofmt -s -w $(shell find . -name "*.go")
#? clean: Clean go cache, built executables, and the auto generated folder.
clean:
env GO111MODULE=on go clean -cache
go clean -cache
rm -fr build/_workspace/pkg/ $(GOBIN)/*
# The devtools target installs tools required for 'go generate'.
# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'.
#? devtools: Install recommended developer tools.
devtools:
env GOBIN= go get -u golang.org/x/tools/cmd/stringer
env GOBIN= go get -u github.com/kevinburke/go-bindata/go-bindata
env GOBIN= go get -u github.com/fjl/gencodec
env GOBIN= go get -u github.com/golang/protobuf/protoc-gen-go
env GOBIN= go install golang.org/x/tools/cmd/stringer@latest
env GOBIN= go install github.com/fjl/gencodec@latest
env GOBIN= go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
env GOBIN= go install ./cmd/abigen
@type "npm" 2> /dev/null || echo 'Please install node.js and npm'
@type "solc" 2> /dev/null || echo 'Please install solc'
@type "protoc" 2> /dev/null || echo 'Please install protoc'
# Cross Compilation Targets (xgo)
geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios
@echo "Full cross compilation done:"
@ls -ld $(GOBIN)/geth-*
geth-linux: geth-linux-386 geth-linux-amd64 geth-linux-arm geth-linux-mips64 geth-linux-mips64le
@echo "Linux cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-*
geth-linux-386:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/386 -v ./cmd/geth
@echo "Linux 386 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep 386
geth-linux-amd64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/amd64 -v ./cmd/geth
@echo "Linux amd64 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep amd64
geth-linux-arm: geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
@echo "Linux ARM cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm
geth-linux-arm-5:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-5 -v ./cmd/geth
@echo "Linux ARMv5 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm-5
geth-linux-arm-6:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-6 -v ./cmd/geth
@echo "Linux ARMv6 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm-6
geth-linux-arm-7:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-7 -v ./cmd/geth
@echo "Linux ARMv7 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm-7
geth-linux-arm64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm64 -v ./cmd/geth
@echo "Linux ARM64 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm64
geth-linux-mips:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPS cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep mips
geth-linux-mipsle:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mipsle --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPSle cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep mipsle
geth-linux-mips64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips64 --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPS64 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep mips64
geth-linux-mips64le:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips64le --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPS64le cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep mips64le
geth-darwin: geth-darwin-386 geth-darwin-amd64
@echo "Darwin cross compilation done:"
@ls -ld $(GOBIN)/geth-darwin-*
geth-darwin-386:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=darwin/386 -v ./cmd/geth
@echo "Darwin 386 cross compilation done:"
@ls -ld $(GOBIN)/geth-darwin-* | grep 386
geth-darwin-amd64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=darwin/amd64 -v ./cmd/geth
@echo "Darwin amd64 cross compilation done:"
@ls -ld $(GOBIN)/geth-darwin-* | grep amd64
geth-windows: geth-windows-386 geth-windows-amd64
@echo "Windows cross compilation done:"
@ls -ld $(GOBIN)/geth-windows-*
geth-windows-386:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=windows/386 -v ./cmd/geth
@echo "Windows 386 cross compilation done:"
@ls -ld $(GOBIN)/geth-windows-* | grep 386
geth-windows-amd64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=windows/amd64 -v ./cmd/geth
@echo "Windows amd64 cross compilation done:"
@ls -ld $(GOBIN)/geth-windows-* | grep amd64
#? help: Get more info on make commands.
help: Makefile
@echo ''
@echo 'Usage:'
@echo ' make [target]'
@echo ''
@echo 'Targets:'
@sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /'

249
README.md
View file

@ -1,22 +1,23 @@
## Go Ethereum
Official Golang implementation of the Ethereum protocol.
Golang execution layer implementation of the Ethereum protocol.
[![API Reference](
https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667
https://pkg.go.dev/badge/github.com/ethereum/go-ethereum
)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc)
[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum)
[![Travis](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum)
[![Travis](https://app.travis-ci.com/ethereum/go-ethereum.svg?branch=master)](https://app.travis-ci.com/github/ethereum/go-ethereum)
[![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/nthXNEv)
[![Twitter](https://img.shields.io/twitter/follow/go_ethereum)](https://x.com/go_ethereum)
Automated builds are available for stable releases and the unstable master branch. Binary
archives are published at https://geth.ethereum.org/downloads/.
## Building the source
For prerequisites and detailed build instructions please read the [Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum) on the wiki.
For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth).
Building `geth` requires both a Go (version 1.13 or later) and a C compiler. You can install
Building `geth` requires both a Go (version 1.23 or later) and a C compiler. You can install
them using your favourite package manager. Once the dependencies are installed, run
```shell
@ -34,45 +35,61 @@ make all
The go-ethereum project comes with several wrappers/executables found in the `cmd`
directory.
| Command | Description |
| :-----------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options) for command line options. |
| `abigen` | Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) wiki page for details. |
| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. |
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |
| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/ethereum/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/ethereum/rpc-tests/blob/master/README.md) for details. |
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://github.com/ethereum/wiki/wiki/RLP)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
| `puppeth` | a CLI wizard that aids in creating a new Ethereum network. |
| Command | Description |
| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. |
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. |
| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. |
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. |
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
## Running `geth`
Going through all the possible command line flags is out of scope here (please consult our
[CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)),
[CLI Wiki page](https://geth.ethereum.org/docs/fundamentals/command-line-options)),
but we've enumerated a few common parameter combos to get you up to speed quickly
on how you can run your own `geth` instance.
### Hardware Requirements
Minimum:
* CPU with 4+ cores
* 8GB RAM
* 1TB free storage space to sync the Mainnet
* 8 MBit/sec download Internet service
Recommended:
* Fast CPU with 8+ cores
* 16GB+ RAM
* High-performance SSD with at least 1TB of free space
* 25+ MBit/sec download Internet service
### Full node on the main Ethereum network
By far the most common scenario is people wanting to simply interact with the Ethereum
network: create accounts; transfer funds; deploy and interact with contracts. For this
particular use-case the user doesn't care about years-old historical data, so we can
fast-sync quickly to the current state of the network. To do so:
particular use case, the user doesn't care about years-old historical data, so we can
sync quickly to the current state of the network. To do so:
```shell
$ geth console
```
This command will:
* Start `geth` in fast sync mode (default, can be changed with the `--syncmode` flag),
* Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag),
causing it to download more data in exchange for avoiding processing the entire history
of the Ethereum network, which is very CPU intensive.
* Start up `geth`'s built-in interactive [JavaScript console](https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console),
(via the trailing `console` subcommand) through which you can invoke all official [`web3` methods](https://github.com/ethereum/wiki/wiki/JavaScript-API)
as well as `geth`'s own [management APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs).
This tool is optional and if you leave it out you can always attach to an already running
* Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console),
(via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md)
(note: the `web3` version bundled within `geth` is very old, and not up to date with official docs),
as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc).
This tool is optional and if you leave it out you can always attach it to an already running
`geth` instance with `geth attach`.
### A Full node on the Görli test network
### A Full node on the Holesky test network
Transitioning towards developers, if you'd like to play around with creating Ethereum
contracts, you almost certainly would like to do that without any real money involved until
@ -81,53 +98,31 @@ network, you want to join the **test** network with your node, which is fully eq
the main network, but with play-Ether only.
```shell
$ geth --goerli console
$ geth --holesky console
```
The `console` subcommand has the exact same meaning as above and they are equally
useful on the testnet too. Please, see above for their explanations if you've skipped here.
The `console` subcommand has the same meaning as above and is equally
useful on the testnet too.
Specifying the `--goerli` flag, however, will reconfigure your `geth` instance a bit:
Specifying the `--holesky` flag, however, will reconfigure your `geth` instance a bit:
* Instead of connecting the main Ethereum network, the client will connect to the Görli
* Instead of connecting to the main Ethereum network, the client will connect to the Holesky
test network, which uses different P2P bootnodes, different network IDs and genesis
states.
* Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth`
will nest itself one level deeper into a `goerli` subfolder (`~/.ethereum/goerli` on
will nest itself one level deeper into a `holesky` subfolder (`~/.ethereum/holesky` on
Linux). Note, on OSX and Linux this also means that attaching to a running testnet node
requires the use of a custom endpoint since `geth attach` will try to attach to a
production node endpoint by default, e.g.,
`geth attach <datadir>/goerli/geth.ipc`. Windows users are not affected by
`geth attach <datadir>/holesky/geth.ipc`. Windows users are not affected by
this.
*Note: Although there are some internal protective measures to prevent transactions from
crossing over between the main network and test network, you should make sure to always
use separate accounts for play-money and real-money. Unless you manually move
*Note: Although some internal protective measures prevent transactions from
crossing over between the main network and test network, you should always
use separate accounts for play and real money. Unless you manually move
accounts, `geth` will by default correctly separate the two networks and will not make any
accounts available between them.*
### Full node on the Rinkeby test network
Go Ethereum also supports connecting to the older proof-of-authority based test network
called [*Rinkeby*](https://www.rinkeby.io) which is operated by members of the community.
```shell
$ geth --rinkeby console
```
### Full node on the Ropsten test network
In addition to Görli and Rinkeby, Geth also supports the ancient Ropsten testnet. The
Ropsten test network is based on the Ethash proof-of-work consensus algorithm. As such,
it has certain extra overhead and is more susceptible to reorganization attacks due to the
network's low difficulty/security.
```shell
$ geth --ropsten console
```
*Note: Older Geth configurations store the Ropsten database in the `testnet` subdirectory.*
### Configuration
As an alternative to passing the numerous flags to the `geth` binary, you can also pass a
@ -137,15 +132,13 @@ configuration file via:
$ geth --config /path/to/your_config.toml
```
To get an idea how the file should look like you can use the `dumpconfig` subcommand to
To get an idea of how the file should look like you can use the `dumpconfig` subcommand to
export your existing configuration:
```shell
$ geth --your-favourite-flags dumpconfig
```
*Note: This works only with `geth` v1.6.0 and above.*
#### Docker quick start
One of the quickest ways to get Ethereum up and running on your machine is by using
@ -157,21 +150,21 @@ docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
ethereum/client-go
```
This will start `geth` in fast-sync mode with a DB memory allowance of 1GB just as the
This will start `geth` in snap-sync mode with a DB memory allowance of 1GB, as the
above command does. It will also create a persistent volume in your home directory for
saving your blockchain as well as map the default ports. There is also an `alpine` tag
available for a slim version of the image.
Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers
and/or hosts. By default, `geth` binds to the local interface and RPC endpoints is not
and/or hosts. By default, `geth` binds to the local interface and RPC endpoints are not
accessible from the outside.
### Programmatically interfacing `geth` nodes
As a developer, sooner rather than later you'll want to start interacting with `geth` and the
Ethereum network via your own programs and not manually through the console. To aid
this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://github.com/ethereum/wiki/wiki/JSON-RPC)
and [`geth` specific APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)).
this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.org/en/developers/docs/apis/json-rpc/)
and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)).
These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based
platforms, and named pipes on Windows).
@ -186,14 +179,13 @@ HTTP based JSON-RPC API options:
* `--http.addr` HTTP-RPC server listening interface (default: `localhost`)
* `--http.port` HTTP-RPC server listening port (default: `8545`)
* `--http.api` API's offered over the HTTP-RPC interface (default: `eth,net,web3`)
* `--http.corsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced)
* `--http.corsdomain` Comma separated list of domains from which to accept cross-origin requests (browser enforced)
* `--ws` Enable the WS-RPC server
* `--ws.addr` WS-RPC server listening interface (default: `localhost`)
* `--ws.port` WS-RPC server listening port (default: `8546`)
* `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`)
* `--ws.origins` Origins from which to accept websockets requests
* `--ws.origins` Origins from which to accept WebSocket requests
* `--ipcdisable` Disable the IPC-RPC server
* `--ipcapi` API's offered over the IPC-RPC interface (default: `admin,debug,eth,miner,net,personal,shh,txpool,web3`)
* `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it)
You'll need to use your own programming environments' capabilities (libraries, tools, etc) to
@ -212,124 +204,23 @@ APIs!**
Maintaining your own private network is more involved as a lot of configurations taken for
granted in the official networks need to be manually set up.
#### Defining the private genesis state
Unfortunately since [the Merge](https://ethereum.org/en/roadmap/merge/) it is no longer possible
to easily set up a network of geth nodes without also setting up a corresponding beacon chain.
First, you'll need to create the genesis state of your networks, which all nodes need to be
aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`):
There are three different solutions depending on your use case:
```json
{
"config": {
"chainId": <arbitrary positive integer>,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}
```
The above fields should be fine for most purposes, although we'd recommend changing
the `nonce` to some random value so you prevent unknown remote nodes from being able
to connect to you. If you'd like to pre-fund some accounts for easier testing, create
the accounts and populate the `alloc` field with their addresses.
```json
"alloc": {
"0x0000000000000000000000000000000000000001": {
"balance": "111111111"
},
"0x0000000000000000000000000000000000000002": {
"balance": "222222222"
}
}
```
With the genesis state defined in the above JSON file, you'll need to initialize **every**
`geth` node with it prior to starting it up to ensure all blockchain parameters are correctly
set:
```shell
$ geth init path/to/genesis.json
```
#### Creating the rendezvous point
With all nodes that you want to run initialized to the desired genesis state, you'll need to
start a bootstrap node that others can use to find each other in your network and/or over
the internet. The clean way is to configure and run a dedicated bootnode:
```shell
$ bootnode --genkey=boot.key
$ bootnode --nodekey=boot.key
```
With the bootnode online, it will display an [`enode` URL](https://github.com/ethereum/wiki/wiki/enode-url-format)
that other nodes can use to connect to it and exchange peer information. Make sure to
replace the displayed IP address information (most probably `[::]`) with your externally
accessible IP to get the actual `enode` URL.
*Note: You could also use a full-fledged `geth` node as a bootnode, but it's the less
recommended way.*
#### Starting up your member nodes
With the bootnode operational and externally reachable (you can try
`telnet <ip> <port>` to ensure it's indeed reachable), start every subsequent `geth`
node pointed to the bootnode for peer discovery via the `--bootnodes` flag. It will
probably also be desirable to keep the data directory of your private network separated, so
do also specify a custom `--datadir` flag.
```shell
$ geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>
```
*Note: Since your network will be completely cut off from the main and test networks, you'll
also need to configure a miner to process transactions and create new blocks for you.*
#### Running a private miner
Mining on the public Ethereum network is a complex task as it's only feasible using GPUs,
requiring an OpenCL or CUDA enabled `ethminer` instance. For information on such a
setup, please consult the [EtherMining subreddit](https://www.reddit.com/r/EtherMining/)
and the [ethminer](https://github.com/ethereum-mining/ethminer) repository.
In a private network setting, however a single CPU miner instance is more than enough for
practical purposes as it can produce a stable stream of blocks at the correct intervals
without needing heavy resources (consider running on a single thread, no need for multiple
ones either). To start a `geth` instance for mining, run it with all your usual flags, extended
by:
```shell
$ geth <usual-flags> --mine --miner.threads=1 --etherbase=0x0000000000000000000000000000000000000000
```
Which will start mining blocks and transactions on a single CPU thread, crediting all
proceedings to the account specified by `--etherbase`. You can further tune the mining
by changing the default gas limit blocks converge to (`--targetgaslimit`) and the price
transactions are accepted at (`--gasprice`).
* If you are looking for a simple way to test smart contracts from go in your CI, you can use the [Simulated Backend](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings#blockchain-simulator).
* If you want a convenient single node environment for testing, you can use our [Dev Mode](https://geth.ethereum.org/docs/developers/dapp-developer/dev-mode).
* If you are looking for a multiple node test network, you can set one up quite easily with [Kurtosis](https://geth.ethereum.org/docs/fundamentals/kurtosis).
## Contribution
Thank you for considering to help out with the source code! We welcome contributions
Thank you for considering helping out with the source code! We welcome contributions
from anyone on the internet, and are grateful for even the smallest of fixes!
If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request
for the maintainers to review and merge into the main code base. If you wish to submit
more complex changes though, please check up with the core devs first on [our gitter channel](https://gitter.im/ethereum/go-ethereum)
more complex changes though, please check up with the core devs first on [our Discord Server](https://discord.gg/invite/nthXNEv)
to ensure those changes are in line with the general philosophy of the project and/or get
some early feedback which can make both your efforts much lighter as well as our review
and merge procedures quick and simple.
@ -344,16 +235,22 @@ Please make sure your contributions adhere to our coding guidelines:
* Commit messages should be prefixed with the package(s) they modify.
* E.g. "eth, rpc: make trace configs optional"
Please see the [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide)
for more details on configuring your environment, managing project dependencies, and
testing procedures.
### Contributing to geth.ethereum.org
For contributions to the [go-ethereum website](https://geth.ethereum.org), please checkout and raise pull requests against the `website` branch.
For more detailed instructions please see the `website` branch [README](https://github.com/ethereum/go-ethereum/tree/website#readme) or the
[contributing](https://geth.ethereum.org/docs/developers/geth-developer/contributing) page of the website.
## License
The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the
[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html),
also included in our repository in the `COPYING.LESSER` file.
The go-ethereum binaries (i.e. all code inside of the `cmd` directory) is licensed under the
The go-ethereum binaries (i.e. all code inside of the `cmd` directory) are licensed under the
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also
included in our repository in the `COPYING` file.

View file

@ -2,34 +2,32 @@
## Supported Versions
Please see Releases. We recommend to use the most recent released version.
Please see [Releases](https://github.com/ethereum/go-ethereum/releases). We recommend using the [most recently released version](https://github.com/ethereum/go-ethereum/releases/latest).
## Audit reports
Audit reports are published in the `docs` folder: https://github.com/ethereum/go-ethereum/tree/master/docs/audits
| Scope | Date | Report Link |
| ------- | ------- | ----------- |
| `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) |
| `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) |
| `Discv5` | 20191015 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf) |
| `Discv5` | 20200124 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf) |
## Reporting a Vulnerability
**Please do not file a public ticket** mentioning the vulnerability.
To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org.
To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org. Please read the [disclosure page](https://github.com/ethereum/go-ethereum/security/advisories?state=published) for more information about publicly disclosed security vulnerabilities.
The following key may be used to communicate sensitive information to developers.
Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A`
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaY
neAk3Bp182GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9
@ -42,79 +40,57 @@ QAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+FnQOUgg2H
h8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c
2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZ
EZCjMXxB8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQAB
tDlFdGhlcmV1bSBGb3VuZGF0aW9uIFNlY3VyaXR5IFRlYW0gPHNlY3VyaXR5QGV0
aGVyZXVtLm9yZz6JAj4EEwECACgCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheA
BQJaCWH6BQkFo2BYAAoJEOiNMzT6X2oK+DEP/3H6dxkm0hvHZKoHLVuuxcu3EHYo
k5sd3MMWPrZSN8qzZnY7ayEDMxnarWOizc+2jfOxfJlzX/g8lR1/fsHdWPFPhPoV
Qk8ygrHn1H8U8+rpw/U03BqmqHpYCDzJ+CIis9UWROniqXw1nuqu/FtWOsdWxNKh
jUo6k/0EsaXsxRPzgJv7fEUcVcQ7as/C3x9sy3muc2gvgA4/BKoGPb1/U0GuA8lV
fDIDshAggmnSUAg+TuYSAAdoFQ1sKwFMPigcLJF2eyKuK3iUyixJrec/c4LSf3wA
cGghbeuqI8INP0Y2zvXDQN2cByxsFAuoZG+m0cyKGaDH2MVUvOKKYqn/03qvrf15
AWAsW0l0yQwOTCo3FbsNzemClm5Bj/xH0E4XuwXwChcMCMOWJrFoxyvCEI+keoQc
c08/a8/MtS7vBAABXwOziSmm6CNqmzpWrh/fDrjlJlba9U3MxzvqU3IFlTdMratv
6V+SgX+L25lCzW4NxxUavoB8fAlvo8lxpHKo24FP+RcLQ8XqkU3RiUsgRjQRFOqQ
TaJcsp8mimmiYyf24mNu6b48pi+a5c/eQR9w59emeEUZqsJU+nqv8BWIIp7o4Agh
NYnKjkhPlY5e1fLVfAHIADZFynWwRPkPMJSrBiP5EtcOFxQGHGjRxU/KjXkvE0hV
xYb1PB8pWMTu/beeiQI+BBMBAgAoBQJYJd7YAhsDBQkB4TOABgsJCAcDAgYVCAIJ
CgsEFgIDAQIeAQIXgAAKCRDojTM0+l9qCplDD/9IZ2i+m1cnqQKtiyHbyFGx32oL
fzqPylX2bOG5DPsSTorSUdJMGVfT04oVxXc4S/2DVnNvi7RAbSiLapCWSplgtBOj
j1xlblOoXxT3m7s1XHGCX5tENxI9fVSSPVKJn+fQaWpPB2MhBA+1lUI6GJ+11T7K
J8LrP/fiw1/nOb7rW61HW44Gtyox23sA/d1+DsFVaF8hxJlNj5coPKr8xWzQ8pQl
juzdjHDukjevuw4rRmRq9vozvj9keEU9XJ5dldyEVXFmdDk7KT0p0Rla9nxYhzf/
r/Bv8Bzy0HCWRb2D31BjXXGG05oVnYmNGxGFxYja4MwgrMmne3ilEVjfUJsapsqi
w41BAyQgIdfREulYN7ahsF5PrjVAqBd9IGtE8ULelF2SQxEBQBngEkP0ahP6tRAL
i7/CBjPKOyKijtqVny7qrGOnU2ygcA88/WDibexDhrjz0Gx8WmErU7rIWZiZ5u4Y
vJYVRo0+6rBCXRPeSJfiP5h1p17Anr2l42boAYslfcrzquB8MHtrNcyn650OLtHG
nbxgIdniKrpuzGN6Opw+O2id2JhD1/1p4SOemwAmthplr1MIyOHNP3q93rEj2J7h
5zPS/AJuKkMDFUpslPNLQjCOwPXtdzL7/kUZGBSyez1T3TaW1uY6l9XaJJRaSn+v
1zPgfp4GJ3lPs4AlAbQ0RXRoZXJldW0gRm91bmRhdGlvbiBCdWcgQm91bnR5IDxi
b3VudHlAZXRoZXJldW0ub3JnPokCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYC
AwECHgECF4AFAloJYfoFCQWjYFgACgkQ6I0zNPpfagoENg/+LnSaVeMxiGVtcjWl
b7Xd73yrEy4uxiESS1AalW9mMf7oZzfI05f7QIQlaLAkNac74vZDJbPKjtb7tpMO
RFhRZMCveq6CPKU6pd1SI8IUVUKwpEe6AJP3lHdVP57dquieFE2HlYKm6uHbCGWU
0cjyTA+uu2KbgCHGmofsPY/xOcZLGEHTHqa5w60JJAQm+BSDKnw8wTyrxGvA3EK/
ePSvOZMYa+iw6vYuZeBIMbdiXR/A2keBi3GuvqB8tDMj7P22TrH5mVDm3zNqGYD6
amDPeiWp4cztY3aZyLcgYotqXPpDceZzDn+HopBPzAb/llCdE7bVswKRhphVMw4b
bhL0R/TQY7Sf6TK2LKSBrjv0DWOSijikE71SJcBnJvHU7EpKrQQ0lMGclm3ynyji
Nf0YTPXQt4I+fwTmOew2GFeK3UytNWbWI7oXX7Nm4bj9bhf3IJ0kmZb/Gs73+xII
e7Rz52Mby436tWyQIQiF9ITYNGvNf53TwBBZMn0pKPiTyr3Ur7FHEotkEOFNh1//
4zQY10XxuBdLrYGyZ4V8xHJM+oKre8Eg2R9qHXVbjvErHE+7CvgnV7YUip0criPr
BlKRvuoJaSliH2JFhSjWVrkPmFGrWN0BAx10yIqMnEplfKeHf4P9Elek3oInS8WP
G1zJG6s/t5+hQK0X37+TB+6rd3GJAj4EEwECACgFAlgl4TsCGwMFCQHhM4AGCwkI
BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEOiNMzT6X2oKzf8P/iIKd77WHTbp4pMN
8h52HyZJtDJmjA1DPZrbGl1TesW/Z9uTd12txlgqZnbG2GfN9+LSP6EOPzR6v2xC
OVhR+RdWhZDJJuQCVS7lJIqQrZgmeTZG0TyQPZdLjVFBOrrhVwYX+HXbu429IzHr
URf5InyR1QgqOXyElDYS6e28HFqvaoA0DWTWDDqOLPVl+U5fuceIE2XXdv3AGLeP
Yf8J5MPobjPiZtBqI6S6iENY2Yn35qLX+axeC/iYSCHVtFuCCIdb/QYR1ZZV8Ps/
aI9DwC7LU+YfPw7iqCIoqxSeA3o1PORkdSigEg3jtfRv5UqVo9a0oBb9jdoADsat
F/gW0E7mto3XGOiaR0eB9SSdsM3x7Bz4A0HIGNaxpZo1RWqlO91leP4c13Px7ISv
5OGXfLg+M8qb+qxbGd1HpitGi9s1y1aVfEj1kOtZ0tN8eu+Upg5WKwPNBDX3ar7J
9NCULgVSL+E79FG+zXw62gxiQrLfKzm4wU/9L5wVkwQnm29hLJ0tokrSBZFnc/1l
7OC+GM63tYicKkY4rqmoWUeYx7IwFH9mtDtvR1RxO85RbQhZizwpZpdpRkH0DqZu
ZJRmRa5r7rPqmfa7d+VIFhz2Xs8pJMLVqxTsLKcLglmjw7aOrYG0SWeH7YraXWGD
N3SlvSBiVwcK7QUKzLLvpadLwxfsuQINBFgl3tgBEACbgq6HTN5gEBi0lkD/MafI
nmNi+59U5gRGYqk46WlfRjhHudXjDpgD0lolGb4hYontkMaKRlCg2Rvgjvk3Zve0
PKWjKw7gr8YBa9fMFY8BhAXI32OdyI9rFhxEZFfWAfwKVmT19BdeAQRFvcfd+8w8
f1XVc+zddULMJFBTr+xKDlIRWwTkdLPQeWbjo0eHl/g4tuLiLrTxVbnj26bf+2+1
DbM/w5VavzPrkviHqvKe/QP/gay4QDViWvFgLb90idfAHIdsPgflp0VDS5rVHFL6
D73rSRdIRo3I8c8mYoNjSR4XDuvgOkAKW9LR3pvouFHHjp6Fr0GesRbrbb2EG66i
PsR99MQ7FqIL9VMHPm2mtR+XvbnKkH2rYyEqaMbSdk29jGapkAWle4sIhSKk749A
4tGkHl08KZ2N9o6GrfUehP/V2eJLaph2DioFL1HxRryrKy80QQKLMJRekxigq8gr
eW8xB4zuf9Mkuou+RHNmo8PebHjFstLigiD6/zP2e+4tUmrT0/JTGOShoGMl8Rt0
VRxdPImKun+4LOXbfOxArOSkY6i35+gsgkkSy1gTJE0BY3S9auT6+YrglY/TWPQ9
IJxWVOKlT+3WIp5wJu2bBKQ420VLqDYzkoWytel/bM1ACUtipMiIVeUs2uFiRjpz
A1Wy0QHKPTdSuGlJPRrfcQARAQABiQIlBBgBAgAPAhsMBQJaCWIIBQkFo2BYAAoJ
EOiNMzT6X2oKgSwQAKKs7BGF8TyZeIEO2EUK7R2bdQDCdSGZY06tqLFg3IHMGxDM
b/7FVoa2AEsFgv6xpoebxBB5zkhUk7lslgxvKiSLYjxfNjTBltfiFJ+eQnf+OTs8
KeR51lLa66rvIH2qUzkNDCCTF45H4wIDpV05AXhBjKYkrDCrtey1rQyFp5fxI+0I
Q1UKKXvzZK4GdxhxDbOUSd38MYy93nqcmclGSGK/gF8XiyuVjeifDCM6+T1NQTX0
K9lneidcqtBDvlggJTLJtQPO33o5EHzXSiud+dKth1uUhZOFEaYRZoye1YE3yB0T
NOOE8fXlvu8iuIAMBSDL9ep6sEIaXYwoD60I2gHdWD0lkP0DOjGQpi4ouXM3Edsd
5MTi0MDRNTij431kn8T/D0LCgmoUmYYMBgbwFhXr67axPZlKjrqR0z3F/Elv0ZPP
cVg1tNznsALYQ9Ovl6b5M3cJ5GapbbvNWC7yEE1qScl9HiMxjt/H6aPastH63/7w
cN0TslW+zRBy05VNJvpWGStQXcngsSUeJtI1Gd992YNjUJq4/Lih6Z1TlwcFVap+
cTcDptoUvXYGg/9mRNNPZwErSfIJ0Ibnx9wPVuRN6NiCLOt2mtKp2F1pM6AOQPpZ
85vEh6I8i6OaO0w/Z0UHBwvpY6jDUliaROsWUQsqz78Z34CVj4cy6vPW2EF4
=r6KK
tDRFdGhlcmV1bSBGb3VuZGF0aW9uIEJ1ZyBCb3VudHkgPGJvdW50eUBldGhlcmV1
bS5vcmc+iQJVBBMBCAA/AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBK6W
7ZaeR5sAhPPhf+iNMzT6X2oKBQJl2LD9BQkRdTklAAoJEOiNMzT6X2oKYYYQALkV
wJjWYoVoMuw9D1ybQo4Sqyp6D/XYHXSpqZDO9RlADQisYBfuO7EW75evgZ+54Ajc
8gZ2BUkFcSR9z2t0TEkUyjmPDZsaElTTP2Boa2GG5pyziEM6t1cMMY1sP1aotx9H
DYwCeMmDv0wTMi6v0C6+/in2hBxbGALRbQKWKd/5ss4OEPe37hG9zAJcBYZg2tes
O7ceg7LHZpNC1zvMUrBY6os74FJ437f8bankqvVE83/dvTcCDhMsei9LiWS2uo26
qiyqeR9lZEj8W5F6UgkQH+UOhamJ9UB3N/h//ipKrwtiv0+jQm9oNG7aIAi3UJgD
CvSod87H0l7/U8RWzyam/r8eh4KFM75hIVtqEy5jFV2z7x2SibXQi7WRfAysjFLp
/li8ff6kLDR9IMATuMSF7Ol0O9JMRfSPjRZRtVOwYVIBla3BhfMrjvMMcZMAy/qS
DWx2iFYDMGsswv7hp3lsFOaa1ju95ClZZk3q/z7u5gH7LFAxR0jPaW48ay3CFylW
sDpQpO1DWb9uXBdhOU+MN18uSjqzocga3Wz2C8jhWRvxyFf3SNIybm3zk6W6IIoy
6KmwSRZ30oxizy6zMYw1qJE89zjjumzlZAm0R/Q4Ui+WJhlSyrYbqzqdxYuLgdEL
lgKfbv9/t8tNXGGSuCe5L7quOv9k7l2+QmLlg+SJtDlFdGhlcmV1bSBGb3VuZGF0
aW9uIFNlY3VyaXR5IFRlYW0gPHNlY3VyaXR5QGV0aGVyZXVtLm9yZz6JAlUEEwEI
AD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEErpbtlp5HmwCE8+F/6I0z
NPpfagoFAmXYsP4FCRF1OSUACgkQ6I0zNPpfagoUGA/+LVzXUJrsfi8+ADMF1hru
wFDcY1r+vM4Ovbk1NhCc/DnV5VG40j5FiQpE81BNiH59sYeZkQm9jFbwevK7Zpuq
RZaG2WGiwU/11xrt5/Qjq7T+vEtd94546kFcBnP8uexZqP4dTi4LHa2on8aRbwzN
7RjCpCQhy1TUuk47dyOR1y3ZHrpTwkHpuhwgffaWtxgSyCMYz7fsd5Ukh3eE+Ani
90CIUieve2U3o+WPxBD9PRaIPg6LmBhfGxGvC/6tqY9W3Z9xEOVDxC4wdYppQzsg
Pg7bNnVmlFWHsEk8FuMfY8nTqY3/ojhJxikWKz2V3Y2AbsLEXCvrEg6b4FvmsS97
8ifEBbFXU8hvMSpMLtO7vLamWyOHq41IXWH6HLNLhDfDzTfpAJ8iYDKGj72YsMzF
0fIjPa6mniMB2RmREAM0Jas3M/6DUw1EzwK1iQofIBoCRPIkR5mxmzjcRB6tVdQa
on20/9YTKKBUQAdK0OWW8j1euuULDgNdkN2LBXdQLy/JcQiggU8kOCKL/Lmj5HWP
FNT9rYfnjmCuux3UfJGfhPryujEA0CdIfq1Qf4ldOVzpWYjsMn+yQxAQTorAzF3z
iYddP2cw/Nvookay8xywKJnDsaRaWqdQ8Ceox3qSB4LCjQRNR5c3HfvGm3EBdEyI
zEEpjZ6GHa05DCajqKjtjlm5Ag0EWCXe2AEQAJuCrodM3mAQGLSWQP8xp8ieY2L7
n1TmBEZiqTjpaV9GOEe51eMOmAPSWiUZviFiie2QxopGUKDZG+CO+Tdm97Q8paMr
DuCvxgFr18wVjwGEBcjfY53Ij2sWHERkV9YB/ApWZPX0F14BBEW9x937zDx/VdVz
7N11QswkUFOv7EoOUhFbBOR0s9B5ZuOjR4eX+Di24uIutPFVuePbpt/7b7UNsz/D
lVq/M+uS+Ieq8p79A/+BrLhANWJa8WAtv3SJ18Ach2w+B+WnRUNLmtUcUvoPvetJ
F0hGjcjxzyZig2NJHhcO6+A6QApb0tHem+i4UceOnoWvQZ6xFuttvYQbrqI+xH30
xDsWogv1Uwc+baa1H5e9ucqQfatjISpoxtJ2Tb2MZqmQBaV7iwiFIqTvj0Di0aQe
XTwpnY32joat9R6E/9XZ4ktqmHYOKgUvUfFGvKsrLzRBAoswlF6TGKCryCt5bzEH
jO5/0yS6i75Ec2ajw95seMWy0uKCIPr/M/Z77i1SatPT8lMY5KGgYyXxG3RVHF08
iYq6f7gs5dt87ECs5KRjqLfn6CyCSRLLWBMkTQFjdL1q5Pr5iuCVj9NY9D0gnFZU
4qVP7dYinnAm7ZsEpDjbRUuoNjOShbK16X9szUAJS2KkyIhV5Sza4WJGOnMDVbLR
Aco9N1K4aUk9Gt9xABEBAAGJAjwEGAEIACYCGwwWIQSulu2WnkebAITz4X/ojTM0
+l9qCgUCZdiwoAUJEXU4yAAKCRDojTM0+l9qCj2PD/9pbIPRMZtvKIIE+OhOAl/s
qfZJXByAM40ELpUhDHqwbOplIEyvXtWfQ5c+kWlG/LPJ2CgLkHyFQDn6tuat82rH
/5VoZyxp16CBAwEgYdycOr9hMGSVKNIJDfV9Bu6VtZnn6fa/swBzGE7eVpXsIoNr
jeqsogBtzLecG1oHMXRMq7oUqu9c6VNoCx2uxRUOeWW8YuP7h9j6mxIuKKbcpmQ5
RSLNEhJZJsMMFLf8RAQPXmshG1ZixY2ZliNe/TTm6eEfFCw0KcQxoX9LmurLWE9w
dIKgn1/nQ04GFnmtcq3hVxY/m9BvzY1jmZXNd4TdpfrPXhi0W/GDn53ERFPJmw5L
F8ogxzD/ekxzyd9nCCgtzkamtBKDJk35x/MoVWMLjD5k6P+yW7YY4xMQliSJHKss
leLnaPpgDBi4KPtLxPswgFqObcy4TNse07rFO4AyHf11FBwMTEfuODCOMnQTpi3z
Zx6KxvS3BEY36abjvwrqsmt8dJ/+/QXT0e82fo2kJ65sXIszez3e0VUZ8KrMp+wd
X0GWYWAfqXws6HrQFYfIpEE0Vz9gXDxEOTFZ2FoVIvIHyRfyDrAIz3wZLmnLGk1h
l3CDjHF0Wigv0CacIQ1V1aYp3NhIVwAvShQ+qS5nFgik6UZnjjWibobOm3yQDzll
6F7hEeTW+gnXEI2gPjfb5w==
=b5eA
-----END PGP PUBLIC KEY BLOCK-----
```

View file

@ -22,18 +22,20 @@ import (
"errors"
"fmt"
"io"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
// The ABI holds information about a contract's context and available
// invokable methods. It will allow you to type check function calls and
// invocable methods. It will allow you to type check function calls and
// packs data accordingly.
type ABI struct {
Constructor Method
Methods map[string]Method
Events map[string]Event
Errors map[string]Error
// Additional "special" functions introduced in solidity v0.6.0.
// It's separated from the original default fallback. Each contract
@ -82,19 +84,22 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
// since there can't be naming collisions with contracts and events,
// we need to decide whether we're calling a method or an event
// we need to decide whether we're calling a method, event or an error
var args Arguments
if method, ok := abi.Methods[name]; ok {
if len(data)%32 != 0 {
return nil, fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data)
return nil, fmt.Errorf("abi: improperly formatted output: %q - Bytes: %+v", data, data)
}
args = method.Outputs
}
if event, ok := abi.Events[name]; ok {
args = event.Inputs
}
if err, ok := abi.Errors[name]; ok {
args = err.Inputs
}
if args == nil {
return nil, errors.New("abi: could not locate named method or event")
return nil, fmt.Errorf("abi: could not locate named method, event or error: %s", name)
}
return args, nil
}
@ -157,12 +162,13 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
abi.Methods = make(map[string]Method)
abi.Events = make(map[string]Event)
abi.Errors = make(map[string]Error)
for _, field := range fields {
switch field.Type {
case "constructor":
abi.Constructor = NewMethod("", "", Constructor, field.StateMutability, field.Constant, field.Payable, field.Inputs, nil)
case "function":
name := abi.overloadedMethodName(field.Name)
name := ResolveNameConflict(field.Name, func(s string) bool { _, ok := abi.Methods[s]; return ok })
abi.Methods[name] = NewMethod(name, field.Name, Function, field.StateMutability, field.Constant, field.Payable, field.Inputs, field.Outputs)
case "fallback":
// New introduced function type in v0.6.0, check more detail
@ -182,8 +188,12 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
abi.Receive = NewMethod("", "", Receive, field.StateMutability, field.Constant, field.Payable, nil, nil)
case "event":
name := abi.overloadedEventName(field.Name)
name := ResolveNameConflict(field.Name, func(s string) bool { _, ok := abi.Events[s]; return ok })
abi.Events[name] = NewEvent(name, field.Name, field.Anonymous, field.Inputs)
case "error":
// Errors cannot be overloaded or overridden but are inherited,
// no need to resolve the name conflict here.
abi.Errors[field.Name] = NewError(field.Name, field.Inputs)
default:
return fmt.Errorf("abi: could not recognize type %v of field %v", field.Type, field.Name)
}
@ -191,36 +201,6 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
return nil
}
// overloadedMethodName returns the next available name for a given function.
// Needed since solidity allows for function overload.
//
// e.g. if the abi contains Methods send, send1
// overloadedMethodName would return send2 for input send.
func (abi *ABI) overloadedMethodName(rawName string) string {
name := rawName
_, ok := abi.Methods[name]
for idx := 0; ok; idx++ {
name = fmt.Sprintf("%s%d", rawName, idx)
_, ok = abi.Methods[name]
}
return name
}
// overloadedEventName returns the next available name for a given event.
// Needed since solidity allows for event overload.
//
// e.g. if the abi contains events received, received1
// overloadedEventName would return received2 for input received.
func (abi *ABI) overloadedEventName(rawName string) string {
name := rawName
_, ok := abi.Events[name]
for idx := 0; ok; idx++ {
name = fmt.Sprintf("%s%d", rawName, idx)
_, ok = abi.Events[name]
}
return name
}
// MethodById looks up a method by the 4-byte id,
// returns nil if none found.
func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
@ -246,6 +226,17 @@ func (abi *ABI) EventByID(topic common.Hash) (*Event, error) {
return nil, fmt.Errorf("no event with id: %#x", topic.Hex())
}
// ErrorByID looks up an error by the 4-byte id,
// returns nil if none found.
func (abi *ABI) ErrorByID(sigdata [4]byte) (*Error, error) {
for _, errABI := range abi.Errors {
if bytes.Equal(errABI.ID[:4], sigdata[:]) {
return &errABI, nil
}
}
return nil, fmt.Errorf("no error with id: %#x", sigdata[:])
}
// HasFallback returns an indicator whether a fallback function is included.
func (abi *ABI) HasFallback() bool {
return abi.Fallback.Type == Fallback
@ -259,21 +250,65 @@ func (abi *ABI) HasReceive() bool {
// revertSelector is a special function selector for revert reason unpacking.
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
// panicSelector is a special function selector for panic reason unpacking.
var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4]
// panicReasons map is for readable panic codes
// see this linkage for the details
// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require
// the reason string list is copied from ether.js
// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218
var panicReasons = map[uint64]string{
0x00: "generic panic",
0x01: "assert(false)",
0x11: "arithmetic underflow or overflow",
0x12: "division or modulo by zero",
0x21: "enum overflow",
0x22: "invalid encoded storage byte array accessed",
0x31: "out-of-bounds array access; popping on an empty array",
0x32: "out-of-bounds access of an array or bytesN",
0x41: "out of memory",
0x51: "uninitialized function",
}
// UnpackRevert resolves the abi-encoded revert reason. According to the solidity
// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert,
// the provided revert reason is abi-encoded as if it were a call to a function
// `Error(string)`. So it's a special tool for it.
// the provided revert reason is abi-encoded as if it were a call to function
// `Error(string)` or `Panic(uint256)`. So it's a special tool for it.
func UnpackRevert(data []byte) (string, error) {
if len(data) < 4 {
return "", errors.New("invalid data for unpacking")
}
if !bytes.Equal(data[:4], revertSelector) {
switch {
case bytes.Equal(data[:4], revertSelector):
typ, err := NewType("string", "", nil)
if err != nil {
return "", err
}
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err
}
return unpacked[0].(string), nil
case bytes.Equal(data[:4], panicSelector):
typ, err := NewType("uint256", "", nil)
if err != nil {
return "", err
}
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err
}
pCode := unpacked[0].(*big.Int)
// uint64 safety check for future
// but the code is not bigger than MAX(uint64) now
if pCode.IsUint64() {
if reason, ok := panicReasons[pCode.Uint64()]; ok {
return reason, nil
}
}
return fmt.Sprintf("unknown panic code: %#x", pCode), nil
default:
return "", errors.New("invalid data for unpacking")
}
typ, _ := NewType("string", "", nil)
unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err
}
return unpacked[0].(string), nil
}

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/testrand"
)
const jsondata = `
@ -43,6 +44,7 @@ const jsondata = `
{ "type" : "function", "name" : "uint64[2]", "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
{ "type" : "function", "name" : "uint64[]", "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
{ "type" : "function", "name" : "int8", "inputs" : [ { "name" : "inputs", "type" : "int8" } ] },
{ "type" : "function", "name" : "bytes32", "inputs" : [ { "name" : "inputs", "type" : "bytes32" } ] },
{ "type" : "function", "name" : "foo", "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
{ "type" : "function", "name" : "bar", "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
{ "type" : "function", "name" : "slice", "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
@ -68,6 +70,7 @@ var (
String, _ = NewType("string", "", nil)
Bool, _ = NewType("bool", "", nil)
Bytes, _ = NewType("bytes", "", nil)
Bytes32, _ = NewType("bytes32", "", nil)
Address, _ = NewType("address", "", nil)
Uint64Arr, _ = NewType("uint64[]", "", nil)
AddressArr, _ = NewType("address[]", "", nil)
@ -98,6 +101,7 @@ var methods = map[string]Method{
"uint64[]": NewMethod("uint64[]", "uint64[]", Function, "", false, false, []Argument{{"inputs", Uint64Arr, false}}, nil),
"uint64[2]": NewMethod("uint64[2]", "uint64[2]", Function, "", false, false, []Argument{{"inputs", Uint64Arr2, false}}, nil),
"int8": NewMethod("int8", "int8", Function, "", false, false, []Argument{{"inputs", Int8, false}}, nil),
"bytes32": NewMethod("bytes32", "bytes32", Function, "", false, false, []Argument{{"inputs", Bytes32, false}}, nil),
"foo": NewMethod("foo", "foo", Function, "", false, false, []Argument{{"inputs", Uint32, false}}, nil),
"bar": NewMethod("bar", "bar", Function, "", false, false, []Argument{{"inputs", Uint32, false}, {"string", Uint16, false}}, nil),
"slice": NewMethod("slice", "slice", Function, "", false, false, []Argument{{"inputs", Uint32Arr2, false}}, nil),
@ -117,6 +121,7 @@ var methods = map[string]Method{
}
func TestReader(t *testing.T) {
t.Parallel()
abi := ABI{
Methods: methods,
}
@ -148,6 +153,7 @@ func TestReader(t *testing.T) {
}
func TestInvalidABI(t *testing.T) {
t.Parallel()
json := `[{ "type" : "function", "name" : "", "constant" : fals }]`
_, err := JSON(strings.NewReader(json))
if err == nil {
@ -162,10 +168,12 @@ func TestInvalidABI(t *testing.T) {
// TestConstructor tests a constructor function.
// The test is based on the following contract:
// contract TestConstructor {
// constructor(uint256 a, uint256 b) public{}
//
// contract TestConstructor {
// constructor(uint256 a, uint256 b) public{}
// }
func TestConstructor(t *testing.T) {
t.Parallel()
json := `[{ "inputs": [{"internalType": "uint256","name": "a","type": "uint256" },{ "internalType": "uint256","name": "b","type": "uint256"}],"stateMutability": "nonpayable","type": "constructor"}]`
method := NewMethod("", "", Constructor, "nonpayable", false, false, []Argument{{"a", Uint256, false}, {"b", Uint256, false}}, nil)
// Test from JSON
@ -195,6 +203,7 @@ func TestConstructor(t *testing.T) {
}
func TestTestNumbers(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@ -232,6 +241,7 @@ func TestTestNumbers(t *testing.T) {
}
func TestMethodSignature(t *testing.T) {
t.Parallel()
m := NewMethod("foo", "foo", Function, "", false, false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil)
exp := "foo(string,string)"
if m.Sig != exp {
@ -270,6 +280,7 @@ func TestMethodSignature(t *testing.T) {
}
func TestOverloadedMethodSignature(t *testing.T) {
t.Parallel()
json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
@ -292,7 +303,55 @@ func TestOverloadedMethodSignature(t *testing.T) {
check("bar0", "bar(uint256,uint256)", false)
}
func TestCustomErrors(t *testing.T) {
t.Parallel()
json := `[{ "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ],"name": "MyError", "type": "error"} ]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
t.Fatal(err)
}
check := func(name string, expect string) {
if abi.Errors[name].Sig != expect {
t.Fatalf("The signature of overloaded method mismatch, want %s, have %s", expect, abi.Methods[name].Sig)
}
}
check("MyError", "MyError(uint256)")
}
func TestCustomErrorUnpackIntoInterface(t *testing.T) {
t.Parallel()
errorName := "MyError"
json := fmt.Sprintf(`[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"%s","type":"error"}]`, errorName)
abi, err := JSON(strings.NewReader(json))
if err != nil {
t.Fatal(err)
}
type MyError struct {
Sender common.Address
Balance *big.Int
}
sender := testrand.Address()
balance := new(big.Int).SetBytes(testrand.Bytes(8))
encoded, err := abi.Errors[errorName].Inputs.Pack(sender, balance)
if err != nil {
t.Fatal(err)
}
result := MyError{}
err = abi.UnpackIntoInterface(&result, errorName, encoded)
if err != nil {
t.Fatal(err)
}
if result.Sender != sender {
t.Errorf("expected %x got %x", sender, result.Sender)
}
if result.Balance.Cmp(balance) != 0 {
t.Errorf("expected %v got %v", balance, result.Balance)
}
}
func TestMultiPack(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@ -330,6 +389,7 @@ func ExampleJSON() {
}
func TestInputVariableInputLength(t *testing.T) {
t.Parallel()
const definition = `[
{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
@ -458,6 +518,7 @@ func TestInputVariableInputLength(t *testing.T) {
}
func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Error(err)
@ -632,6 +693,7 @@ func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
}
func TestDefaultFunctionParsing(t *testing.T) {
t.Parallel()
const definition = `[{ "name" : "balance", "type" : "function" }]`
abi, err := JSON(strings.NewReader(definition))
@ -645,6 +707,7 @@ func TestDefaultFunctionParsing(t *testing.T) {
}
func TestBareEvents(t *testing.T) {
t.Parallel()
const definition = `[
{ "type" : "event", "name" : "balance" },
{ "type" : "event", "name" : "anon", "anonymous" : true},
@ -707,17 +770,21 @@ func TestBareEvents(t *testing.T) {
}
// TestUnpackEvent is based on this contract:
// contract T {
// event received(address sender, uint amount, bytes memo);
// event receivedAddr(address sender);
// function receive(bytes memo) external payable {
// received(msg.sender, msg.value, memo);
// receivedAddr(msg.sender);
// }
// }
//
// contract T {
// event received(address sender, uint amount, bytes memo);
// event receivedAddr(address sender);
// function receive(bytes memo) external payable {
// received(msg.sender, msg.value, memo);
// receivedAddr(msg.sender);
// }
// }
//
// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
//
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
func TestUnpackEvent(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@ -756,6 +823,7 @@ func TestUnpackEvent(t *testing.T) {
}
func TestUnpackEventIntoMap(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@ -806,6 +874,7 @@ func TestUnpackEventIntoMap(t *testing.T) {
}
func TestUnpackMethodIntoMap(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@ -856,6 +925,7 @@ func TestUnpackMethodIntoMap(t *testing.T) {
}
func TestUnpackIntoMapNamingConflict(t *testing.T) {
t.Parallel()
// Two methods have the same name
var abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"get","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
@ -939,6 +1009,7 @@ func TestUnpackIntoMapNamingConflict(t *testing.T) {
}
func TestABI_MethodById(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@ -971,6 +1042,7 @@ func TestABI_MethodById(t *testing.T) {
}
func TestABI_EventById(t *testing.T) {
t.Parallel()
tests := []struct {
name string
json string
@ -1021,9 +1093,7 @@ func TestABI_EventById(t *testing.T) {
}
if event == nil {
t.Errorf("We should find a event for topic %s, test #%d", topicID.Hex(), testnum)
}
if event.ID != topicID {
} else if event.ID != topicID {
t.Errorf("Event id %s does not match topic %s, test #%d", event.ID.Hex(), topicID.Hex(), testnum)
}
@ -1038,9 +1108,39 @@ func TestABI_EventById(t *testing.T) {
}
}
func TestABI_ErrorByID(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(`[
{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"MyError1","type":"error"},
{"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"x","type":"tuple"},{"internalType":"address","name":"y","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"z","type":"tuple"}],"name":"MyError2","type":"error"},
{"inputs":[{"internalType":"uint256[]","name":"x","type":"uint256[]"}],"name":"MyError3","type":"error"}
]`))
if err != nil {
t.Fatal(err)
}
for name, m := range abi.Errors {
a := fmt.Sprintf("%v", &m)
var id [4]byte
copy(id[:], m.ID[:4])
m2, err := abi.ErrorByID(id)
if err != nil {
t.Fatalf("Failed to look up ABI error: %v", err)
}
b := fmt.Sprintf("%v", m2)
if a != b {
t.Errorf("Error %v (id %x) not 'findable' by id in ABI", name, id)
}
}
// test unsuccessful lookups
if _, err = abi.ErrorByID([4]byte{}); err == nil {
t.Error("Expected error: no error with this id")
}
}
// TestDoubleDuplicateMethodNames checks that if transfer0 already exists, there won't be a name
// conflict and that the second transfer method will be renamed transfer1.
func TestDoubleDuplicateMethodNames(t *testing.T) {
t.Parallel()
abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer0","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@ -1063,12 +1163,14 @@ func TestDoubleDuplicateMethodNames(t *testing.T) {
// TestDoubleDuplicateEventNames checks that if send0 already exists, there won't be a name
// conflict and that the second send event will be renamed send1.
// The test runs the abi of the following contract.
// contract DuplicateEvent {
// event send(uint256 a);
//
// contract DuplicateEvent {
// event send(uint256 a);
// event send0();
// event send();
// }
func TestDoubleDuplicateEventNames(t *testing.T) {
t.Parallel()
abiJSON := `[{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "a","type": "uint256"}],"name": "send","type": "event"},{"anonymous": false,"inputs": [],"name": "send0","type": "event"},{ "anonymous": false, "inputs": [],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@ -1091,10 +1193,12 @@ func TestDoubleDuplicateEventNames(t *testing.T) {
// TestUnnamedEventParam checks that an event with unnamed parameters is
// correctly handled.
// The test runs the abi of the following contract.
// contract TestEvent {
//
// contract TestEvent {
// event send(uint256, uint256);
// }
func TestUnnamedEventParam(t *testing.T) {
t.Parallel()
abiJSON := `[{ "anonymous": false, "inputs": [{ "indexed": false,"internalType": "uint256", "name": "","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "","type": "uint256"}],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@ -1124,9 +1228,12 @@ func TestUnpackRevert(t *testing.T) {
{"", "", errors.New("invalid data for unpacking")},
{"08c379a1", "", errors.New("invalid data for unpacking")},
{"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil},
{"4e487b710000000000000000000000000000000000000000000000000000000000000000", "generic panic", nil},
{"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
}
for index, c := range cases {
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
t.Parallel()
got, err := UnpackRevert(common.Hex2Bytes(c.input))
if c.expectErr != nil {
if err == nil {
@ -1143,3 +1250,10 @@ func TestUnpackRevert(t *testing.T) {
})
}
}
func TestInternalContractType(t *testing.T) {
jsonData := `[{"inputs":[{"components":[{"internalType":"uint256","name":"dailyLimit","type":"uint256"},{"internalType":"uint256","name":"txLimit","type":"uint256"},{"internalType":"uint256","name":"accountDailyLimit","type":"uint256"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"bool","name":"onlyWhitelisted","type":"bool"}],"internalType":"struct IMessagePassingBridge.BridgeLimits","name":"bridgeLimits","type":"tuple"},{"components":[{"internalType":"uint256","name":"lastTransferReset","type":"uint256"},{"internalType":"uint256","name":"bridged24Hours","type":"uint256"}],"internalType":"struct IMessagePassingBridge.AccountLimit","name":"accountDailyLimit","type":"tuple"},{"components":[{"internalType":"uint256","name":"lastTransferReset","type":"uint256"},{"internalType":"uint256","name":"bridged24Hours","type":"uint256"}],"internalType":"struct IMessagePassingBridge.BridgeDailyLimit","name":"bridgeDailyLimit","type":"tuple"},{"internalType":"contract INameService","name":"nameService","type":"INameService"},{"internalType":"bool","name":"isClosed","type":"bool"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"canBridge","outputs":[{"internalType":"bool","name":"isWithinLimit","type":"bool"},{"internalType":"string","name":"error","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"normalizeFrom18ToTokenDecimals","outputs":[{"internalType":"uint256","name":"normalized","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"normalizeFromTokenTo18Decimals","outputs":[{"internalType":"uint256","name":"normalized","type":"uint256"}],"stateMutability":"pure","type":"function"}]`
if _, err := JSON(strings.NewReader(jsonData)); err != nil {
t.Fatal(err)
}
}

View file

@ -17,38 +17,67 @@
package abi
import (
"bytes"
"fmt"
"math/rand"
"reflect"
"strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/crypto"
fuzz "github.com/google/gofuzz"
)
func unpackPack(abi abi.ABI, method string, inputType []interface{}, input []byte) bool {
outptr := reflect.New(reflect.TypeOf(inputType))
if err := abi.UnpackIntoInterface(outptr.Interface(), method, input); err == nil {
output, err := abi.Pack(method, input)
// TestReplicate can be used to replicate crashers from the fuzzing tests.
// Just replace testString with the data in .quoted
func TestReplicate(t *testing.T) {
t.Parallel()
//t.Skip("Test only useful for reproducing issues")
fuzzAbi([]byte("\x20\x20\x20\x20\x20\x20\x20\x20\x80\x00\x00\x00\x20\x20\x20\x20\x00"))
//fuzzAbi([]byte("asdfasdfkadsf;lasdf;lasd;lfk"))
}
// FuzzABI is the main entrypoint for fuzzing
func FuzzABI(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzAbi(data)
})
}
var (
names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
stateMut = []string{"pure", "view", "payable"}
pays = []string{"true", "false"}
vNames = []string{"a", "b", "c", "d", "e", "f", "g"}
varNames = append(vNames, names...)
varTypes = []string{"bool", "address", "bytes", "string",
"uint8", "int8", "uint8", "int8", "uint16", "int16",
"uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56",
"uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96",
"uint104", "int104", "uint112", "int112", "uint120", "int120", "uint128", "int128", "uint136", "int136",
"uint144", "int144", "uint152", "int152", "uint160", "int160", "uint168", "int168", "uint176", "int176",
"uint184", "int184", "uint192", "int192", "uint200", "int200", "uint208", "int208", "uint216", "int216",
"uint224", "int224", "uint232", "int232", "uint240", "int240", "uint248", "int248", "uint256", "int256",
"bytes1", "bytes2", "bytes3", "bytes4", "bytes5", "bytes6", "bytes7", "bytes8", "bytes9", "bytes10", "bytes11",
"bytes12", "bytes13", "bytes14", "bytes15", "bytes16", "bytes17", "bytes18", "bytes19", "bytes20", "bytes21",
"bytes22", "bytes23", "bytes24", "bytes25", "bytes26", "bytes27", "bytes28", "bytes29", "bytes30", "bytes31",
"bytes32", "bytes"}
)
func unpackPack(abi ABI, method string, input []byte) ([]interface{}, bool) {
if out, err := abi.Unpack(method, input); err == nil {
_, err := abi.Pack(method, out...)
if err != nil {
// We have some false positives as we can unpack these type successfully, but not pack them
if err.Error() == "abi: cannot use []uint8 as type [0]int8 as argument" ||
err.Error() == "abi: cannot use uint8 as type int8 as argument" {
return false
return out, false
}
panic(err)
}
if !bytes.Equal(input, output[4:]) {
panic(fmt.Sprintf("unpackPack is not equal, \ninput : %x\noutput: %x", input, output[4:]))
}
return true
return out, true
}
return false
return nil, false
}
func packUnpack(abi abi.ABI, method string, input []interface{}) bool {
func packUnpack(abi ABI, method string, input *[]interface{}) bool {
if packed, err := abi.Pack(method, input); err == nil {
outptr := reflect.New(reflect.TypeOf(input))
err := abi.UnpackIntoInterface(outptr.Interface(), method, packed)
@ -64,12 +93,12 @@ func packUnpack(abi abi.ABI, method string, input []interface{}) bool {
return false
}
type args struct {
type arg struct {
name string
typ string
}
func createABI(name string, stateMutability, payable *string, inputs []args) (abi.ABI, error) {
func createABI(name string, stateMutability, payable *string, inputs []arg) (ABI, error) {
sig := fmt.Sprintf(`[{ "type" : "function", "name" : "%v" `, name)
if stateMutability != nil {
sig += fmt.Sprintf(`, "stateMutability": "%v" `, *stateMutability)
@ -96,91 +125,55 @@ func createABI(name string, stateMutability, payable *string, inputs []args) (ab
sig += "} ]"
}
sig += `}]`
return abi.JSON(strings.NewReader(sig))
//fmt.Printf("sig: %s\n", sig)
return JSON(strings.NewReader(sig))
}
func fillStruct(structs []interface{}, data []byte) {
if structs != nil && len(data) != 0 {
fuzz.NewFromGoFuzz(data).Fuzz(&structs)
}
}
func createStructs(args []args) []interface{} {
structs := make([]interface{}, len(args))
for i, arg := range args {
t, err := abi.NewType(arg.typ, "", nil)
if err != nil {
panic(err)
func fuzzAbi(input []byte) {
var (
fuzzer = fuzz.NewFromGoFuzz(input)
name = oneOf(fuzzer, names)
stateM = oneOfOrNil(fuzzer, stateMut)
payable = oneOfOrNil(fuzzer, pays)
arguments []arg
)
for i := 0; i < upTo(fuzzer, 10); i++ {
argName := oneOf(fuzzer, varNames)
argTyp := oneOf(fuzzer, varTypes)
switch upTo(fuzzer, 10) {
case 0: // 10% chance to make it a slice
argTyp += "[]"
case 1: // 10% chance to make it an array
argTyp += fmt.Sprintf("[%d]", 1+upTo(fuzzer, 30))
default:
}
structs[i] = reflect.New(t.GetType()).Elem()
arguments = append(arguments, arg{name: argName, typ: argTyp})
}
return structs
abi, err := createABI(name, stateM, payable, arguments)
if err != nil {
//fmt.Printf("err: %v\n", err)
panic(err)
}
structs, _ := unpackPack(abi, name, input)
_ = packUnpack(abi, name, &structs)
}
func runFuzzer(input []byte) int {
good := false
names := []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
stateMut := []string{"", "pure", "view", "payable"}
stateMutabilites := []*string{nil, &stateMut[0], &stateMut[1], &stateMut[2], &stateMut[3]}
pays := []string{"true", "false"}
payables := []*string{nil, &pays[0], &pays[1]}
varNames := []string{"a", "b", "c", "d", "e", "f", "g"}
varNames = append(varNames, names...)
varTypes := []string{"bool", "address", "bytes", "string",
"uint8", "int8", "uint8", "int8", "uint16", "int16",
"uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56",
"uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96",
"uint104", "int104", "uint112", "int112", "uint120", "int120", "uint128", "int128", "uint136", "int136",
"uint144", "int144", "uint152", "int152", "uint160", "int160", "uint168", "int168", "uint176", "int176",
"uint184", "int184", "uint192", "int192", "uint200", "int200", "uint208", "int208", "uint216", "int216",
"uint224", "int224", "uint232", "int232", "uint240", "int240", "uint248", "int248", "uint256", "int256",
"bytes1", "bytes2", "bytes3", "bytes4", "bytes5", "bytes6", "bytes7", "bytes8", "bytes9", "bytes10", "bytes11",
"bytes12", "bytes13", "bytes14", "bytes15", "bytes16", "bytes17", "bytes18", "bytes19", "bytes20", "bytes21",
"bytes22", "bytes23", "bytes24", "bytes25", "bytes26", "bytes27", "bytes28", "bytes29", "bytes30", "bytes31",
"bytes32", "bytes"}
rnd := rand.New(rand.NewSource(123456))
if len(input) > 0 {
kec := crypto.Keccak256(input)
rnd = rand.New(rand.NewSource(int64(kec[0])))
func upTo(fuzzer *fuzz.Fuzzer, max int) int {
var i int
fuzzer.Fuzz(&i)
if i < 0 {
return (-1 - i) % max
}
name := names[rnd.Intn(len(names))]
stateM := stateMutabilites[rnd.Intn(len(stateMutabilites))]
payable := payables[rnd.Intn(len(payables))]
maxLen := 5
for k := 1; k < maxLen; k++ {
var arg []args
for i := k; i > 0; i-- {
argName := varNames[i]
argTyp := varTypes[rnd.Int31n(int32(len(varTypes)))]
if rnd.Int31n(10) == 0 {
argTyp += "[]"
} else if rnd.Int31n(10) == 0 {
arrayArgs := rnd.Int31n(30) + 1
argTyp += fmt.Sprintf("[%d]", arrayArgs)
}
arg = append(arg, args{
name: argName,
typ: argTyp,
})
}
abi, err := createABI(name, stateM, payable, arg)
if err != nil {
continue
}
structs := createStructs(arg)
b := unpackPack(abi, name, structs, input)
fillStruct(structs, input)
c := packUnpack(abi, name, structs)
good = good || b || c
}
if good {
return 1
}
return 0
return i % max
}
func Fuzz(input []byte) int {
return runFuzzer(input)
func oneOf(fuzzer *fuzz.Fuzzer, options []string) string {
return options[upTo(fuzzer, len(options))]
}
func oneOfOrNil(fuzzer *fuzz.Fuzzer, options []string) *string {
if i := upTo(fuzzer, len(options)+1); i < len(options) {
return &options[i]
}
return nil
}

View file

@ -14,15 +14,14 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package bind generates Ethereum contract Go bindings.
// Package abigen generates Ethereum contract Go bindings.
//
// Detailed usage document and tutorial available on the go-ethereum Wiki page:
// https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts
package bind
// https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings
package abigen
import (
"bytes"
"errors"
"fmt"
"go/format"
"regexp"
@ -34,20 +33,52 @@ import (
"github.com/ethereum/go-ethereum/log"
)
// Lang is a target programming language selector to generate bindings for.
type Lang int
const (
LangGo Lang = iota
LangJava
LangObjC
var (
intRegex = regexp.MustCompile(`(u)?int([0-9]*)`)
)
func isKeyWord(arg string) bool {
switch arg {
case "break":
case "case":
case "chan":
case "const":
case "continue":
case "default":
case "defer":
case "else":
case "fallthrough":
case "for":
case "func":
case "go":
case "goto":
case "if":
case "import":
case "interface":
case "iota":
case "map":
case "make":
case "new":
case "package":
case "range":
case "return":
case "select":
case "struct":
case "switch":
case "type":
case "var":
default:
return false
}
return true
}
// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant
// to be used as is in client code, but rather as an intermediate struct which
// enforces compile time type safety and naming convention opposed to having to
// enforces compile time type safety and naming convention as opposed to having to
// manually maintain hard coded strings that break on runtime.
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string) (string, error) {
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
var (
// contracts is the map of each individual contract requested binding
contracts = make(map[string]*tmplContract)
@ -88,38 +119,54 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
transactIdentifiers = make(map[string]bool)
eventIdentifiers = make(map[string]bool)
)
for _, input := range evmABI.Constructor.Inputs {
if hasStruct(input.Type) {
bindStructType(input.Type, structs)
}
}
for _, original := range evmABI.Methods {
// Normalize the method for capital cases and non-anonymous inputs/outputs
normalized := original
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
normalizedName := abi.ToCamelCase(alias(aliases, original.Name))
// Ensure there is no duplicated identifier
var identifiers = callIdentifiers
if !original.IsConstant() {
identifiers = transactIdentifiers
}
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
normalizedName = fmt.Sprintf("M%s", normalizedName)
normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool {
_, ok := identifiers[name]
return ok
})
}
if identifiers[normalizedName] {
return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName)
}
identifiers[normalizedName] = true
normalized.Name = normalizedName
normalized.Inputs = make([]abi.Argument, len(original.Inputs))
copy(normalized.Inputs, original.Inputs)
for j, input := range normalized.Inputs {
if input.Name == "" {
if input.Name == "" || isKeyWord(input.Name) {
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
}
if hasStruct(input.Type) {
bindStructType[lang](input.Type, structs)
bindStructType(input.Type, structs)
}
}
normalized.Outputs = make([]abi.Argument, len(original.Outputs))
copy(normalized.Outputs, original.Outputs)
for j, output := range normalized.Outputs {
if output.Name != "" {
normalized.Outputs[j].Name = capitalise(output.Name)
normalized.Outputs[j].Name = abi.ToCamelCase(output.Name)
}
if hasStruct(output.Type) {
bindStructType[lang](output.Type, structs)
bindStructType(output.Type, structs)
}
}
// Append the methods to the call or transact lists
@ -138,21 +185,39 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
normalized := original
// Ensure there is no duplicated identifier
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
normalizedName := abi.ToCamelCase(alias(aliases, original.Name))
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
normalizedName = fmt.Sprintf("E%s", normalizedName)
normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool {
_, ok := eventIdentifiers[name]
return ok
})
}
if eventIdentifiers[normalizedName] {
return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName)
}
eventIdentifiers[normalizedName] = true
normalized.Name = normalizedName
used := make(map[string]bool)
normalized.Inputs = make([]abi.Argument, len(original.Inputs))
copy(normalized.Inputs, original.Inputs)
for j, input := range normalized.Inputs {
if input.Name == "" {
if input.Name == "" || isKeyWord(input.Name) {
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
}
// Event is a bit special, we need to define event struct in binding,
// ensure there is no camel-case-style name conflict.
for index := 0; ; index++ {
if !used[abi.ToCamelCase(normalized.Inputs[j].Name)] {
used[abi.ToCamelCase(normalized.Inputs[j].Name)] = true
break
}
normalized.Inputs[j].Name = fmt.Sprintf("%s%d", normalized.Inputs[j].Name, index)
}
if hasStruct(input.Type) {
bindStructType[lang](input.Type, structs)
bindStructType(input.Type, structs)
}
}
// Append the event to the accumulator list
@ -165,14 +230,10 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
if evmABI.HasReceive() {
receive = &tmplMethod{Original: evmABI.Receive}
}
// There is no easy way to pass arbitrary java objects to the Go side.
if len(structs) > 0 && lang == LangJava {
return "", errors.New("java binding for tuple arguments is not supported yet")
}
contracts[types[i]] = &tmplContract{
Type: capitalise(types[i]),
InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1),
Type: abi.ToCamelCase(types[i]),
InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""),
InputBin: strings.TrimPrefix(strings.TrimSpace(bytecodes[i]), "0x"),
Constructor: evmABI.Constructor,
Calls: calls,
@ -182,6 +243,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
Events: events,
Libraries: make(map[string]string),
}
// Function 4-byte signatures are stored in the same sequence
// as types, if available.
if len(fsigs) > i {
@ -189,7 +251,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
}
// Parse library references.
for pattern, name := range libs {
matched, err := regexp.Match("__\\$"+pattern+"\\$__", []byte(contracts[types[i]].InputBin))
matched, err := regexp.MatchString("__\\$"+pattern+"\\$__", contracts[types[i]].InputBin)
if err != nil {
log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err)
}
@ -207,6 +269,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
_, ok := isLib[types[i]]
contracts[types[i]].Library = ok
}
// Generate the contract template data content and render it
data := &tmplData{
Package: pkg,
@ -217,42 +280,30 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
buffer := new(bytes.Buffer)
funcs := map[string]interface{}{
"bindtype": bindType[lang],
"bindtopictype": bindTopicType[lang],
"namedtype": namedType[lang],
"capitalise": capitalise,
"bindtype": bindType,
"bindtopictype": bindTopicType,
"capitalise": abi.ToCamelCase,
"decapitalise": decapitalise,
}
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSource[lang]))
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSource))
if err := tmpl.Execute(buffer, data); err != nil {
return "", err
}
// For Go bindings pass the code through gofmt to clean it up
if lang == LangGo {
code, err := format.Source(buffer.Bytes())
if err != nil {
return "", fmt.Errorf("%v\n%s", err, buffer)
}
return string(code), nil
// Pass the code through gofmt to clean it up
code, err := format.Source(buffer.Bytes())
if err != nil {
return "", fmt.Errorf("%v\n%s", err, buffer)
}
// For all others just return as is for now
return buffer.String(), nil
return string(code), nil
}
// bindType is a set of type binders that convert Solidity types to some supported
// programming language types.
var bindType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
LangGo: bindTypeGo,
LangJava: bindTypeJava,
}
// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go ones.
func bindBasicTypeGo(kind abi.Type) string {
// bindBasicType converts basic solidity types(except array, slice and tuple) to Go ones.
func bindBasicType(kind abi.Type) string {
switch kind.T {
case abi.AddressTy:
return "common.Address"
case abi.IntTy, abi.UintTy:
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
parts := intRegex.FindStringSubmatch(kind.String())
switch parts[2] {
case "8", "16", "32", "64":
return fmt.Sprintf("%sint%s", parts[1], parts[2])
@ -270,125 +321,26 @@ func bindBasicTypeGo(kind abi.Type) string {
}
}
// bindTypeGo converts solidity types to Go ones. Since there is no clear mapping
// bindType converts solidity types to Go ones. Since there is no clear mapping
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
// mapped will use an upscaled type (e.g. BigDecimal).
func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
func bindType(kind abi.Type, structs map[string]*tmplStruct) string {
switch kind.T {
case abi.TupleTy:
return structs[kind.TupleRawName+kind.String()].Name
case abi.ArrayTy:
return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem, structs)
return fmt.Sprintf("[%d]", kind.Size) + bindType(*kind.Elem, structs)
case abi.SliceTy:
return "[]" + bindTypeGo(*kind.Elem, structs)
return "[]" + bindType(*kind.Elem, structs)
default:
return bindBasicTypeGo(kind)
return bindBasicType(kind)
}
}
// bindBasicTypeJava converts basic solidity types(except array, slice and tuple) to Java ones.
func bindBasicTypeJava(kind abi.Type) string {
switch kind.T {
case abi.AddressTy:
return "Address"
case abi.IntTy, abi.UintTy:
// Note that uint and int (without digits) are also matched,
// these are size 256, and will translate to BigInt (the default).
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
if len(parts) != 3 {
return kind.String()
}
// All unsigned integers should be translated to BigInt since gomobile doesn't
// support them.
if parts[1] == "u" {
return "BigInt"
}
namedSize := map[string]string{
"8": "byte",
"16": "short",
"32": "int",
"64": "long",
}[parts[2]]
// default to BigInt
if namedSize == "" {
namedSize = "BigInt"
}
return namedSize
case abi.FixedBytesTy, abi.BytesTy:
return "byte[]"
case abi.BoolTy:
return "boolean"
case abi.StringTy:
return "String"
case abi.FunctionTy:
return "byte[24]"
default:
return kind.String()
}
}
// pluralizeJavaType explicitly converts multidimensional types to predefined
// types in go side.
func pluralizeJavaType(typ string) string {
switch typ {
case "boolean":
return "Bools"
case "String":
return "Strings"
case "Address":
return "Addresses"
case "byte[]":
return "Binaries"
case "BigInt":
return "BigInts"
}
return typ + "[]"
}
// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping
// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly
// mapped will use an upscaled type (e.g. BigDecimal).
func bindTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
switch kind.T {
case abi.TupleTy:
return structs[kind.TupleRawName+kind.String()].Name
case abi.ArrayTy, abi.SliceTy:
return pluralizeJavaType(bindTypeJava(*kind.Elem, structs))
default:
return bindBasicTypeJava(kind)
}
}
// bindTopicType is a set of type binders that convert Solidity types to some
// supported programming language topic types.
var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
LangGo: bindTopicTypeGo,
LangJava: bindTopicTypeJava,
}
// bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same
// bindTopicType converts a Solidity topic type to a Go one. It is almost the same
// functionality as for simple types, but dynamic types get converted to hashes.
func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
bound := bindTypeGo(kind, structs)
// todo(rjl493456442) according solidity documentation, indexed event
// parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored.
//
// We only convert stringS and bytes to hash, still need to deal with
// array(both fixed-size and dynamic-size) and struct.
if bound == "string" || bound == "[]byte" {
bound = "common.Hash"
}
return bound
}
// bindTopicTypeJava converts a Solidity topic type to a Java one. It is almost the same
// functionality as for simple types, but dynamic types get converted to hashes.
func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
bound := bindTypeJava(kind, structs)
func bindTopicType(kind abi.Type, structs map[string]*tmplStruct) string {
bound := bindType(kind, structs)
// todo(rjl493456442) according solidity documentation, indexed event
// parameters that are not value types i.e. arrays and structs are not
@ -396,23 +348,16 @@ func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
//
// We only convert strings and bytes to hash, still need to deal with
// array(both fixed-size and dynamic-size) and struct.
if bound == "String" || bound == "byte[]" {
bound = "Hash"
if bound == "string" || bound == "[]byte" {
bound = "common.Hash"
}
return bound
}
// bindStructType is a set of type binders that convert Solidity tuple types to some supported
// programming language struct definition.
var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
LangGo: bindStructTypeGo,
LangJava: bindStructTypeJava,
}
// bindStructTypeGo converts a Solidity tuple type to a Go one and records the mapping
// in the given map.
// Notably, this function will resolve and record nested struct recursively.
func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
// bindStructType converts a Solidity tuple type to a Go one and records the mapping
// in the given map. Notably, this function will resolve and record nested struct
// recursively.
func bindStructType(kind abi.Type, structs map[string]*tmplStruct) string {
switch kind.T {
case abi.TupleTy:
// We compose a raw struct name and a canonical parameter expression
@ -425,96 +370,37 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
if s, exist := structs[id]; exist {
return s.Name
}
var fields []*tmplField
var (
names = make(map[string]bool)
fields []*tmplField
)
for i, elem := range kind.TupleElems {
field := bindStructTypeGo(*elem, structs)
fields = append(fields, &tmplField{Type: field, Name: capitalise(kind.TupleRawNames[i]), SolKind: *elem})
name := abi.ToCamelCase(kind.TupleRawNames[i])
name = abi.ResolveNameConflict(name, func(s string) bool { return names[s] })
names[name] = true
fields = append(fields, &tmplField{
Type: bindStructType(*elem, structs),
Name: name,
SolKind: *elem,
})
}
name := kind.TupleRawName
if name == "" {
name = fmt.Sprintf("Struct%d", len(structs))
}
name = abi.ToCamelCase(name)
structs[id] = &tmplStruct{
Name: name,
Fields: fields,
}
return name
case abi.ArrayTy:
return fmt.Sprintf("[%d]", kind.Size) + bindStructTypeGo(*kind.Elem, structs)
return fmt.Sprintf("[%d]", kind.Size) + bindStructType(*kind.Elem, structs)
case abi.SliceTy:
return "[]" + bindStructTypeGo(*kind.Elem, structs)
return "[]" + bindStructType(*kind.Elem, structs)
default:
return bindBasicTypeGo(kind)
}
}
// bindStructTypeJava converts a Solidity tuple type to a Java one and records the mapping
// in the given map.
// Notably, this function will resolve and record nested struct recursively.
func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
switch kind.T {
case abi.TupleTy:
// We compose a raw struct name and a canonical parameter expression
// together here. The reason is before solidity v0.5.11, kind.TupleRawName
// is empty, so we use canonical parameter expression to distinguish
// different struct definition. From the consideration of backward
// compatibility, we concat these two together so that if kind.TupleRawName
// is not empty, it can have unique id.
id := kind.TupleRawName + kind.String()
if s, exist := structs[id]; exist {
return s.Name
}
var fields []*tmplField
for i, elem := range kind.TupleElems {
field := bindStructTypeJava(*elem, structs)
fields = append(fields, &tmplField{Type: field, Name: decapitalise(kind.TupleRawNames[i]), SolKind: *elem})
}
name := kind.TupleRawName
if name == "" {
name = fmt.Sprintf("Class%d", len(structs))
}
structs[id] = &tmplStruct{
Name: name,
Fields: fields,
}
return name
case abi.ArrayTy, abi.SliceTy:
return pluralizeJavaType(bindStructTypeJava(*kind.Elem, structs))
default:
return bindBasicTypeJava(kind)
}
}
// namedType is a set of functions that transform language specific types to
// named versions that may be used inside method names.
var namedType = map[Lang]func(string, abi.Type) string{
LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") },
LangJava: namedTypeJava,
}
// namedTypeJava converts some primitive data types to named variants that can
// be used as parts of method names.
func namedTypeJava(javaKind string, solKind abi.Type) string {
switch javaKind {
case "byte[]":
return "Binary"
case "boolean":
return "Bool"
default:
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
if len(parts) != 4 {
return javaKind
}
switch parts[2] {
case "8", "16", "32", "64":
if parts[3] == "" {
return capitalise(fmt.Sprintf("%sint%s", parts[1], parts[2]))
}
return capitalise(fmt.Sprintf("%sint%ss", parts[1], parts[2]))
default:
return javaKind
}
return bindBasicType(kind)
}
}
@ -527,22 +413,11 @@ func alias(aliases map[string]string, n string) string {
return n
}
// methodNormalizer is a name transformer that modifies Solidity method names to
// conform to target language naming conventions.
var methodNormalizer = map[Lang]func(string) string{
LangGo: abi.ToCamelCase,
LangJava: decapitalise,
}
// capitalise makes a camel-case string which starts with an upper case character.
var capitalise = abi.ToCamelCase
// decapitalise makes a camel-case string which starts with a lower case character.
func decapitalise(input string) string {
if len(input) == 0 {
return input
}
goForm := abi.ToCamelCase(input)
return strings.ToLower(goForm[:1]) + goForm[1:]
}
@ -561,7 +436,7 @@ func structured(args abi.Arguments) bool {
}
// If the field name is empty when normalized or collides (var, Var, _var, _Var),
// we can't organize into a struct
field := capitalise(out.Name)
field := abi.ToCamelCase(out.Name)
if field == "" || exists[field] {
return false
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,373 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abigen
import (
"bytes"
"fmt"
"go/format"
"reflect"
"regexp"
"slices"
"sort"
"strings"
"text/template"
"unicode"
"github.com/ethereum/go-ethereum/accounts/abi"
)
// underlyingBindType returns a string representation of the Go type
// that corresponds to the given ABI type, panicking if it is not a
// pointer.
func underlyingBindType(typ abi.Type) string {
goType := typ.GetType()
if goType.Kind() != reflect.Pointer {
panic("trying to retrieve underlying bind type of non-pointer type.")
}
return goType.Elem().String()
}
// isPointerType returns true if the underlying type is a pointer.
func isPointerType(typ abi.Type) bool {
return typ.GetType().Kind() == reflect.Pointer
}
// OLD:
// binder is used during the conversion of an ABI definition into Go bindings
// (as part of the execution of BindV2). In contrast to contractBinder, binder
// contains binding-generation-state that is shared between contracts:
//
// a global struct map of structs emitted by all contracts is tracked and expanded.
// Structs generated in the bindings are not prefixed with the contract name
// that uses them (to keep the generated bindings less verbose).
//
// This contrasts to other per-contract state (constructor/method/event/error,
// pack/unpack methods) which are guaranteed to be unique because of their
// association with the uniquely-named owning contract (whether prefixed in the
// generated symbol name, or as a member method on a contract struct).
//
// In addition, binder contains the input alias map. In BindV2, a binder is
// instantiated to produce a set of tmplContractV2 and tmplStruct objects from
// the provided ABI definition. These are used as part of the input to rendering
// the binding template.
// NEW:
// binder is used to translate an ABI definition into a set of data-structures
// that will be used to render the template and produce Go bindings. This can
// be thought of as the "backend" that sanitizes the ABI definition to a format
// that can be directly rendered with minimal complexity in the template.
//
// The input data to the template rendering consists of:
// - the set of all contracts requested for binding, each containing
// methods/events/errors to emit pack/unpack methods for.
// - the set of structures defined by the contracts, and created
// as part of the binding process.
type binder struct {
// contracts is the map of each individual contract requested binding.
// It is keyed by the contract name provided in the ABI definition.
contracts map[string]*tmplContractV2
// structs is the map of all emitted structs from contracts being bound.
// it is keyed by a unique identifier generated from the name of the owning contract
// and the solidity type signature of the struct
structs map[string]*tmplStruct
// aliases is a map for renaming instances of named events/functions/errors
// to specified values. it is keyed by source symbol name, and values are
// what the replacement name should be.
aliases map[string]string
}
// BindStructType registers the type to be emitted as a struct in the
// bindings.
func (b *binder) BindStructType(typ abi.Type) {
bindStructType(typ, b.structs)
}
// contractBinder holds state for binding of a single contract. It is a type
// registry for compiling maps of identifiers that will be emitted in generated
// bindings.
type contractBinder struct {
binder *binder
// all maps are keyed by the original (non-normalized) name of the symbol in question
// from the provided ABI definition.
calls map[string]*tmplMethod
events map[string]*tmplEvent
errors map[string]*tmplError
callIdentifiers map[string]bool
eventIdentifiers map[string]bool
errorIdentifiers map[string]bool
}
func newContractBinder(binder *binder) *contractBinder {
return &contractBinder{
binder,
make(map[string]*tmplMethod),
make(map[string]*tmplEvent),
make(map[string]*tmplError),
make(map[string]bool),
make(map[string]bool),
make(map[string]bool),
}
}
// registerIdentifier applies alias renaming, name normalization (conversion
// from snake to camel-case), and registers the normalized name in the specified identifier map.
// It returns an error if the normalized name already exists in the map.
func (cb *contractBinder) registerIdentifier(identifiers map[string]bool, original string) (normalized string, err error) {
normalized = abi.ToCamelCase(alias(cb.binder.aliases, original))
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalized) > 0 && unicode.IsDigit(rune(normalized[0])) {
normalized = fmt.Sprintf("E%s", normalized)
normalized = abi.ResolveNameConflict(normalized, func(name string) bool {
_, ok := identifiers[name]
return ok
})
}
if _, ok := identifiers[normalized]; ok {
return "", fmt.Errorf("duplicate symbol '%s'", normalized)
}
identifiers[normalized] = true
return normalized, nil
}
// bindMethod registers a method to be emitted in the bindings. The name, inputs
// and outputs are normalized. If any inputs are struct-type their structs are
// registered to be emitted in the bindings. Any methods that return more than
// one output have their results gathered into a struct.
func (cb *contractBinder) bindMethod(original abi.Method) error {
normalized := original
normalizedName, err := cb.registerIdentifier(cb.callIdentifiers, original.Name)
if err != nil {
return err
}
normalized.Name = normalizedName
normalized.Inputs = normalizeArgs(original.Inputs)
for _, input := range normalized.Inputs {
if hasStruct(input.Type) {
cb.binder.BindStructType(input.Type)
}
}
normalized.Outputs = normalizeArgs(original.Outputs)
for _, output := range normalized.Outputs {
if hasStruct(output.Type) {
cb.binder.BindStructType(output.Type)
}
}
var isStructured bool
// If the call returns multiple values, gather them into a struct
if len(normalized.Outputs) > 1 {
isStructured = true
}
cb.calls[original.Name] = &tmplMethod{
Original: original,
Normalized: normalized,
Structured: isStructured,
}
return nil
}
// normalize a set of arguments by stripping underscores, giving a generic name
// in the case where the arg name collides with a reserved Go keyword, and finally
// converting to camel-case.
func normalizeArgs(args abi.Arguments) abi.Arguments {
args = slices.Clone(args)
used := make(map[string]bool)
for i, input := range args {
if isKeyWord(input.Name) {
args[i].Name = fmt.Sprintf("arg%d", i)
}
args[i].Name = abi.ToCamelCase(args[i].Name)
if args[i].Name == "" {
args[i].Name = fmt.Sprintf("arg%d", i)
} else {
args[i].Name = strings.ToLower(args[i].Name[:1]) + args[i].Name[1:]
}
for index := 0; ; index++ {
if !used[args[i].Name] {
used[args[i].Name] = true
break
}
args[i].Name = fmt.Sprintf("%s%d", args[i].Name, index)
}
}
return args
}
// normalizeErrorOrEventFields normalizes errors/events for emitting through
// bindings: Any anonymous fields are given generated names.
func (cb *contractBinder) normalizeErrorOrEventFields(originalInputs abi.Arguments) abi.Arguments {
normalizedArguments := normalizeArgs(originalInputs)
for _, input := range normalizedArguments {
if hasStruct(input.Type) {
cb.binder.BindStructType(input.Type)
}
}
return normalizedArguments
}
// bindEvent normalizes an event and registers it to be emitted in the bindings.
func (cb *contractBinder) bindEvent(original abi.Event) error {
// Skip anonymous events as they don't support explicit filtering
if original.Anonymous {
return nil
}
normalizedName, err := cb.registerIdentifier(cb.eventIdentifiers, original.Name)
if err != nil {
return err
}
normalized := original
normalized.Name = normalizedName
normalized.Inputs = cb.normalizeErrorOrEventFields(original.Inputs)
cb.events[original.Name] = &tmplEvent{Original: original, Normalized: normalized}
return nil
}
// bindError normalizes an error and registers it to be emitted in the bindings.
func (cb *contractBinder) bindError(original abi.Error) error {
normalizedName, err := cb.registerIdentifier(cb.errorIdentifiers, original.Name)
if err != nil {
return err
}
normalized := original
normalized.Name = normalizedName
normalized.Inputs = cb.normalizeErrorOrEventFields(original.Inputs)
cb.errors[original.Name] = &tmplError{Original: original, Normalized: normalized}
return nil
}
// parseLibraryDeps extracts references to library dependencies from the unlinked
// hex string deployment bytecode.
func parseLibraryDeps(unlinkedCode string) (res []string) {
reMatchSpecificPattern, err := regexp.Compile(`__\$([a-f0-9]+)\$__`)
if err != nil {
panic(err)
}
for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(unlinkedCode, -1) {
res = append(res, match[1])
}
return res
}
// iterSorted iterates the map in the lexicographic order of the keys calling
// onItem on each. If the callback returns an error, iteration is halted and
// the error is returned from iterSorted.
func iterSorted[V any](inp map[string]V, onItem func(string, V) error) error {
var sortedKeys []string
for key := range inp {
sortedKeys = append(sortedKeys, key)
}
sort.Strings(sortedKeys)
for _, key := range sortedKeys {
if err := onItem(key, inp[key]); err != nil {
return err
}
}
return nil
}
// BindV2 generates a Go wrapper around a contract ABI. This wrapper isn't meant
// to be used as is in client code, but rather as an intermediate struct which
// enforces compile time type safety and naming convention as opposed to having to
// manually maintain hard coded strings that break on runtime.
func BindV2(types []string, abis []string, bytecodes []string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
b := binder{
contracts: make(map[string]*tmplContractV2),
structs: make(map[string]*tmplStruct),
aliases: aliases,
}
for i := 0; i < len(types); i++ {
// Parse the actual ABI to generate the binding for
evmABI, err := abi.JSON(strings.NewReader(abis[i]))
if err != nil {
return "", err
}
for _, input := range evmABI.Constructor.Inputs {
if hasStruct(input.Type) {
bindStructType(input.Type, b.structs)
}
}
cb := newContractBinder(&b)
err = iterSorted(evmABI.Methods, func(_ string, original abi.Method) error {
return cb.bindMethod(original)
})
if err != nil {
return "", err
}
err = iterSorted(evmABI.Events, func(_ string, original abi.Event) error {
return cb.bindEvent(original)
})
if err != nil {
return "", err
}
err = iterSorted(evmABI.Errors, func(_ string, original abi.Error) error {
return cb.bindError(original)
})
if err != nil {
return "", err
}
b.contracts[types[i]] = newTmplContractV2(types[i], abis[i], bytecodes[i], evmABI.Constructor, cb)
}
invertedLibs := make(map[string]string)
for pattern, name := range libs {
invertedLibs[name] = pattern
}
data := tmplDataV2{
Package: pkg,
Contracts: b.contracts,
Libraries: invertedLibs,
Structs: b.structs,
}
for typ, contract := range data.Contracts {
for _, depPattern := range parseLibraryDeps(contract.InputBin) {
data.Contracts[typ].Libraries[libs[depPattern]] = depPattern
}
}
buffer := new(bytes.Buffer)
funcs := map[string]interface{}{
"bindtype": bindType,
"bindtopictype": bindTopicType,
"capitalise": abi.ToCamelCase,
"decapitalise": decapitalise,
"ispointertype": isPointerType,
"underlyingbindtype": underlyingBindType,
}
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSourceV2))
if err := tmpl.Execute(buffer, data); err != nil {
return "", err
}
// Pass the code through gofmt to clean it up
code, err := format.Source(buffer.Bytes())
if err != nil {
return "", fmt.Errorf("%v\n%s", err, buffer)
}
return string(code), nil
}

File diff suppressed because one or more lines are too long

View file

@ -1,87 +1,3 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind
import "github.com/ethereum/go-ethereum/accounts/abi"
// tmplData is the data structure required to fill the binding template.
type tmplData struct {
Package string // Name of the package to place the generated file in
Contracts map[string]*tmplContract // List of contracts to generate into this file
Libraries map[string]string // Map the bytecode's link pattern to the library name
Structs map[string]*tmplStruct // Contract struct type definitions
}
// tmplContract contains the data needed to generate an individual contract binding.
type tmplContract struct {
Type string // Type name of the main contract binding
InputABI string // JSON ABI used as the input to generate the binding from
InputBin string // Optional EVM bytecode used to generate deploy code from
FuncSigs map[string]string // Optional map: string signature -> 4-byte signature
Constructor abi.Method // Contract constructor for deploy parametrization
Calls map[string]*tmplMethod // Contract calls that only read state data
Transacts map[string]*tmplMethod // Contract calls that write state data
Fallback *tmplMethod // Additional special fallback function
Receive *tmplMethod // Additional special receive function
Events map[string]*tmplEvent // Contract events accessors
Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs
Library bool // Indicator whether the contract is a library
}
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
// and cached data fields.
type tmplMethod struct {
Original abi.Method // Original method as parsed by the abi package
Normalized abi.Method // Normalized version of the parsed method (capitalized names, non-anonymous args/returns)
Structured bool // Whether the returns should be accumulated into a struct
}
// tmplEvent is a wrapper around an abi.Event that contains a few preprocessed
// and cached data fields.
type tmplEvent struct {
Original abi.Event // Original event as parsed by the abi package
Normalized abi.Event // Normalized version of the parsed fields
}
// tmplField is a wrapper around a struct field with binding language
// struct type definition and relative filed name.
type tmplField struct {
Type string // Field type representation depends on target binding language
Name string // Field name converted from the raw user-defined field name
SolKind abi.Type // Raw abi type information
}
// tmplStruct is a wrapper around an abi.tuple and contains an auto-generated
// struct name.
type tmplStruct struct {
Name string // Auto-generated struct name(before solidity v0.5.11) or raw name.
Fields []*tmplField // Struct fields definition depends on the binding language.
}
// tmplSource is language to template mapping containing all the supported
// programming languages the package can generate to.
var tmplSource = map[Lang]string{
LangGo: tmplSourceGo,
LangJava: tmplSourceJava,
}
// tmplSourceGo is the Go source template that the generated Go contract binding
// is based on.
const tmplSourceGo = `
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
@ -90,6 +6,7 @@ package {{.Package}}
import (
"math/big"
"strings"
"errors"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
@ -101,6 +18,7 @@ import (
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
@ -108,6 +26,7 @@ var (
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
_ = abi.ConvertType
)
{{$structs := .Structs}}
@ -120,32 +39,48 @@ var (
{{end}}
{{range $contract := .Contracts}}
// {{.Type}}ABI is the input ABI used to generate the binding from.
const {{.Type}}ABI = "{{.InputABI}}"
{{if $contract.FuncSigs}}
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
var {{.Type}}FuncSigs = map[string]string{
// {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract.
var {{.Type}}MetaData = &bind.MetaData{
ABI: "{{.InputABI}}",
{{if $contract.FuncSigs -}}
Sigs: map[string]string{
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
{{end}}
}
},
{{end -}}
{{if .InputBin -}}
Bin: "0x{{.InputBin}}",
{{end}}
}
// {{.Type}}ABI is the input ABI used to generate the binding from.
// Deprecated: Use {{.Type}}MetaData.ABI instead.
var {{.Type}}ABI = {{.Type}}MetaData.ABI
{{if $contract.FuncSigs}}
// Deprecated: Use {{.Type}}MetaData.Sigs instead.
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
var {{.Type}}FuncSigs = {{.Type}}MetaData.Sigs
{{end}}
{{if .InputBin}}
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
var {{.Type}}Bin = "0x{{.InputBin}}"
// Deprecated: Use {{.Type}}MetaData.Bin instead.
var {{.Type}}Bin = {{.Type}}MetaData.Bin
// Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
parsed, err := abi.JSON(strings.NewReader({{.Type}}ABI))
parsed, err := {{.Type}}MetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
if parsed == nil {
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
{{range $pattern, $name := .Libraries}}
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
{{$contract.Type}}Bin = strings.Replace({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:], -1)
{{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:])
{{end}}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
if err != nil {
return common.Address{}, nil, nil, err
}
@ -250,11 +185,11 @@ var (
// bind{{.Type}} binds a generic wrapper to an already deployed contract.
func bind{{.Type}}(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader({{.Type}}ABI))
parsed, err := {{.Type}}MetaData.GetAbi()
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
@ -304,8 +239,11 @@ var (
err := _{{$contract.Type}}.contract.Call(opts, &out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
{{if .Structured}}
outstruct := new(struct{ {{range .Normalized.Outputs}} {{.Name}} {{bindtype .Type $structs}}; {{end}} })
{{range $i, $t := .Normalized.Outputs}}
outstruct.{{.Name}} = out[{{$i}}].({{bindtype .Type $structs}}){{end}}
if err != nil {
return *outstruct, err
}
{{range $i, $t := .Normalized.Outputs}}
outstruct.{{.Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
return *outstruct, err
{{else}}
@ -314,7 +252,7 @@ var (
}
{{range $i, $t := .Normalized.Outputs}}
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
{{end}}
}
@ -357,7 +295,7 @@ var (
}
{{end}}
{{if .Fallback}}
{{if .Fallback}}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
// Solidity: {{.Fallback.Original.String}}
@ -371,16 +309,16 @@ var (
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
//
// Solidity: {{.Fallback.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
}
{{end}}
{{if .Receive}}
{{if .Receive}}
// Receive is a paid mutator transaction binding the contract receive function.
//
// Solidity: {{.Receive.Original.String}}
@ -394,9 +332,9 @@ var (
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
}
// Receive is a paid mutator transaction binding the contract receive function.
//
//
// Solidity: {{.Receive.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
@ -546,142 +484,4 @@ var (
}
{{end}}
{{end}}
`
// tmplSourceJava is the Java source template that the generated Java contract binding
// is based on.
const tmplSourceJava = `
// This file is an automatically generated Java binding. Do not modify as any
// change will likely be lost upon the next re-generation!
package {{.Package}};
import org.ethereum.geth.*;
import java.util.*;
{{$structs := .Structs}}
{{range $contract := .Contracts}}
{{if not .Library}}public {{end}}class {{.Type}} {
// ABI is the input ABI used to generate the binding from.
public final static String ABI = "{{.InputABI}}";
{{if $contract.FuncSigs}}
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
public final static Map<String, String> {{.Type}}FuncSigs;
static {
Hashtable<String, String> temp = new Hashtable<String, String>();
{{range $strsig, $binsig := .FuncSigs}}temp.put("{{$binsig}}", "{{$strsig}}");
{{end}}
{{.Type}}FuncSigs = Collections.unmodifiableMap(temp);
}
{{end}}
{{if .InputBin}}
// BYTECODE is the compiled bytecode used for deploying new contracts.
public final static String BYTECODE = "0x{{.InputBin}}";
// deploy deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
public static {{.Type}} deploy(TransactOpts auth, EthereumClient client{{range .Constructor.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
Interfaces args = Geth.newInterfaces({{(len .Constructor.Inputs)}});
String bytecode = BYTECODE;
{{if .Libraries}}
// "link" contract to dependent libraries by deploying them first.
{{range $pattern, $name := .Libraries}}
{{capitalise $name}} {{decapitalise $name}}Inst = {{capitalise $name}}.deploy(auth, client);
bytecode = bytecode.replace("__${{$pattern}}$__", {{decapitalise $name}}Inst.Address.getHex().substring(2));
{{end}}
{{end}}
{{range $index, $element := .Constructor.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}});
{{end}}
return new {{.Type}}(Geth.deployContract(auth, ABI, Geth.decodeFromHex(bytecode), client, args));
}
// Internal constructor used by contract deployment.
private {{.Type}}(BoundContract deployment) {
this.Address = deployment.getAddress();
this.Deployer = deployment.getDeployer();
this.Contract = deployment;
}
{{end}}
// Ethereum address where this contract is located at.
public final Address Address;
// Ethereum transaction in which this contract was deployed (if known!).
public final Transaction Deployer;
// Contract instance bound to a blockchain address.
private final BoundContract Contract;
// Creates a new instance of {{.Type}}, bound to a specific deployed contract.
public {{.Type}}(Address address, EthereumClient client) throws Exception {
this(Geth.bindContract(address, ABI, client));
}
{{range .Calls}}
{{if gt (len .Normalized.Outputs) 1}}
// {{capitalise .Normalized.Name}}Results is the output of a call to {{.Normalized.Name}}.
public class {{capitalise .Normalized.Name}}Results {
{{range $index, $item := .Normalized.Outputs}}public {{bindtype .Type $structs}} {{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}};
{{end}}
}
{{end}}
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
//
// Solidity: {{.Original.String}}
public {{if gt (len .Normalized.Outputs) 1}}{{capitalise .Normalized.Name}}Results{{else if eq (len .Normalized.Outputs) 0}}void{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}}{{end}}{{end}} {{.Normalized.Name}}(CallOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}});
{{range $index, $item := .Normalized.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}});
{{end}}
Interfaces results = Geth.newInterfaces({{(len .Normalized.Outputs)}});
{{range $index, $item := .Normalized.Outputs}}Interface result{{$index}} = Geth.newInterface(); result{{$index}}.setDefault{{namedtype (bindtype .Type $structs) .Type}}(); results.set({{$index}}, result{{$index}});
{{end}}
if (opts == null) {
opts = Geth.newCallOpts();
}
this.Contract.call(opts, results, "{{.Original.Name}}", args);
{{if gt (len .Normalized.Outputs) 1}}
{{capitalise .Normalized.Name}}Results result = new {{capitalise .Normalized.Name}}Results();
{{range $index, $item := .Normalized.Outputs}}result.{{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}} = results.get({{$index}}).get{{namedtype (bindtype .Type $structs) .Type}}();
{{end}}
return result;
{{else}}{{range .Normalized.Outputs}}return results.get(0).get{{namedtype (bindtype .Type $structs) .Type}}();{{end}}
{{end}}
}
{{end}}
{{range .Transacts}}
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
//
// Solidity: {{.Original.String}}
public Transaction {{.Normalized.Name}}(TransactOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}});
{{range $index, $item := .Normalized.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}});
{{end}}
return this.Contract.transact(opts, "{{.Original.Name}}" , args);
}
{{end}}
{{if .Fallback}}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
// Solidity: {{.Fallback.Original.String}}
public Transaction Fallback(TransactOpts opts, byte[] calldata) throws Exception {
return this.Contract.rawTransact(opts, calldata);
}
{{end}}
{{if .Receive}}
// Receive is a paid mutator transaction binding the contract receive function.
//
// Solidity: {{.Receive.Original.String}}
public Transaction Receive(TransactOpts opts) throws Exception {
return this.Contract.rawTransact(opts, null);
}
{{end}}
}
{{end}}
`
{{end}}

View file

@ -0,0 +1,247 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package {{.Package}}
import (
"bytes"
"math/big"
"errors"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
{{$structs := .Structs}}
{{range $structs}}
// {{.Name}} is an auto generated low-level Go binding around an user-defined struct.
type {{.Name}} struct {
{{range $field := .Fields}}
{{capitalise $field.Name}} {{$field.Type}}{{end}}
}
{{end}}
{{range $contract := .Contracts}}
// {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract.
var {{.Type}}MetaData = bind.MetaData{
ABI: "{{.InputABI}}",
{{if (index $.Libraries .Type) -}}
ID: "{{index $.Libraries .Type}}",
{{ else -}}
ID: "{{.Type}}",
{{end -}}
{{if .InputBin -}}
Bin: "0x{{.InputBin}}",
{{end -}}
{{if .Libraries -}}
Deps: []*bind.MetaData{
{{- range $name, $pattern := .Libraries}}
&{{$name}}MetaData,
{{- end}}
},
{{end}}
}
// {{.Type}} is an auto generated Go binding around an Ethereum contract.
type {{.Type}} struct {
abi abi.ABI
}
// New{{.Type}} creates a new instance of {{.Type}}.
func New{{.Type}}() *{{.Type}} {
parsed, err := {{.Type}}MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &{{.Type}}{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *{{.Type}}) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
{{ if .Constructor.Inputs }}
// PackConstructor is the Go binding used to pack the parameters required for
// contract deployment.
//
// Solidity: {{.Constructor.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) PackConstructor({{range .Constructor.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) []byte {
enc, err := {{ decapitalise $contract.Type}}.abi.Pack("" {{range .Constructor.Inputs}}, {{.Name}}{{end}})
if err != nil {
panic(err)
}
return enc
}
{{ end }}
{{range .Calls}}
// Pack{{.Normalized.Name}} is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x{{printf "%x" .Original.ID}}. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Pack{{.Normalized.Name}}({{range .Normalized.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) []byte {
enc, err := {{ decapitalise $contract.Type}}.abi.Pack("{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
if err != nil {
panic(err)
}
return enc
}
// TryPack{{.Normalized.Name}} is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x{{printf "%x" .Original.ID}}. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) TryPack{{.Normalized.Name}}({{range .Normalized.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) ([]byte, error) {
return {{ decapitalise $contract.Type}}.abi.Pack("{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
}
{{/* Unpack method is needed only when there are return args */}}
{{if .Normalized.Outputs }}
{{ if .Structured }}
// {{.Normalized.Name}}Output serves as a container for the return parameters of contract
// method {{ .Normalized.Name }}.
type {{.Normalized.Name}}Output struct {
{{range .Normalized.Outputs}}
{{capitalise .Name}} {{bindtype .Type $structs}}{{end}}
}
{{ end }}
// Unpack{{.Normalized.Name}} is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x{{printf "%x" .Original.ID}}.
//
// Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}(data []byte) (
{{- if .Structured}} {{.Normalized.Name}}Output,{{else}}
{{- range .Normalized.Outputs}} {{bindtype .Type $structs}},{{- end }}
{{- end }} error) {
out, err := {{ decapitalise $contract.Type}}.abi.Unpack("{{.Original.Name}}", data)
{{- if .Structured}}
outstruct := new({{.Normalized.Name}}Output)
if err != nil {
return *outstruct, err
}
{{- range $i, $t := .Normalized.Outputs}}
{{- if ispointertype .Type}}
outstruct.{{capitalise .Name}} = abi.ConvertType(out[{{$i}}], new({{underlyingbindtype .Type }})).({{bindtype .Type $structs}})
{{- else }}
outstruct.{{capitalise .Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}})
{{- end }}
{{- end }}
return *outstruct, nil{{else}}
if err != nil {
return {{range $i, $_ := .Normalized.Outputs}}{{if ispointertype .Type}}new({{underlyingbindtype .Type }}), {{else}}*new({{bindtype .Type $structs}}), {{end}}{{end}} err
}
{{- range $i, $t := .Normalized.Outputs}}
{{- if ispointertype .Type }}
out{{$i}} := abi.ConvertType(out[{{$i}}], new({{underlyingbindtype .Type}})).({{bindtype .Type $structs}})
{{- else }}
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}})
{{- end }}
{{- end}}
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} nil
{{- end}}
}
{{end}}
{{end}}
{{range .Events}}
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Original.Name}} event raised by the {{$contract.Type}} contract.
type {{$contract.Type}}{{.Normalized.Name}} struct {
{{- range .Normalized.Inputs}}
{{ capitalise .Name}}
{{- if .Indexed}} {{ bindtopictype .Type $structs}}{{- else}} {{ bindtype .Type $structs}}{{ end }}
{{- end}}
Raw *types.Log // Blockchain specific contextual infos
}
const {{$contract.Type}}{{.Normalized.Name}}EventName = "{{.Original.Name}}"
// ContractEventName returns the user-defined event name.
func ({{$contract.Type}}{{.Normalized.Name}}) ContractEventName() string {
return {{$contract.Type}}{{.Normalized.Name}}EventName
}
// Unpack{{.Normalized.Name}}Event is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Event(log *types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
event := "{{.Original.Name}}"
if len(log.Topics) == 0 || log.Topics[0] != {{ decapitalise $contract.Type}}.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new({{$contract.Type}}{{.Normalized.Name}})
if len(log.Data) > 0 {
if err := {{ decapitalise $contract.Type}}.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range {{ decapitalise $contract.Type}}.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
{{end}}
{{ if .Errors }}
// UnpackError attempts to decode the provided error data using user-defined
// error definitions.
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) UnpackError(raw []byte) (any, error) {
{{- range $k, $v := .Errors}}
if bytes.Equal(raw[:4], {{ decapitalise $contract.Type}}.abi.Errors["{{.Normalized.Name}}"].ID.Bytes()[:4]) {
return {{ decapitalise $contract.Type}}.Unpack{{.Normalized.Name}}Error(raw[4:])
}
{{- end }}
return nil, errors.New("Unknown error")
}
{{ end }}
{{range .Errors}}
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Original.Name}} error raised by the {{$contract.Type}} contract.
type {{$contract.Type}}{{.Normalized.Name}} struct { {{range .Normalized.Inputs}}
{{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type $structs}}{{else}}{{bindtype .Type $structs}}{{end}}; {{end}}
}
// ErrorID returns the hash of canonical representation of the error's signature.
//
// Solidity: {{.Original.String}}
func {{$contract.Type}}{{.Normalized.Name}}ErrorID() common.Hash {
return common.HexToHash("{{.Original.ID}}")
}
// Unpack{{.Normalized.Name}}Error is the Go binding used to decode the provided
// error data into the corresponding Go error struct.
//
// Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Error(raw []byte) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
out := new({{$contract.Type}}{{.Normalized.Name}})
if err := {{ decapitalise $contract.Type}}.abi.UnpackIntoInterface(out, "{{.Normalized.Name}}", raw); err != nil {
return nil, err
}
return out, nil
}
{{end}}
{{end}}

View file

@ -0,0 +1,136 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abigen
import (
_ "embed"
"strings"
"unicode"
"github.com/ethereum/go-ethereum/accounts/abi"
)
// tmplData is the data structure required to fill the binding template.
type tmplData struct {
Package string // Name of the package to place the generated file in
Contracts map[string]*tmplContract // List of contracts to generate into this file
Libraries map[string]string // Map the bytecode's link pattern to the library name
Structs map[string]*tmplStruct // Contract struct type definitions
}
// tmplContract contains the data needed to generate an individual contract binding.
type tmplContract struct {
Type string // Type name of the main contract binding
InputABI string // JSON ABI used as the input to generate the binding from
InputBin string // Optional EVM bytecode used to generate deploy code from
FuncSigs map[string]string // Optional map: string signature -> 4-byte signature
Constructor abi.Method // Contract constructor for deploy parametrization
Calls map[string]*tmplMethod // Contract calls that only read state data
Transacts map[string]*tmplMethod // Contract calls that write state data
Fallback *tmplMethod // Additional special fallback function
Receive *tmplMethod // Additional special receive function
Events map[string]*tmplEvent // Contract events accessors
Libraries map[string]string // Same as tmplData, but filtered to only keep direct deps that the contract needs
Library bool // Indicator whether the contract is a library
}
type tmplContractV2 struct {
Type string // Type name of the main contract binding
InputABI string // JSON ABI used as the input to generate the binding from
InputBin string // Optional EVM bytecode used to generate deploy code from
Constructor abi.Method // Contract constructor for deploy parametrization
Calls map[string]*tmplMethod // All contract methods (excluding fallback, receive)
Events map[string]*tmplEvent // Contract events accessors
Libraries map[string]string // all direct library dependencies
Errors map[string]*tmplError // all errors defined
}
func newTmplContractV2(typ string, abiStr string, bytecode string, constructor abi.Method, cb *contractBinder) *tmplContractV2 {
// Strip any whitespace from the JSON ABI
strippedABI := strings.Map(func(r rune) rune {
if unicode.IsSpace(r) {
return -1
}
return r
}, abiStr)
return &tmplContractV2{
abi.ToCamelCase(typ),
strings.ReplaceAll(strippedABI, "\"", "\\\""),
strings.TrimPrefix(strings.TrimSpace(bytecode), "0x"),
constructor,
cb.calls,
cb.events,
make(map[string]string),
cb.errors,
}
}
type tmplDataV2 struct {
Package string // Name of the package to use for the generated bindings
Contracts map[string]*tmplContractV2 // Contracts that will be emitted in the bindings (keyed by contract name)
Libraries map[string]string // Map of the contract's name to link pattern
Structs map[string]*tmplStruct // Contract struct type definitions
}
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
// and cached data fields.
type tmplMethod struct {
Original abi.Method // Original method as parsed by the abi package
Normalized abi.Method // Normalized version of the parsed method (capitalized names, non-anonymous args/returns)
Structured bool // Whether the returns should be accumulated into a struct
}
// tmplEvent is a wrapper around an abi.Event that contains a few preprocessed
// and cached data fields.
type tmplEvent struct {
Original abi.Event // Original event as parsed by the abi package
Normalized abi.Event // Normalized version of the parsed fields
}
// tmplError is a wrapper around an abi.Error that contains a few preprocessed
// and cached data fields.
type tmplError struct {
Original abi.Error
Normalized abi.Error
}
// tmplField is a wrapper around a struct field with binding language
// struct type definition and relative filed name.
type tmplField struct {
Type string // Field type representation depends on target binding language
Name string // Field name converted from the raw user-defined field name
SolKind abi.Type // Raw abi type information
}
// tmplStruct is a wrapper around an abi.tuple and contains an auto-generated
// struct name.
type tmplStruct struct {
Name string // Auto-generated struct name(before solidity v0.5.11) or raw name.
Fields []*tmplField // Struct fields definition depends on the binding language.
}
// tmplSource is the Go source template that the generated Go contract binding
// is based on.
//
//go:embed source.go.tpl
var tmplSource string
// tmplSourceV2 is the Go source template that the generated Go contract binding
// for abigen v2 is based on.
//
//go:embed source2.go.tpl
var tmplSourceV2 string

View file

@ -0,0 +1,74 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// CallbackParamMetaData contains all meta data concerning the CallbackParam contract.
var CallbackParamMetaData = bind.MetaData{
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"callback\",\"type\":\"function\"}],\"name\":\"test\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
ID: "949f96f86d3c2e1bcc15563ad898beaaca",
Bin: "0x608060405234801561001057600080fd5b5061015e806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063d7a5aba214610040575b600080fd5b34801561004c57600080fd5b506100be6004803603602081101561006357600080fd5b810190808035806c0100000000000000000000000090049068010000000000000000900463ffffffff1677ffffffffffffffffffffffffffffffffffffffffffffffff169091602001919093929190939291905050506100c0565b005b818160016040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561011657600080fd5b505af115801561012a573d6000803e3d6000fd5b50505050505056fea165627a7a7230582062f87455ff84be90896dbb0c4e4ddb505c600d23089f8e80a512548440d7e2580029",
}
// CallbackParam is an auto generated Go binding around an Ethereum contract.
type CallbackParam struct {
abi abi.ABI
}
// NewCallbackParam creates a new instance of CallbackParam.
func NewCallbackParam() *CallbackParam {
parsed, err := CallbackParamMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &CallbackParam{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *CallbackParam) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackTest is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd7a5aba2. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function test(function callback) returns()
func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte {
enc, err := callbackParam.abi.Pack("test", callback)
if err != nil {
panic(err)
}
return enc
}
// TryPackTest is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd7a5aba2. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function test(function callback) returns()
func (callbackParam *CallbackParam) TryPackTest(callback [24]byte) ([]byte, error) {
return callbackParam.abi.Pack("test", callback)
}

View file

@ -0,0 +1,383 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// CrowdsaleMetaData contains all meta data concerning the Crowdsale contract.
var CrowdsaleMetaData = bind.MetaData{
ABI: "[{\"constant\":false,\"inputs\":[],\"name\":\"checkGoalReached\",\"outputs\":[],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"deadline\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"tokenReward\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"fundingGoal\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"amountRaised\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"price\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"funders\",\"outputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"inputs\":[{\"name\":\"ifSuccessfulSendTo\",\"type\":\"address\"},{\"name\":\"fundingGoalInEthers\",\"type\":\"uint256\"},{\"name\":\"durationInMinutes\",\"type\":\"uint256\"},{\"name\":\"etherCostOfEachToken\",\"type\":\"uint256\"},{\"name\":\"addressOfTokenUsedAsReward\",\"type\":\"address\"}],\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"backer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"isContribution\",\"type\":\"bool\"}],\"name\":\"FundTransfer\",\"type\":\"event\"}]",
ID: "84d7e935785c5c648282d326307bb8fa0d",
Bin: "0x606060408190526007805460ff1916905560a0806105a883396101006040529051608051915160c05160e05160008054600160a060020a03199081169095178155670de0b6b3a7640000958602600155603c9093024201600355930260045560058054909216909217905561052f90819061007990396000f36060604052361561006c5760e060020a600035046301cb3b20811461008257806329dcb0cf1461014457806338af3eed1461014d5780636e66f6e91461015f5780637a3a0e84146101715780637b3e5e7b1461017a578063a035b1fe14610183578063dc0d3dff1461018c575b61020060075460009060ff161561032357610002565b61020060035460009042106103205760025460015490106103cb576002548154600160a060020a0316908290606082818181858883f150915460025460408051600160a060020a039390931683526020830191909152818101869052517fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6945090819003909201919050a15b60405160008054600160a060020a039081169230909116319082818181858883f150506007805460ff1916600117905550505050565b6103a160035481565b6103ab600054600160a060020a031681565b6103ab600554600160a060020a031681565b6103a160015481565b6103a160025481565b6103a160045481565b6103be60043560068054829081101561000257506000526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f8101547ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d409190910154600160a060020a03919091169082565b005b505050815481101561000257906000526020600020906002020160005060008201518160000160006101000a815481600160a060020a030219169083021790555060208201518160010160005055905050806002600082828250540192505081905550600560009054906101000a9004600160a060020a0316600160a060020a031663a9059cbb3360046000505484046040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505060408051600160a060020a03331681526020810184905260018183015290517fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf692509081900360600190a15b50565b5060a0604052336060908152346080819052600680546001810180835592939282908280158290116102025760020281600202836000526020600020918201910161020291905b8082111561039d57805473ffffffffffffffffffffffffffffffffffffffff19168155600060019190910190815561036a565b5090565b6060908152602090f35b600160a060020a03166060908152602090f35b6060918252608052604090f35b5b60065481101561010e576006805482908110156100025760009182526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0190600680549254600160a060020a0316928490811015610002576002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40015460405190915082818181858883f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf660066000508281548110156100025760008290526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01548154600160a060020a039190911691908490811015610002576002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40015460408051600160a060020a0394909416845260208401919091526000838201525191829003606001919050a16001016103cc56",
}
// Crowdsale is an auto generated Go binding around an Ethereum contract.
type Crowdsale struct {
abi abi.ABI
}
// NewCrowdsale creates a new instance of Crowdsale.
func NewCrowdsale() *Crowdsale {
parsed, err := CrowdsaleMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Crowdsale{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Crowdsale) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackConstructor is the Go binding used to pack the parameters required for
// contract deployment.
//
// Solidity: constructor(address ifSuccessfulSendTo, uint256 fundingGoalInEthers, uint256 durationInMinutes, uint256 etherCostOfEachToken, address addressOfTokenUsedAsReward) returns()
func (crowdsale *Crowdsale) PackConstructor(ifSuccessfulSendTo common.Address, fundingGoalInEthers *big.Int, durationInMinutes *big.Int, etherCostOfEachToken *big.Int, addressOfTokenUsedAsReward common.Address) []byte {
enc, err := crowdsale.abi.Pack("", ifSuccessfulSendTo, fundingGoalInEthers, durationInMinutes, etherCostOfEachToken, addressOfTokenUsedAsReward)
if err != nil {
panic(err)
}
return enc
}
// PackAmountRaised is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x7b3e5e7b. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function amountRaised() returns(uint256)
func (crowdsale *Crowdsale) PackAmountRaised() []byte {
enc, err := crowdsale.abi.Pack("amountRaised")
if err != nil {
panic(err)
}
return enc
}
// TryPackAmountRaised is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x7b3e5e7b. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function amountRaised() returns(uint256)
func (crowdsale *Crowdsale) TryPackAmountRaised() ([]byte, error) {
return crowdsale.abi.Pack("amountRaised")
}
// UnpackAmountRaised is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x7b3e5e7b.
//
// Solidity: function amountRaised() returns(uint256)
func (crowdsale *Crowdsale) UnpackAmountRaised(data []byte) (*big.Int, error) {
out, err := crowdsale.abi.Unpack("amountRaised", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackBeneficiary is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x38af3eed. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function beneficiary() returns(address)
func (crowdsale *Crowdsale) PackBeneficiary() []byte {
enc, err := crowdsale.abi.Pack("beneficiary")
if err != nil {
panic(err)
}
return enc
}
// TryPackBeneficiary is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x38af3eed. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function beneficiary() returns(address)
func (crowdsale *Crowdsale) TryPackBeneficiary() ([]byte, error) {
return crowdsale.abi.Pack("beneficiary")
}
// UnpackBeneficiary is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x38af3eed.
//
// Solidity: function beneficiary() returns(address)
func (crowdsale *Crowdsale) UnpackBeneficiary(data []byte) (common.Address, error) {
out, err := crowdsale.abi.Unpack("beneficiary", data)
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, nil
}
// PackCheckGoalReached is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x01cb3b20. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function checkGoalReached() returns()
func (crowdsale *Crowdsale) PackCheckGoalReached() []byte {
enc, err := crowdsale.abi.Pack("checkGoalReached")
if err != nil {
panic(err)
}
return enc
}
// TryPackCheckGoalReached is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x01cb3b20. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function checkGoalReached() returns()
func (crowdsale *Crowdsale) TryPackCheckGoalReached() ([]byte, error) {
return crowdsale.abi.Pack("checkGoalReached")
}
// PackDeadline is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x29dcb0cf. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function deadline() returns(uint256)
func (crowdsale *Crowdsale) PackDeadline() []byte {
enc, err := crowdsale.abi.Pack("deadline")
if err != nil {
panic(err)
}
return enc
}
// TryPackDeadline is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x29dcb0cf. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function deadline() returns(uint256)
func (crowdsale *Crowdsale) TryPackDeadline() ([]byte, error) {
return crowdsale.abi.Pack("deadline")
}
// UnpackDeadline is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x29dcb0cf.
//
// Solidity: function deadline() returns(uint256)
func (crowdsale *Crowdsale) UnpackDeadline(data []byte) (*big.Int, error) {
out, err := crowdsale.abi.Unpack("deadline", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackFunders is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xdc0d3dff. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function funders(uint256 ) returns(address addr, uint256 amount)
func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte {
enc, err := crowdsale.abi.Pack("funders", arg0)
if err != nil {
panic(err)
}
return enc
}
// TryPackFunders is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xdc0d3dff. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function funders(uint256 ) returns(address addr, uint256 amount)
func (crowdsale *Crowdsale) TryPackFunders(arg0 *big.Int) ([]byte, error) {
return crowdsale.abi.Pack("funders", arg0)
}
// FundersOutput serves as a container for the return parameters of contract
// method Funders.
type FundersOutput struct {
Addr common.Address
Amount *big.Int
}
// UnpackFunders is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xdc0d3dff.
//
// Solidity: function funders(uint256 ) returns(address addr, uint256 amount)
func (crowdsale *Crowdsale) UnpackFunders(data []byte) (FundersOutput, error) {
out, err := crowdsale.abi.Unpack("funders", data)
outstruct := new(FundersOutput)
if err != nil {
return *outstruct, err
}
outstruct.Addr = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
outstruct.Amount = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackFundingGoal is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x7a3a0e84. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function fundingGoal() returns(uint256)
func (crowdsale *Crowdsale) PackFundingGoal() []byte {
enc, err := crowdsale.abi.Pack("fundingGoal")
if err != nil {
panic(err)
}
return enc
}
// TryPackFundingGoal is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x7a3a0e84. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function fundingGoal() returns(uint256)
func (crowdsale *Crowdsale) TryPackFundingGoal() ([]byte, error) {
return crowdsale.abi.Pack("fundingGoal")
}
// UnpackFundingGoal is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x7a3a0e84.
//
// Solidity: function fundingGoal() returns(uint256)
func (crowdsale *Crowdsale) UnpackFundingGoal(data []byte) (*big.Int, error) {
out, err := crowdsale.abi.Unpack("fundingGoal", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackPrice is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xa035b1fe. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function price() returns(uint256)
func (crowdsale *Crowdsale) PackPrice() []byte {
enc, err := crowdsale.abi.Pack("price")
if err != nil {
panic(err)
}
return enc
}
// TryPackPrice is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xa035b1fe. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function price() returns(uint256)
func (crowdsale *Crowdsale) TryPackPrice() ([]byte, error) {
return crowdsale.abi.Pack("price")
}
// UnpackPrice is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xa035b1fe.
//
// Solidity: function price() returns(uint256)
func (crowdsale *Crowdsale) UnpackPrice(data []byte) (*big.Int, error) {
out, err := crowdsale.abi.Unpack("price", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackTokenReward is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6e66f6e9. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function tokenReward() returns(address)
func (crowdsale *Crowdsale) PackTokenReward() []byte {
enc, err := crowdsale.abi.Pack("tokenReward")
if err != nil {
panic(err)
}
return enc
}
// TryPackTokenReward is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6e66f6e9. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function tokenReward() returns(address)
func (crowdsale *Crowdsale) TryPackTokenReward() ([]byte, error) {
return crowdsale.abi.Pack("tokenReward")
}
// UnpackTokenReward is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6e66f6e9.
//
// Solidity: function tokenReward() returns(address)
func (crowdsale *Crowdsale) UnpackTokenReward(data []byte) (common.Address, error) {
out, err := crowdsale.abi.Unpack("tokenReward", data)
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, nil
}
// CrowdsaleFundTransfer represents a FundTransfer event raised by the Crowdsale contract.
type CrowdsaleFundTransfer struct {
Backer common.Address
Amount *big.Int
IsContribution bool
Raw *types.Log // Blockchain specific contextual infos
}
const CrowdsaleFundTransferEventName = "FundTransfer"
// ContractEventName returns the user-defined event name.
func (CrowdsaleFundTransfer) ContractEventName() string {
return CrowdsaleFundTransferEventName
}
// UnpackFundTransferEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event FundTransfer(address backer, uint256 amount, bool isContribution)
func (crowdsale *Crowdsale) UnpackFundTransferEvent(log *types.Log) (*CrowdsaleFundTransfer, error) {
event := "FundTransfer"
if len(log.Topics) == 0 || log.Topics[0] != crowdsale.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(CrowdsaleFundTransfer)
if len(log.Data) > 0 {
if err := crowdsale.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range crowdsale.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,144 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// DeeplyNestedArrayMetaData contains all meta data concerning the DeeplyNestedArray contract.
var DeeplyNestedArrayMetaData = bind.MetaData{
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"arr\",\"type\":\"uint64[3][4][5]\"}],\"name\":\"storeDeepUintArray\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"retrieveDeepArray\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64[3][4][5]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deepUint64Array\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
ID: "3a44c26b21f02743d5dbeb02d24a67bf41",
Bin: "0x6060604052341561000f57600080fd5b6106438061001e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063344248551461005c5780638ed4573a1461011457806398ed1856146101ab575b600080fd5b341561006757600080fd5b610112600480806107800190600580602002604051908101604052809291906000905b828210156101055783826101800201600480602002604051908101604052809291906000905b828210156100f25783826060020160038060200260405190810160405280929190826003602002808284378201915050505050815260200190600101906100b0565b505050508152602001906001019061008a565b5050505091905050610208565b005b341561011f57600080fd5b61012761021d565b604051808260056000925b8184101561019b578284602002015160046000925b8184101561018d5782846020020151600360200280838360005b8381101561017c578082015181840152602081019050610161565b505050509050019260010192610147565b925050509260010192610132565b9250505091505060405180910390f35b34156101b657600080fd5b6101de6004808035906020019091908035906020019091908035906020019091905050610309565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b80600090600561021992919061035f565b5050565b6102256103b0565b6000600580602002604051908101604052809291906000905b8282101561030057838260040201600480602002604051908101604052809291906000905b828210156102ed578382016003806020026040519081016040528092919082600380156102d9576020028201916000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff16815260200190600801906020826007010492830192600103820291508084116102945790505b505050505081526020019060010190610263565b505050508152602001906001019061023e565b50505050905090565b60008360058110151561031857fe5b600402018260048110151561032957fe5b018160038110151561033757fe5b6004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b826005600402810192821561039f579160200282015b8281111561039e5782518290600461038e9291906103df565b5091602001919060040190610375565b5b5090506103ac919061042d565b5090565b610780604051908101604052806005905b6103c9610459565b8152602001906001900390816103c15790505090565b826004810192821561041c579160200282015b8281111561041b5782518290600361040b929190610488565b50916020019190600101906103f2565b5b5090506104299190610536565b5090565b61045691905b8082111561045257600081816104499190610562565b50600401610433565b5090565b90565b610180604051908101604052806004905b6104726105a7565b81526020019060019003908161046a5790505090565b82600380016004900481019282156105255791602002820160005b838211156104ef57835183826101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555092602001926008016020816007010492830192600103026104a3565b80156105235782816101000a81549067ffffffffffffffff02191690556008016020816007010492830192600103026104ef565b505b50905061053291906105d9565b5090565b61055f91905b8082111561055b57600081816105529190610610565b5060010161053c565b5090565b90565b50600081816105719190610610565b50600101600081816105839190610610565b50600101600081816105959190610610565b5060010160006105a59190610610565b565b6060604051908101604052806003905b600067ffffffffffffffff168152602001906001900390816105b75790505090565b61060d91905b8082111561060957600081816101000a81549067ffffffffffffffff0219169055506001016105df565b5090565b90565b50600090555600a165627a7a7230582087e5a43f6965ab6ef7a4ff056ab80ed78fd8c15cff57715a1bf34ec76a93661c0029",
}
// DeeplyNestedArray is an auto generated Go binding around an Ethereum contract.
type DeeplyNestedArray struct {
abi abi.ABI
}
// NewDeeplyNestedArray creates a new instance of DeeplyNestedArray.
func NewDeeplyNestedArray() *DeeplyNestedArray {
parsed, err := DeeplyNestedArrayMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &DeeplyNestedArray{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *DeeplyNestedArray) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDeepUint64Array is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x98ed1856. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64)
func (deeplyNestedArray *DeeplyNestedArray) PackDeepUint64Array(arg0 *big.Int, arg1 *big.Int, arg2 *big.Int) []byte {
enc, err := deeplyNestedArray.abi.Pack("deepUint64Array", arg0, arg1, arg2)
if err != nil {
panic(err)
}
return enc
}
// TryPackDeepUint64Array is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x98ed1856. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64)
func (deeplyNestedArray *DeeplyNestedArray) TryPackDeepUint64Array(arg0 *big.Int, arg1 *big.Int, arg2 *big.Int) ([]byte, error) {
return deeplyNestedArray.abi.Pack("deepUint64Array", arg0, arg1, arg2)
}
// UnpackDeepUint64Array is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x98ed1856.
//
// Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64)
func (deeplyNestedArray *DeeplyNestedArray) UnpackDeepUint64Array(data []byte) (uint64, error) {
out, err := deeplyNestedArray.abi.Unpack("deepUint64Array", data)
if err != nil {
return *new(uint64), err
}
out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64)
return out0, nil
}
// PackRetrieveDeepArray is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x8ed4573a. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function retrieveDeepArray() view returns(uint64[3][4][5])
func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte {
enc, err := deeplyNestedArray.abi.Pack("retrieveDeepArray")
if err != nil {
panic(err)
}
return enc
}
// TryPackRetrieveDeepArray is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x8ed4573a. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function retrieveDeepArray() view returns(uint64[3][4][5])
func (deeplyNestedArray *DeeplyNestedArray) TryPackRetrieveDeepArray() ([]byte, error) {
return deeplyNestedArray.abi.Pack("retrieveDeepArray")
}
// UnpackRetrieveDeepArray is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x8ed4573a.
//
// Solidity: function retrieveDeepArray() view returns(uint64[3][4][5])
func (deeplyNestedArray *DeeplyNestedArray) UnpackRetrieveDeepArray(data []byte) ([5][4][3]uint64, error) {
out, err := deeplyNestedArray.abi.Unpack("retrieveDeepArray", data)
if err != nil {
return *new([5][4][3]uint64), err
}
out0 := *abi.ConvertType(out[0], new([5][4][3]uint64)).(*[5][4][3]uint64)
return out0, nil
}
// PackStoreDeepUintArray is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x34424855. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function storeDeepUintArray(uint64[3][4][5] arr) returns()
func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3]uint64) []byte {
enc, err := deeplyNestedArray.abi.Pack("storeDeepUintArray", arr)
if err != nil {
panic(err)
}
return enc
}
// TryPackStoreDeepUintArray is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x34424855. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function storeDeepUintArray(uint64[3][4][5] arr) returns()
func (deeplyNestedArray *DeeplyNestedArray) TryPackStoreDeepUintArray(arr [5][4][3]uint64) ([]byte, error) {
return deeplyNestedArray.abi.Pack("storeDeepUintArray", arr)
}

View file

@ -0,0 +1,52 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// EmptyMetaData contains all meta data concerning the Empty contract.
var EmptyMetaData = bind.MetaData{
ABI: "[]",
ID: "c4ce3210982aa6fc94dabe46dc1dbf454d",
Bin: "0x606060405260068060106000396000f3606060405200",
}
// Empty is an auto generated Go binding around an Ethereum contract.
type Empty struct {
abi abi.ABI
}
// NewEmpty creates a new instance of Empty.
func NewEmpty() *Empty {
parsed, err := EmptyMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Empty{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Empty) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}

View file

@ -0,0 +1,261 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// EventCheckerMetaData contains all meta data concerning the EventChecker contract.
var EventCheckerMetaData = bind.MetaData{
ABI: "[{\"type\":\"event\",\"name\":\"empty\",\"inputs\":[]},{\"type\":\"event\",\"name\":\"indexed\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"indexed\":true},{\"name\":\"num\",\"type\":\"int256\",\"indexed\":true}]},{\"type\":\"event\",\"name\":\"mixed\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"indexed\":true},{\"name\":\"num\",\"type\":\"int256\"}]},{\"type\":\"event\",\"name\":\"anonymous\",\"anonymous\":true,\"inputs\":[]},{\"type\":\"event\",\"name\":\"dynamic\",\"inputs\":[{\"name\":\"idxStr\",\"type\":\"string\",\"indexed\":true},{\"name\":\"idxDat\",\"type\":\"bytes\",\"indexed\":true},{\"name\":\"str\",\"type\":\"string\"},{\"name\":\"dat\",\"type\":\"bytes\"}]},{\"type\":\"event\",\"name\":\"unnamed\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true}]}]",
ID: "253d421f98e29b25315bde79c1251ab27c",
}
// EventChecker is an auto generated Go binding around an Ethereum contract.
type EventChecker struct {
abi abi.ABI
}
// NewEventChecker creates a new instance of EventChecker.
func NewEventChecker() *EventChecker {
parsed, err := EventCheckerMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &EventChecker{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *EventChecker) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// EventCheckerDynamic represents a dynamic event raised by the EventChecker contract.
type EventCheckerDynamic struct {
IdxStr common.Hash
IdxDat common.Hash
Str string
Dat []byte
Raw *types.Log // Blockchain specific contextual infos
}
const EventCheckerDynamicEventName = "dynamic"
// ContractEventName returns the user-defined event name.
func (EventCheckerDynamic) ContractEventName() string {
return EventCheckerDynamicEventName
}
// UnpackDynamicEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event dynamic(string indexed idxStr, bytes indexed idxDat, string str, bytes dat)
func (eventChecker *EventChecker) UnpackDynamicEvent(log *types.Log) (*EventCheckerDynamic, error) {
event := "dynamic"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(EventCheckerDynamic)
if len(log.Data) > 0 {
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range eventChecker.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// EventCheckerEmpty represents a empty event raised by the EventChecker contract.
type EventCheckerEmpty struct {
Raw *types.Log // Blockchain specific contextual infos
}
const EventCheckerEmptyEventName = "empty"
// ContractEventName returns the user-defined event name.
func (EventCheckerEmpty) ContractEventName() string {
return EventCheckerEmptyEventName
}
// UnpackEmptyEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event empty()
func (eventChecker *EventChecker) UnpackEmptyEvent(log *types.Log) (*EventCheckerEmpty, error) {
event := "empty"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(EventCheckerEmpty)
if len(log.Data) > 0 {
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range eventChecker.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// EventCheckerIndexed represents a indexed event raised by the EventChecker contract.
type EventCheckerIndexed struct {
Addr common.Address
Num *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const EventCheckerIndexedEventName = "indexed"
// ContractEventName returns the user-defined event name.
func (EventCheckerIndexed) ContractEventName() string {
return EventCheckerIndexedEventName
}
// UnpackIndexedEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event indexed(address indexed addr, int256 indexed num)
func (eventChecker *EventChecker) UnpackIndexedEvent(log *types.Log) (*EventCheckerIndexed, error) {
event := "indexed"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(EventCheckerIndexed)
if len(log.Data) > 0 {
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range eventChecker.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// EventCheckerMixed represents a mixed event raised by the EventChecker contract.
type EventCheckerMixed struct {
Addr common.Address
Num *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const EventCheckerMixedEventName = "mixed"
// ContractEventName returns the user-defined event name.
func (EventCheckerMixed) ContractEventName() string {
return EventCheckerMixedEventName
}
// UnpackMixedEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event mixed(address indexed addr, int256 num)
func (eventChecker *EventChecker) UnpackMixedEvent(log *types.Log) (*EventCheckerMixed, error) {
event := "mixed"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(EventCheckerMixed)
if len(log.Data) > 0 {
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range eventChecker.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// EventCheckerUnnamed represents a unnamed event raised by the EventChecker contract.
type EventCheckerUnnamed struct {
Arg0 *big.Int
Arg1 *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const EventCheckerUnnamedEventName = "unnamed"
// ContractEventName returns the user-defined event name.
func (EventCheckerUnnamed) ContractEventName() string {
return EventCheckerUnnamedEventName
}
// UnpackUnnamedEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event unnamed(uint256 indexed arg0, uint256 indexed arg1)
func (eventChecker *EventChecker) UnpackUnnamedEvent(log *types.Log) (*EventCheckerUnnamed, error) {
event := "unnamed"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(EventCheckerUnnamed)
if len(log.Data) > 0 {
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range eventChecker.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

View file

@ -0,0 +1,98 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// GetterMetaData contains all meta data concerning the Getter contract.
var GetterMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"getter\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"int256\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"type\":\"function\"}]",
ID: "e23a74c8979fe93c9fff15e4f51535ad54",
Bin: "0x606060405260dc8060106000396000f3606060405260e060020a6000350463993a04b78114601a575b005b600060605260c0604052600260809081527f486900000000000000000000000000000000000000000000000000000000000060a05260017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060e0829052610100819052606060c0908152600261012081905281906101409060a09080838184600060046012f1505081517fffff000000000000000000000000000000000000000000000000000000000000169091525050604051610160819003945092505050f3",
}
// Getter is an auto generated Go binding around an Ethereum contract.
type Getter struct {
abi abi.ABI
}
// NewGetter creates a new instance of Getter.
func NewGetter() *Getter {
parsed, err := GetterMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Getter{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Getter) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackGetter is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x993a04b7. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function getter() returns(string, int256, bytes32)
func (getter *Getter) PackGetter() []byte {
enc, err := getter.abi.Pack("getter")
if err != nil {
panic(err)
}
return enc
}
// TryPackGetter is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x993a04b7. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function getter() returns(string, int256, bytes32)
func (getter *Getter) TryPackGetter() ([]byte, error) {
return getter.abi.Pack("getter")
}
// GetterOutput serves as a container for the return parameters of contract
// method Getter.
type GetterOutput struct {
Arg0 string
Arg1 *big.Int
Arg2 [32]byte
}
// UnpackGetter is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x993a04b7.
//
// Solidity: function getter() returns(string, int256, bytes32)
func (getter *Getter) UnpackGetter(data []byte) (GetterOutput, error) {
out, err := getter.abi.Unpack("getter", data)
outstruct := new(GetterOutput)
if err != nil {
return *outstruct, err
}
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
outstruct.Arg2 = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
return *outstruct, nil
}

View file

@ -0,0 +1,122 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// IdentifierCollisionMetaData contains all meta data concerning the IdentifierCollision contract.
var IdentifierCollisionMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"MyVar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_myVar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
ID: "1863c5622f8ac2c09c42f063ca883fe438",
Bin: "0x60806040523480156100115760006000fd5b50610017565b60c3806100256000396000f3fe608060405234801560105760006000fd5b506004361060365760003560e01c806301ad4d8714603c5780634ef1f0ad146058576036565b60006000fd5b60426074565b6040518082815260200191505060405180910390f35b605e607d565b6040518082815260200191505060405180910390f35b60006000505481565b60006000600050549050608b565b9056fea265627a7a7231582067c8d84688b01c4754ba40a2a871cede94ea1f28b5981593ab2a45b46ac43af664736f6c634300050c0032",
}
// IdentifierCollision is an auto generated Go binding around an Ethereum contract.
type IdentifierCollision struct {
abi abi.ABI
}
// NewIdentifierCollision creates a new instance of IdentifierCollision.
func NewIdentifierCollision() *IdentifierCollision {
parsed, err := IdentifierCollisionMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &IdentifierCollision{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *IdentifierCollision) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackMyVar is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x4ef1f0ad. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function MyVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) PackMyVar() []byte {
enc, err := identifierCollision.abi.Pack("MyVar")
if err != nil {
panic(err)
}
return enc
}
// TryPackMyVar is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x4ef1f0ad. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function MyVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) TryPackMyVar() ([]byte, error) {
return identifierCollision.abi.Pack("MyVar")
}
// UnpackMyVar is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x4ef1f0ad.
//
// Solidity: function MyVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) UnpackMyVar(data []byte) (*big.Int, error) {
out, err := identifierCollision.abi.Unpack("MyVar", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackPubVar is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x01ad4d87. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function _myVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) PackPubVar() []byte {
enc, err := identifierCollision.abi.Pack("_myVar")
if err != nil {
panic(err)
}
return enc
}
// TryPackPubVar is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x01ad4d87. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function _myVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) TryPackPubVar() ([]byte, error) {
return identifierCollision.abi.Pack("_myVar")
}
// UnpackPubVar is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x01ad4d87.
//
// Solidity: function _myVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) UnpackPubVar(data []byte) (*big.Int, error) {
out, err := identifierCollision.abi.Unpack("_myVar", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}

View file

@ -0,0 +1,183 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// InputCheckerMetaData contains all meta data concerning the InputChecker contract.
var InputCheckerMetaData = bind.MetaData{
ABI: "[{\"type\":\"function\",\"name\":\"noInput\",\"constant\":true,\"inputs\":[],\"outputs\":[]},{\"type\":\"function\",\"name\":\"namedInput\",\"constant\":true,\"inputs\":[{\"name\":\"str\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"anonInput\",\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"namedInputs\",\"constant\":true,\"inputs\":[{\"name\":\"str1\",\"type\":\"string\"},{\"name\":\"str2\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"anonInputs\",\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"mixedInputs\",\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"str\",\"type\":\"string\"}],\"outputs\":[]}]",
ID: "e551ce092312e54f54f45ffdf06caa4cdc",
}
// InputChecker is an auto generated Go binding around an Ethereum contract.
type InputChecker struct {
abi abi.ABI
}
// NewInputChecker creates a new instance of InputChecker.
func NewInputChecker() *InputChecker {
parsed, err := InputCheckerMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &InputChecker{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *InputChecker) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackAnonInput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x3e708e82. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function anonInput(string ) returns()
func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte {
enc, err := inputChecker.abi.Pack("anonInput", arg0)
if err != nil {
panic(err)
}
return enc
}
// TryPackAnonInput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x3e708e82. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function anonInput(string ) returns()
func (inputChecker *InputChecker) TryPackAnonInput(arg0 string) ([]byte, error) {
return inputChecker.abi.Pack("anonInput", arg0)
}
// PackAnonInputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x28160527. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function anonInputs(string , string ) returns()
func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byte {
enc, err := inputChecker.abi.Pack("anonInputs", arg0, arg1)
if err != nil {
panic(err)
}
return enc
}
// TryPackAnonInputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x28160527. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function anonInputs(string , string ) returns()
func (inputChecker *InputChecker) TryPackAnonInputs(arg0 string, arg1 string) ([]byte, error) {
return inputChecker.abi.Pack("anonInputs", arg0, arg1)
}
// PackMixedInputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xc689ebdc. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function mixedInputs(string , string str) returns()
func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byte {
enc, err := inputChecker.abi.Pack("mixedInputs", arg0, str)
if err != nil {
panic(err)
}
return enc
}
// TryPackMixedInputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xc689ebdc. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function mixedInputs(string , string str) returns()
func (inputChecker *InputChecker) TryPackMixedInputs(arg0 string, str string) ([]byte, error) {
return inputChecker.abi.Pack("mixedInputs", arg0, str)
}
// PackNamedInput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x0d402005. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function namedInput(string str) returns()
func (inputChecker *InputChecker) PackNamedInput(str string) []byte {
enc, err := inputChecker.abi.Pack("namedInput", str)
if err != nil {
panic(err)
}
return enc
}
// TryPackNamedInput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x0d402005. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function namedInput(string str) returns()
func (inputChecker *InputChecker) TryPackNamedInput(str string) ([]byte, error) {
return inputChecker.abi.Pack("namedInput", str)
}
// PackNamedInputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x63c796ed. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function namedInputs(string str1, string str2) returns()
func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []byte {
enc, err := inputChecker.abi.Pack("namedInputs", str1, str2)
if err != nil {
panic(err)
}
return enc
}
// TryPackNamedInputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x63c796ed. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function namedInputs(string str1, string str2) returns()
func (inputChecker *InputChecker) TryPackNamedInputs(str1 string, str2 string) ([]byte, error) {
return inputChecker.abi.Pack("namedInputs", str1, str2)
}
// PackNoInput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x53539029. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function noInput() returns()
func (inputChecker *InputChecker) PackNoInput() []byte {
enc, err := inputChecker.abi.Pack("noInput")
if err != nil {
panic(err)
}
return enc
}
// TryPackNoInput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x53539029. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function noInput() returns()
func (inputChecker *InputChecker) TryPackNoInput() ([]byte, error) {
return inputChecker.abi.Pack("noInput")
}

View file

@ -0,0 +1,156 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// InteractorMetaData contains all meta data concerning the Interactor contract.
var InteractorMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"transactString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"deployString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"str\",\"type\":\"string\"}],\"name\":\"transact\",\"outputs\":[],\"type\":\"function\"},{\"inputs\":[{\"name\":\"str\",\"type\":\"string\"}],\"type\":\"constructor\"}]",
ID: "f63980878028f3242c9033fdc30fd21a81",
Bin: "0x6060604052604051610328380380610328833981016040528051018060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10608d57805160ff19168380011785555b50607c9291505b8082111560ba57838155600101606b565b50505061026a806100be6000396000f35b828001600101855582156064579182015b828111156064578251826000505591602001919060010190609e565b509056606060405260e060020a60003504630d86a0e181146100315780636874e8091461008d578063d736c513146100ea575b005b610190600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102295780601f106101fe57610100808354040283529160200191610229565b61019060008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102295780601f106101fe57610100808354040283529160200191610229565b60206004803580820135601f81018490049093026080908101604052606084815261002f946024939192918401918190838280828437509496505050505050508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061023157805160ff19168380011785555b506102619291505b808211156102665760008155830161017d565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b820191906000526020600020905b81548152906001019060200180831161020c57829003601f168201915b505050505081565b82800160010185558215610175579182015b82811115610175578251826000505591602001919060010190610243565b505050565b509056",
}
// Interactor is an auto generated Go binding around an Ethereum contract.
type Interactor struct {
abi abi.ABI
}
// NewInteractor creates a new instance of Interactor.
func NewInteractor() *Interactor {
parsed, err := InteractorMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Interactor{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Interactor) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackConstructor is the Go binding used to pack the parameters required for
// contract deployment.
//
// Solidity: constructor(string str) returns()
func (interactor *Interactor) PackConstructor(str string) []byte {
enc, err := interactor.abi.Pack("", str)
if err != nil {
panic(err)
}
return enc
}
// PackDeployString is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6874e809. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function deployString() returns(string)
func (interactor *Interactor) PackDeployString() []byte {
enc, err := interactor.abi.Pack("deployString")
if err != nil {
panic(err)
}
return enc
}
// TryPackDeployString is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6874e809. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function deployString() returns(string)
func (interactor *Interactor) TryPackDeployString() ([]byte, error) {
return interactor.abi.Pack("deployString")
}
// UnpackDeployString is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6874e809.
//
// Solidity: function deployString() returns(string)
func (interactor *Interactor) UnpackDeployString(data []byte) (string, error) {
out, err := interactor.abi.Unpack("deployString", data)
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, nil
}
// PackTransact is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd736c513. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function transact(string str) returns()
func (interactor *Interactor) PackTransact(str string) []byte {
enc, err := interactor.abi.Pack("transact", str)
if err != nil {
panic(err)
}
return enc
}
// TryPackTransact is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd736c513. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function transact(string str) returns()
func (interactor *Interactor) TryPackTransact(str string) ([]byte, error) {
return interactor.abi.Pack("transact", str)
}
// PackTransactString is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x0d86a0e1. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function transactString() returns(string)
func (interactor *Interactor) PackTransactString() []byte {
enc, err := interactor.abi.Pack("transactString")
if err != nil {
panic(err)
}
return enc
}
// TryPackTransactString is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x0d86a0e1. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function transactString() returns(string)
func (interactor *Interactor) TryPackTransactString() ([]byte, error) {
return interactor.abi.Pack("transactString")
}
// UnpackTransactString is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x0d86a0e1.
//
// Solidity: function transactString() returns(string)
func (interactor *Interactor) UnpackTransactString(data []byte) (string, error) {
out, err := interactor.abi.Unpack("transactString", data)
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, nil
}

View file

@ -0,0 +1,157 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// Oraclerequest is an auto generated low-level Go binding around an user-defined struct.
type Oraclerequest struct {
Data []byte
Data0 []byte
}
// NameConflictMetaData contains all meta data concerning the NameConflict contract.
var NameConflictMetaData = bind.MetaData{
ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"msg\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"_msg\",\"type\":\"int256\"}],\"name\":\"log\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"internalType\":\"structoracle.request\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"addRequest\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"internalType\":\"structoracle.request\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "8f6e2703b307244ae6bd61ed94ce959cf9",
Bin: "0x608060405234801561001057600080fd5b5061042b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063c2bb515f1461003b578063cce7b04814610059575b600080fd5b610043610075565b60405161005091906101af565b60405180910390f35b610073600480360381019061006e91906103ac565b6100b5565b005b61007d6100b8565b604051806040016040528060405180602001604052806000815250815260200160405180602001604052806000815250815250905090565b50565b604051806040016040528060608152602001606081525090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561010c5780820151818401526020810190506100f1565b8381111561011b576000848401525b50505050565b6000601f19601f8301169050919050565b600061013d826100d2565b61014781856100dd565b93506101578185602086016100ee565b61016081610121565b840191505092915050565b600060408301600083015184820360008601526101888282610132565b915050602083015184820360208601526101a28282610132565b9150508091505092915050565b600060208201905081810360008301526101c9818461016b565b905092915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61022282610121565b810181811067ffffffffffffffff82111715610241576102406101ea565b5b80604052505050565b60006102546101d1565b90506102608282610219565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561028f5761028e6101ea565b5b61029882610121565b9050602081019050919050565b82818337600083830152505050565b60006102c76102c284610274565b61024a565b9050828152602081018484840111156102e3576102e261026f565b5b6102ee8482856102a5565b509392505050565b600082601f83011261030b5761030a61026a565b5b813561031b8482602086016102b4565b91505092915050565b60006040828403121561033a576103396101e5565b5b610344604061024a565b9050600082013567ffffffffffffffff81111561036457610363610265565b5b610370848285016102f6565b600083015250602082013567ffffffffffffffff81111561039457610393610265565b5b6103a0848285016102f6565b60208301525092915050565b6000602082840312156103c2576103c16101db565b5b600082013567ffffffffffffffff8111156103e0576103df6101e0565b5b6103ec84828501610324565b9150509291505056fea264697066735822122033bca1606af9b6aeba1673f98c52003cec19338539fb44b86690ce82c51483b564736f6c634300080e0033",
}
// NameConflict is an auto generated Go binding around an Ethereum contract.
type NameConflict struct {
abi abi.ABI
}
// NewNameConflict creates a new instance of NameConflict.
func NewNameConflict() *NameConflict {
parsed, err := NameConflictMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &NameConflict{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *NameConflict) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackAddRequest is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xcce7b048. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function addRequest((bytes,bytes) req) pure returns()
func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte {
enc, err := nameConflict.abi.Pack("addRequest", req)
if err != nil {
panic(err)
}
return enc
}
// TryPackAddRequest is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xcce7b048. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function addRequest((bytes,bytes) req) pure returns()
func (nameConflict *NameConflict) TryPackAddRequest(req Oraclerequest) ([]byte, error) {
return nameConflict.abi.Pack("addRequest", req)
}
// PackGetRequest is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xc2bb515f. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function getRequest() pure returns((bytes,bytes))
func (nameConflict *NameConflict) PackGetRequest() []byte {
enc, err := nameConflict.abi.Pack("getRequest")
if err != nil {
panic(err)
}
return enc
}
// TryPackGetRequest is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xc2bb515f. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function getRequest() pure returns((bytes,bytes))
func (nameConflict *NameConflict) TryPackGetRequest() ([]byte, error) {
return nameConflict.abi.Pack("getRequest")
}
// UnpackGetRequest is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xc2bb515f.
//
// Solidity: function getRequest() pure returns((bytes,bytes))
func (nameConflict *NameConflict) UnpackGetRequest(data []byte) (Oraclerequest, error) {
out, err := nameConflict.abi.Unpack("getRequest", data)
if err != nil {
return *new(Oraclerequest), err
}
out0 := *abi.ConvertType(out[0], new(Oraclerequest)).(*Oraclerequest)
return out0, nil
}
// NameConflictLog represents a log event raised by the NameConflict contract.
type NameConflictLog struct {
Msg *big.Int
Msg0 *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const NameConflictLogEventName = "log"
// ContractEventName returns the user-defined event name.
func (NameConflictLog) ContractEventName() string {
return NameConflictLogEventName
}
// UnpackLogEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event log(int256 msg, int256 _msg)
func (nameConflict *NameConflict) UnpackLogEvent(log *types.Log) (*NameConflictLog, error) {
event := "log"
if len(log.Topics) == 0 || log.Topics[0] != nameConflict.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(NameConflictLog)
if len(log.Data) > 0 {
if err := nameConflict.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range nameConflict.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

View file

@ -0,0 +1,159 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// NumericMethodNameMetaData contains all meta data concerning the NumericMethodName contract.
var NumericMethodNameMetaData = bind.MetaData{
ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_param\",\"type\":\"address\"}],\"name\":\"_1TestEvent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_1test\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"__1test\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"__2test\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "a691b347afbc44b90dd9a1dfbc65661904",
Bin: "0x6080604052348015600f57600080fd5b5060958061001e6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80639d993132146041578063d02767c7146049578063ffa02795146051575b600080fd5b60476059565b005b604f605b565b005b6057605d565b005b565b565b56fea26469706673582212200382ca602dff96a7e2ba54657985e2b4ac423a56abe4a1f0667bc635c4d4371f64736f6c63430008110033",
}
// NumericMethodName is an auto generated Go binding around an Ethereum contract.
type NumericMethodName struct {
abi abi.ABI
}
// NewNumericMethodName creates a new instance of NumericMethodName.
func NewNumericMethodName() *NumericMethodName {
parsed, err := NumericMethodNameMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &NumericMethodName{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *NumericMethodName) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackE1test is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xffa02795. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function _1test() pure returns()
func (numericMethodName *NumericMethodName) PackE1test() []byte {
enc, err := numericMethodName.abi.Pack("_1test")
if err != nil {
panic(err)
}
return enc
}
// TryPackE1test is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xffa02795. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function _1test() pure returns()
func (numericMethodName *NumericMethodName) TryPackE1test() ([]byte, error) {
return numericMethodName.abi.Pack("_1test")
}
// PackE1test0 is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd02767c7. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function __1test() pure returns()
func (numericMethodName *NumericMethodName) PackE1test0() []byte {
enc, err := numericMethodName.abi.Pack("__1test")
if err != nil {
panic(err)
}
return enc
}
// TryPackE1test0 is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd02767c7. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function __1test() pure returns()
func (numericMethodName *NumericMethodName) TryPackE1test0() ([]byte, error) {
return numericMethodName.abi.Pack("__1test")
}
// PackE2test is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x9d993132. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function __2test() pure returns()
func (numericMethodName *NumericMethodName) PackE2test() []byte {
enc, err := numericMethodName.abi.Pack("__2test")
if err != nil {
panic(err)
}
return enc
}
// TryPackE2test is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x9d993132. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function __2test() pure returns()
func (numericMethodName *NumericMethodName) TryPackE2test() ([]byte, error) {
return numericMethodName.abi.Pack("__2test")
}
// NumericMethodNameE1TestEvent represents a _1TestEvent event raised by the NumericMethodName contract.
type NumericMethodNameE1TestEvent struct {
Param common.Address
Raw *types.Log // Blockchain specific contextual infos
}
const NumericMethodNameE1TestEventEventName = "_1TestEvent"
// ContractEventName returns the user-defined event name.
func (NumericMethodNameE1TestEvent) ContractEventName() string {
return NumericMethodNameE1TestEventEventName
}
// UnpackE1TestEventEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event _1TestEvent(address _param)
func (numericMethodName *NumericMethodName) UnpackE1TestEventEvent(log *types.Log) (*NumericMethodNameE1TestEvent, error) {
event := "_1TestEvent"
if len(log.Topics) == 0 || log.Topics[0] != numericMethodName.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(NumericMethodNameE1TestEvent)
if len(log.Data) > 0 {
if err := numericMethodName.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range numericMethodName.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

View file

@ -0,0 +1,319 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// OutputCheckerMetaData contains all meta data concerning the OutputChecker contract.
var OutputCheckerMetaData = bind.MetaData{
ABI: "[{\"type\":\"function\",\"name\":\"noOutput\",\"constant\":true,\"inputs\":[],\"outputs\":[]},{\"type\":\"function\",\"name\":\"namedOutput\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"str\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"anonOutput\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"namedOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"str1\",\"type\":\"string\"},{\"name\":\"str2\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"collidingOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"str\",\"type\":\"string\"},{\"name\":\"Str\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"anonOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"mixedOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"str\",\"type\":\"string\"}]}]",
ID: "cc1d4e235801a590b506d5130b0cca90a1",
}
// OutputChecker is an auto generated Go binding around an Ethereum contract.
type OutputChecker struct {
abi abi.ABI
}
// NewOutputChecker creates a new instance of OutputChecker.
func NewOutputChecker() *OutputChecker {
parsed, err := OutputCheckerMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &OutputChecker{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *OutputChecker) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackAnonOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x008bda05. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function anonOutput() returns(string)
func (outputChecker *OutputChecker) PackAnonOutput() []byte {
enc, err := outputChecker.abi.Pack("anonOutput")
if err != nil {
panic(err)
}
return enc
}
// TryPackAnonOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x008bda05. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function anonOutput() returns(string)
func (outputChecker *OutputChecker) TryPackAnonOutput() ([]byte, error) {
return outputChecker.abi.Pack("anonOutput")
}
// UnpackAnonOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x008bda05.
//
// Solidity: function anonOutput() returns(string)
func (outputChecker *OutputChecker) UnpackAnonOutput(data []byte) (string, error) {
out, err := outputChecker.abi.Unpack("anonOutput", data)
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, nil
}
// PackAnonOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x3c401115. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function anonOutputs() returns(string, string)
func (outputChecker *OutputChecker) PackAnonOutputs() []byte {
enc, err := outputChecker.abi.Pack("anonOutputs")
if err != nil {
panic(err)
}
return enc
}
// TryPackAnonOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x3c401115. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function anonOutputs() returns(string, string)
func (outputChecker *OutputChecker) TryPackAnonOutputs() ([]byte, error) {
return outputChecker.abi.Pack("anonOutputs")
}
// AnonOutputsOutput serves as a container for the return parameters of contract
// method AnonOutputs.
type AnonOutputsOutput struct {
Arg0 string
Arg1 string
}
// UnpackAnonOutputs is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x3c401115.
//
// Solidity: function anonOutputs() returns(string, string)
func (outputChecker *OutputChecker) UnpackAnonOutputs(data []byte) (AnonOutputsOutput, error) {
out, err := outputChecker.abi.Unpack("anonOutputs", data)
outstruct := new(AnonOutputsOutput)
if err != nil {
return *outstruct, err
}
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Arg1 = *abi.ConvertType(out[1], new(string)).(*string)
return *outstruct, nil
}
// PackCollidingOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xeccbc1ee. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function collidingOutputs() returns(string str, string Str)
func (outputChecker *OutputChecker) PackCollidingOutputs() []byte {
enc, err := outputChecker.abi.Pack("collidingOutputs")
if err != nil {
panic(err)
}
return enc
}
// TryPackCollidingOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xeccbc1ee. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function collidingOutputs() returns(string str, string Str)
func (outputChecker *OutputChecker) TryPackCollidingOutputs() ([]byte, error) {
return outputChecker.abi.Pack("collidingOutputs")
}
// CollidingOutputsOutput serves as a container for the return parameters of contract
// method CollidingOutputs.
type CollidingOutputsOutput struct {
Str string
Str0 string
}
// UnpackCollidingOutputs is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xeccbc1ee.
//
// Solidity: function collidingOutputs() returns(string str, string Str)
func (outputChecker *OutputChecker) UnpackCollidingOutputs(data []byte) (CollidingOutputsOutput, error) {
out, err := outputChecker.abi.Unpack("collidingOutputs", data)
outstruct := new(CollidingOutputsOutput)
if err != nil {
return *outstruct, err
}
outstruct.Str = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Str0 = *abi.ConvertType(out[1], new(string)).(*string)
return *outstruct, nil
}
// PackMixedOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x21b77b44. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function mixedOutputs() returns(string, string str)
func (outputChecker *OutputChecker) PackMixedOutputs() []byte {
enc, err := outputChecker.abi.Pack("mixedOutputs")
if err != nil {
panic(err)
}
return enc
}
// TryPackMixedOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x21b77b44. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function mixedOutputs() returns(string, string str)
func (outputChecker *OutputChecker) TryPackMixedOutputs() ([]byte, error) {
return outputChecker.abi.Pack("mixedOutputs")
}
// MixedOutputsOutput serves as a container for the return parameters of contract
// method MixedOutputs.
type MixedOutputsOutput struct {
Arg0 string
Str string
}
// UnpackMixedOutputs is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x21b77b44.
//
// Solidity: function mixedOutputs() returns(string, string str)
func (outputChecker *OutputChecker) UnpackMixedOutputs(data []byte) (MixedOutputsOutput, error) {
out, err := outputChecker.abi.Unpack("mixedOutputs", data)
outstruct := new(MixedOutputsOutput)
if err != nil {
return *outstruct, err
}
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Str = *abi.ConvertType(out[1], new(string)).(*string)
return *outstruct, nil
}
// PackNamedOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x5e632bd5. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function namedOutput() returns(string str)
func (outputChecker *OutputChecker) PackNamedOutput() []byte {
enc, err := outputChecker.abi.Pack("namedOutput")
if err != nil {
panic(err)
}
return enc
}
// TryPackNamedOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x5e632bd5. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function namedOutput() returns(string str)
func (outputChecker *OutputChecker) TryPackNamedOutput() ([]byte, error) {
return outputChecker.abi.Pack("namedOutput")
}
// UnpackNamedOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x5e632bd5.
//
// Solidity: function namedOutput() returns(string str)
func (outputChecker *OutputChecker) UnpackNamedOutput(data []byte) (string, error) {
out, err := outputChecker.abi.Unpack("namedOutput", data)
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, nil
}
// PackNamedOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x7970a189. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function namedOutputs() returns(string str1, string str2)
func (outputChecker *OutputChecker) PackNamedOutputs() []byte {
enc, err := outputChecker.abi.Pack("namedOutputs")
if err != nil {
panic(err)
}
return enc
}
// TryPackNamedOutputs is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x7970a189. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function namedOutputs() returns(string str1, string str2)
func (outputChecker *OutputChecker) TryPackNamedOutputs() ([]byte, error) {
return outputChecker.abi.Pack("namedOutputs")
}
// NamedOutputsOutput serves as a container for the return parameters of contract
// method NamedOutputs.
type NamedOutputsOutput struct {
Str1 string
Str2 string
}
// UnpackNamedOutputs is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x7970a189.
//
// Solidity: function namedOutputs() returns(string str1, string str2)
func (outputChecker *OutputChecker) UnpackNamedOutputs(data []byte) (NamedOutputsOutput, error) {
out, err := outputChecker.abi.Unpack("namedOutputs", data)
outstruct := new(NamedOutputsOutput)
if err != nil {
return *outstruct, err
}
outstruct.Str1 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Str2 = *abi.ConvertType(out[1], new(string)).(*string)
return *outstruct, nil
}
// PackNoOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x625f0306. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function noOutput() returns()
func (outputChecker *OutputChecker) PackNoOutput() []byte {
enc, err := outputChecker.abi.Pack("noOutput")
if err != nil {
panic(err)
}
return enc
}
// TryPackNoOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x625f0306. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function noOutput() returns()
func (outputChecker *OutputChecker) TryPackNoOutput() ([]byte, error) {
return outputChecker.abi.Pack("noOutput")
}

View file

@ -0,0 +1,179 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// OverloadMetaData contains all meta data concerning the Overload contract.
var OverloadMetaData = bind.MetaData{
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"},{\"name\":\"j\",\"type\":\"uint256\"}],\"name\":\"foo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"foo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"bar\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"i\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"j\",\"type\":\"uint256\"}],\"name\":\"bar\",\"type\":\"event\"}]",
ID: "f49f0ff7ed407de5c37214f49309072aec",
Bin: "0x608060405234801561001057600080fd5b50610153806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806304bc52f81461003b5780632fbebd3814610073575b600080fd5b6100716004803603604081101561005157600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b61009f6004803603602081101561008957600080fd5b81019080803590602001909291905050506100e4565b005b7fae42e9514233792a47a1e4554624e83fe852228e1503f63cd383e8a431f4f46d8282604051808381526020018281526020019250505060405180910390a15050565b7f0423a1321222a0a8716c22b92fac42d85a45a612b696a461784d9fa537c81e5c816040518082815260200191505060405180910390a15056fea265627a7a72305820e22b049858b33291cbe67eeaece0c5f64333e439d27032ea8337d08b1de18fe864736f6c634300050a0032",
}
// Overload is an auto generated Go binding around an Ethereum contract.
type Overload struct {
abi abi.ABI
}
// NewOverload creates a new instance of Overload.
func NewOverload() *Overload {
parsed, err := OverloadMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Overload{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Overload) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackFoo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x04bc52f8. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function foo(uint256 i, uint256 j) returns()
func (overload *Overload) PackFoo(i *big.Int, j *big.Int) []byte {
enc, err := overload.abi.Pack("foo", i, j)
if err != nil {
panic(err)
}
return enc
}
// TryPackFoo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x04bc52f8. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function foo(uint256 i, uint256 j) returns()
func (overload *Overload) TryPackFoo(i *big.Int, j *big.Int) ([]byte, error) {
return overload.abi.Pack("foo", i, j)
}
// PackFoo0 is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2fbebd38. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function foo(uint256 i) returns()
func (overload *Overload) PackFoo0(i *big.Int) []byte {
enc, err := overload.abi.Pack("foo0", i)
if err != nil {
panic(err)
}
return enc
}
// TryPackFoo0 is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2fbebd38. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function foo(uint256 i) returns()
func (overload *Overload) TryPackFoo0(i *big.Int) ([]byte, error) {
return overload.abi.Pack("foo0", i)
}
// OverloadBar represents a bar event raised by the Overload contract.
type OverloadBar struct {
I *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const OverloadBarEventName = "bar"
// ContractEventName returns the user-defined event name.
func (OverloadBar) ContractEventName() string {
return OverloadBarEventName
}
// UnpackBarEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event bar(uint256 i)
func (overload *Overload) UnpackBarEvent(log *types.Log) (*OverloadBar, error) {
event := "bar"
if len(log.Topics) == 0 || log.Topics[0] != overload.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(OverloadBar)
if len(log.Data) > 0 {
if err := overload.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range overload.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// OverloadBar0 represents a bar0 event raised by the Overload contract.
type OverloadBar0 struct {
I *big.Int
J *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const OverloadBar0EventName = "bar0"
// ContractEventName returns the user-defined event name.
func (OverloadBar0) ContractEventName() string {
return OverloadBar0EventName
}
// UnpackBar0Event is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event bar(uint256 i, uint256 j)
func (overload *Overload) UnpackBar0Event(log *types.Log) (*OverloadBar0, error) {
event := "bar0"
if len(log.Topics) == 0 || log.Topics[0] != overload.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(OverloadBar0)
if len(log.Data) > 0 {
if err := overload.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range overload.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

View file

@ -0,0 +1,74 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// RangeKeywordMetaData contains all meta data concerning the RangeKeyword contract.
var RangeKeywordMetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"range\",\"type\":\"uint256\"}],\"name\":\"functionWithKeywordParameter\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "cec8c872ba06feb1b8f0a00e7b237eb226",
Bin: "0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063527a119f14602d575b600080fd5b60436004803603810190603f9190605b565b6045565b005b50565b6000813590506055816092565b92915050565b600060208284031215606e57606d608d565b5b6000607a848285016048565b91505092915050565b6000819050919050565b600080fd5b6099816083565b811460a357600080fd5b5056fea2646970667358221220d4f4525e2615516394055d369fb17df41c359e5e962734f27fd683ea81fd9db164736f6c63430008070033",
}
// RangeKeyword is an auto generated Go binding around an Ethereum contract.
type RangeKeyword struct {
abi abi.ABI
}
// NewRangeKeyword creates a new instance of RangeKeyword.
func NewRangeKeyword() *RangeKeyword {
parsed, err := RangeKeywordMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &RangeKeyword{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *RangeKeyword) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackFunctionWithKeywordParameter is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x527a119f. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function functionWithKeywordParameter(uint256 range) pure returns()
func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int) []byte {
enc, err := rangeKeyword.abi.Pack("functionWithKeywordParameter", arg0)
if err != nil {
panic(err)
}
return enc
}
// TryPackFunctionWithKeywordParameter is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x527a119f. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function functionWithKeywordParameter(uint256 range) pure returns()
func (rangeKeyword *RangeKeyword) TryPackFunctionWithKeywordParameter(arg0 *big.Int) ([]byte, error) {
return rangeKeyword.abi.Pack("functionWithKeywordParameter", arg0)
}

View file

@ -0,0 +1,192 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// SlicerMetaData contains all meta data concerning the Slicer contract.
var SlicerMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"address[]\"}],\"name\":\"echoAddresses\",\"outputs\":[{\"name\":\"output\",\"type\":\"address[]\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"uint24[23]\"}],\"name\":\"echoFancyInts\",\"outputs\":[{\"name\":\"output\",\"type\":\"uint24[23]\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"int256[]\"}],\"name\":\"echoInts\",\"outputs\":[{\"name\":\"output\",\"type\":\"int256[]\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"bool[]\"}],\"name\":\"echoBools\",\"outputs\":[{\"name\":\"output\",\"type\":\"bool[]\"}],\"type\":\"function\"}]",
ID: "082c0740ab6537c7169cb573d097c52112",
Bin: "0x606060405261015c806100126000396000f3606060405260e060020a6000350463be1127a3811461003c578063d88becc014610092578063e15a3db71461003c578063f637e5891461003c575b005b604080516020600480358082013583810285810185019096528085526100ee959294602494909392850192829185019084908082843750949650505050505050604080516020810190915260009052805b919050565b604080516102e0818101909252610138916004916102e491839060179083908390808284375090955050505050506102e0604051908101604052806017905b60008152602001906001900390816100d15790505081905061008d565b60405180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600f02600301f1509050019250505060405180910390f35b60405180826102e0808381846000600461015cf15090500191505060405180910390f3",
}
// Slicer is an auto generated Go binding around an Ethereum contract.
type Slicer struct {
abi abi.ABI
}
// NewSlicer creates a new instance of Slicer.
func NewSlicer() *Slicer {
parsed, err := SlicerMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Slicer{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Slicer) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackEchoAddresses is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbe1127a3. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function echoAddresses(address[] input) returns(address[] output)
func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte {
enc, err := slicer.abi.Pack("echoAddresses", input)
if err != nil {
panic(err)
}
return enc
}
// TryPackEchoAddresses is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbe1127a3. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function echoAddresses(address[] input) returns(address[] output)
func (slicer *Slicer) TryPackEchoAddresses(input []common.Address) ([]byte, error) {
return slicer.abi.Pack("echoAddresses", input)
}
// UnpackEchoAddresses is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xbe1127a3.
//
// Solidity: function echoAddresses(address[] input) returns(address[] output)
func (slicer *Slicer) UnpackEchoAddresses(data []byte) ([]common.Address, error) {
out, err := slicer.abi.Unpack("echoAddresses", data)
if err != nil {
return *new([]common.Address), err
}
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address)
return out0, nil
}
// PackEchoBools is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xf637e589. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function echoBools(bool[] input) returns(bool[] output)
func (slicer *Slicer) PackEchoBools(input []bool) []byte {
enc, err := slicer.abi.Pack("echoBools", input)
if err != nil {
panic(err)
}
return enc
}
// TryPackEchoBools is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xf637e589. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function echoBools(bool[] input) returns(bool[] output)
func (slicer *Slicer) TryPackEchoBools(input []bool) ([]byte, error) {
return slicer.abi.Pack("echoBools", input)
}
// UnpackEchoBools is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xf637e589.
//
// Solidity: function echoBools(bool[] input) returns(bool[] output)
func (slicer *Slicer) UnpackEchoBools(data []byte) ([]bool, error) {
out, err := slicer.abi.Unpack("echoBools", data)
if err != nil {
return *new([]bool), err
}
out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool)
return out0, nil
}
// PackEchoFancyInts is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd88becc0. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output)
func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte {
enc, err := slicer.abi.Pack("echoFancyInts", input)
if err != nil {
panic(err)
}
return enc
}
// TryPackEchoFancyInts is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xd88becc0. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output)
func (slicer *Slicer) TryPackEchoFancyInts(input [23]*big.Int) ([]byte, error) {
return slicer.abi.Pack("echoFancyInts", input)
}
// UnpackEchoFancyInts is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xd88becc0.
//
// Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output)
func (slicer *Slicer) UnpackEchoFancyInts(data []byte) ([23]*big.Int, error) {
out, err := slicer.abi.Unpack("echoFancyInts", data)
if err != nil {
return *new([23]*big.Int), err
}
out0 := *abi.ConvertType(out[0], new([23]*big.Int)).(*[23]*big.Int)
return out0, nil
}
// PackEchoInts is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe15a3db7. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function echoInts(int256[] input) returns(int256[] output)
func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte {
enc, err := slicer.abi.Pack("echoInts", input)
if err != nil {
panic(err)
}
return enc
}
// TryPackEchoInts is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe15a3db7. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function echoInts(int256[] input) returns(int256[] output)
func (slicer *Slicer) TryPackEchoInts(input []*big.Int) ([]byte, error) {
return slicer.abi.Pack("echoInts", input)
}
// UnpackEchoInts is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xe15a3db7.
//
// Solidity: function echoInts(int256[] input) returns(int256[] output)
func (slicer *Slicer) UnpackEchoInts(data []byte) ([]*big.Int, error) {
out, err := slicer.abi.Unpack("echoInts", data)
if err != nil {
return *new([]*big.Int), err
}
out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int)
return out0, nil
}

View file

@ -0,0 +1,138 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// Struct0 is an auto generated low-level Go binding around an user-defined struct.
type Struct0 struct {
B [32]byte
}
// StructsMetaData contains all meta data concerning the Structs contract.
var StructsMetaData = bind.MetaData{
ABI: "[{\"inputs\":[],\"name\":\"F\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[]\",\"name\":\"c\",\"type\":\"uint256[]\"},{\"internalType\":\"bool[]\",\"name\":\"d\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"G\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
ID: "920a35318e7581766aec7a17218628a91d",
Bin: "0x608060405234801561001057600080fd5b50610278806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806328811f591461003b5780636fecb6231461005b575b600080fd5b610043610070565b604051610052939291906101a0565b60405180910390f35b6100636100d6565b6040516100529190610186565b604080516002808252606082810190935282918291829190816020015b610095610131565b81526020019060019003908161008d575050805190915061026960611b9082906000906100be57fe5b60209081029190910101515293606093508392509050565b6040805160028082526060828101909352829190816020015b6100f7610131565b8152602001906001900390816100ef575050805190915061026960611b90829060009061012057fe5b602090810291909101015152905090565b60408051602081019091526000815290565b815260200190565b6000815180845260208085019450808401835b8381101561017b578151518752958201959082019060010161015e565b509495945050505050565b600060208252610199602083018461014b565b9392505050565b6000606082526101b3606083018661014b565b6020838203818501528186516101c98185610239565b91508288019350845b818110156101f3576101e5838651610143565b9484019492506001016101d2565b505084810360408601528551808252908201925081860190845b8181101561022b57825115158552938301939183019160010161020d565b509298975050505050505050565b9081526020019056fea2646970667358221220eb85327e285def14230424c52893aebecec1e387a50bb6b75fc4fdbed647f45f64736f6c63430006050033",
}
// Structs is an auto generated Go binding around an Ethereum contract.
type Structs struct {
abi abi.ABI
}
// NewStructs creates a new instance of Structs.
func NewStructs() *Structs {
parsed, err := StructsMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Structs{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackF is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x28811f59. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
func (structs *Structs) PackF() []byte {
enc, err := structs.abi.Pack("F")
if err != nil {
panic(err)
}
return enc
}
// TryPackF is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x28811f59. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
func (structs *Structs) TryPackF() ([]byte, error) {
return structs.abi.Pack("F")
}
// FOutput serves as a container for the return parameters of contract
// method F.
type FOutput struct {
A []Struct0
C []*big.Int
D []bool
}
// UnpackF is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x28811f59.
//
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
func (structs *Structs) UnpackF(data []byte) (FOutput, error) {
out, err := structs.abi.Unpack("F", data)
outstruct := new(FOutput)
if err != nil {
return *outstruct, err
}
outstruct.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
outstruct.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int)
outstruct.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool)
return *outstruct, nil
}
// PackG is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6fecb623. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function G() view returns((bytes32)[] a)
func (structs *Structs) PackG() []byte {
enc, err := structs.abi.Pack("G")
if err != nil {
panic(err)
}
return enc
}
// TryPackG is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6fecb623. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function G() view returns((bytes32)[] a)
func (structs *Structs) TryPackG() ([]byte, error) {
return structs.abi.Pack("G")
}
// UnpackG is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6fecb623.
//
// Solidity: function G() view returns((bytes32)[] a)
func (structs *Structs) UnpackG(data []byte) ([]Struct0, error) {
out, err := structs.abi.Unpack("G", data)
if err != nil {
return *new([]Struct0), err
}
out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
return out0, nil
}

View file

@ -0,0 +1,409 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// TokenMetaData contains all meta data concerning the Token contract.
var TokenMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"spentAllowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"name\":\"tokenName\",\"type\":\"string\"},{\"name\":\"decimalUnits\",\"type\":\"uint8\"},{\"name\":\"tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"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\"}]",
ID: "1317f51c845ce3bfb7c268e5337a825f12",
Bin: "0x60606040526040516107fd3803806107fd83398101604052805160805160a05160c051929391820192909101600160a060020a0333166000908152600360209081526040822086905581548551838052601f6002600019610100600186161502019093169290920482018390047f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56390810193919290918801908390106100e857805160ff19168380011785555b506101189291505b8082111561017157600081556001016100b4565b50506002805460ff19168317905550505050610658806101a56000396000f35b828001600101855582156100ac579182015b828111156100ac5782518260005055916020019190600101906100fa565b50508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017557805160ff19168380011785555b506100c89291506100b4565b5090565b82800160010185558215610165579182015b8281111561016557825182600050559160200191906001019061018756606060405236156100775760e060020a600035046306fdde03811461007f57806323b872dd146100dc578063313ce5671461010e57806370a082311461011a57806395d89b4114610132578063a9059cbb1461018e578063cae9ca51146101bd578063dc3080f21461031c578063dd62ed3e14610341575b610365610002565b61036760008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b6103d5600435602435604435600160a060020a038316600090815260036020526040812054829010156104f357610002565b6103e760025460ff1681565b6103d560043560036020526000908152604090205481565b610367600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b610365600435602435600160a060020a033316600090815260036020526040902054819010156103f157610002565b60806020604435600481810135601f8101849004909302840160405260608381526103d5948235946024803595606494939101919081908382808284375094965050505050505060006000836004600050600033600160a060020a03168152602001908152602001600020600050600087600160a060020a031681526020019081526020016000206000508190555084905080600160a060020a0316638f4ffcb1338630876040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156102f25780820380516001836020036101000a031916815260200191505b50955050505050506000604051808303816000876161da5a03f11561000257505050509392505050565b6005602090815260043560009081526040808220909252602435815220546103d59081565b60046020818152903560009081526040808220909252602435815220546103d59081565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a03821660009081526040902054808201101561041357610002565b806003600050600033600160a060020a03168152602001908152602001600020600082828250540392505081905550806003600050600084600160a060020a0316815260200190815260200160002060008282825054019250508190555081600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b820191906000526020600020905b8154815290600101906020018083116104ce57829003601f168201915b505050505081565b600160a060020a03831681526040812054808301101561051257610002565b600160a060020a0380851680835260046020908152604080852033949094168086529382528085205492855260058252808520938552929052908220548301111561055c57610002565b816003600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816003600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816005600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054019250508190555082600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3939250505056",
}
// Token is an auto generated Go binding around an Ethereum contract.
type Token struct {
abi abi.ABI
}
// NewToken creates a new instance of Token.
func NewToken() *Token {
parsed, err := TokenMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Token{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Token) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackConstructor is the Go binding used to pack the parameters required for
// contract deployment.
//
// Solidity: constructor(uint256 initialSupply, string tokenName, uint8 decimalUnits, string tokenSymbol) returns()
func (token *Token) PackConstructor(initialSupply *big.Int, tokenName string, decimalUnits uint8, tokenSymbol string) []byte {
enc, err := token.abi.Pack("", initialSupply, tokenName, decimalUnits, tokenSymbol)
if err != nil {
panic(err)
}
return enc
}
// PackAllowance is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xdd62ed3e. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function allowance(address , address ) returns(uint256)
func (token *Token) PackAllowance(arg0 common.Address, arg1 common.Address) []byte {
enc, err := token.abi.Pack("allowance", arg0, arg1)
if err != nil {
panic(err)
}
return enc
}
// TryPackAllowance is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xdd62ed3e. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function allowance(address , address ) returns(uint256)
func (token *Token) TryPackAllowance(arg0 common.Address, arg1 common.Address) ([]byte, error) {
return token.abi.Pack("allowance", arg0, arg1)
}
// UnpackAllowance is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xdd62ed3e.
//
// Solidity: function allowance(address , address ) returns(uint256)
func (token *Token) UnpackAllowance(data []byte) (*big.Int, error) {
out, err := token.abi.Unpack("allowance", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackApproveAndCall is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xcae9ca51. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success)
func (token *Token) PackApproveAndCall(spender common.Address, value *big.Int, extraData []byte) []byte {
enc, err := token.abi.Pack("approveAndCall", spender, value, extraData)
if err != nil {
panic(err)
}
return enc
}
// TryPackApproveAndCall is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xcae9ca51. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success)
func (token *Token) TryPackApproveAndCall(spender common.Address, value *big.Int, extraData []byte) ([]byte, error) {
return token.abi.Pack("approveAndCall", spender, value, extraData)
}
// UnpackApproveAndCall is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xcae9ca51.
//
// Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success)
func (token *Token) UnpackApproveAndCall(data []byte) (bool, error) {
out, err := token.abi.Unpack("approveAndCall", data)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, nil
}
// PackBalanceOf is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x70a08231. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function balanceOf(address ) returns(uint256)
func (token *Token) PackBalanceOf(arg0 common.Address) []byte {
enc, err := token.abi.Pack("balanceOf", arg0)
if err != nil {
panic(err)
}
return enc
}
// TryPackBalanceOf is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x70a08231. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function balanceOf(address ) returns(uint256)
func (token *Token) TryPackBalanceOf(arg0 common.Address) ([]byte, error) {
return token.abi.Pack("balanceOf", arg0)
}
// UnpackBalanceOf is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x70a08231.
//
// Solidity: function balanceOf(address ) returns(uint256)
func (token *Token) UnpackBalanceOf(data []byte) (*big.Int, error) {
out, err := token.abi.Unpack("balanceOf", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackDecimals is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x313ce567. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function decimals() returns(uint8)
func (token *Token) PackDecimals() []byte {
enc, err := token.abi.Pack("decimals")
if err != nil {
panic(err)
}
return enc
}
// TryPackDecimals is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x313ce567. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function decimals() returns(uint8)
func (token *Token) TryPackDecimals() ([]byte, error) {
return token.abi.Pack("decimals")
}
// UnpackDecimals is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x313ce567.
//
// Solidity: function decimals() returns(uint8)
func (token *Token) UnpackDecimals(data []byte) (uint8, error) {
out, err := token.abi.Unpack("decimals", data)
if err != nil {
return *new(uint8), err
}
out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
return out0, nil
}
// PackName is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x06fdde03. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function name() returns(string)
func (token *Token) PackName() []byte {
enc, err := token.abi.Pack("name")
if err != nil {
panic(err)
}
return enc
}
// TryPackName is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x06fdde03. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function name() returns(string)
func (token *Token) TryPackName() ([]byte, error) {
return token.abi.Pack("name")
}
// UnpackName is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x06fdde03.
//
// Solidity: function name() returns(string)
func (token *Token) UnpackName(data []byte) (string, error) {
out, err := token.abi.Unpack("name", data)
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, nil
}
// PackSpentAllowance is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xdc3080f2. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function spentAllowance(address , address ) returns(uint256)
func (token *Token) PackSpentAllowance(arg0 common.Address, arg1 common.Address) []byte {
enc, err := token.abi.Pack("spentAllowance", arg0, arg1)
if err != nil {
panic(err)
}
return enc
}
// TryPackSpentAllowance is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xdc3080f2. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function spentAllowance(address , address ) returns(uint256)
func (token *Token) TryPackSpentAllowance(arg0 common.Address, arg1 common.Address) ([]byte, error) {
return token.abi.Pack("spentAllowance", arg0, arg1)
}
// UnpackSpentAllowance is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xdc3080f2.
//
// Solidity: function spentAllowance(address , address ) returns(uint256)
func (token *Token) UnpackSpentAllowance(data []byte) (*big.Int, error) {
out, err := token.abi.Unpack("spentAllowance", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackSymbol is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x95d89b41. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function symbol() returns(string)
func (token *Token) PackSymbol() []byte {
enc, err := token.abi.Pack("symbol")
if err != nil {
panic(err)
}
return enc
}
// TryPackSymbol is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x95d89b41. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function symbol() returns(string)
func (token *Token) TryPackSymbol() ([]byte, error) {
return token.abi.Pack("symbol")
}
// UnpackSymbol is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x95d89b41.
//
// Solidity: function symbol() returns(string)
func (token *Token) UnpackSymbol(data []byte) (string, error) {
out, err := token.abi.Unpack("symbol", data)
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, nil
}
// PackTransfer is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xa9059cbb. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function transfer(address _to, uint256 _value) returns()
func (token *Token) PackTransfer(to common.Address, value *big.Int) []byte {
enc, err := token.abi.Pack("transfer", to, value)
if err != nil {
panic(err)
}
return enc
}
// TryPackTransfer is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xa9059cbb. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function transfer(address _to, uint256 _value) returns()
func (token *Token) TryPackTransfer(to common.Address, value *big.Int) ([]byte, error) {
return token.abi.Pack("transfer", to, value)
}
// PackTransferFrom is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x23b872dd. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success)
func (token *Token) PackTransferFrom(from common.Address, to common.Address, value *big.Int) []byte {
enc, err := token.abi.Pack("transferFrom", from, to, value)
if err != nil {
panic(err)
}
return enc
}
// TryPackTransferFrom is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x23b872dd. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success)
func (token *Token) TryPackTransferFrom(from common.Address, to common.Address, value *big.Int) ([]byte, error) {
return token.abi.Pack("transferFrom", from, to, value)
}
// UnpackTransferFrom is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x23b872dd.
//
// Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success)
func (token *Token) UnpackTransferFrom(data []byte) (bool, error) {
out, err := token.abi.Unpack("transferFrom", data)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, nil
}
// TokenTransfer represents a Transfer event raised by the Token contract.
type TokenTransfer struct {
From common.Address
To common.Address
Value *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const TokenTransferEventName = "Transfer"
// ContractEventName returns the user-defined event name.
func (TokenTransfer) ContractEventName() string {
return TokenTransferEventName
}
// UnpackTransferEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
func (token *Token) UnpackTransferEvent(log *types.Log) (*TokenTransfer, error) {
event := "Transfer"
if len(log.Topics) == 0 || log.Topics[0] != token.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(TokenTransfer)
if len(log.Data) > 0 {
if err := token.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range token.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,98 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// TuplerMetaData contains all meta data concerning the Tupler contract.
var TuplerMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"tuple\",\"outputs\":[{\"name\":\"a\",\"type\":\"string\"},{\"name\":\"b\",\"type\":\"int256\"},{\"name\":\"c\",\"type\":\"bytes32\"}],\"type\":\"function\"}]",
ID: "a8f4d2061f55c712cfae266c426a1cd568",
Bin: "0x606060405260dc8060106000396000f3606060405260e060020a60003504633175aae28114601a575b005b600060605260c0604052600260809081527f486900000000000000000000000000000000000000000000000000000000000060a05260017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060e0829052610100819052606060c0908152600261012081905281906101409060a09080838184600060046012f1505081517fffff000000000000000000000000000000000000000000000000000000000000169091525050604051610160819003945092505050f3",
}
// Tupler is an auto generated Go binding around an Ethereum contract.
type Tupler struct {
abi abi.ABI
}
// NewTupler creates a new instance of Tupler.
func NewTupler() *Tupler {
parsed, err := TuplerMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Tupler{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Tupler) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackTuple is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x3175aae2. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function tuple() returns(string a, int256 b, bytes32 c)
func (tupler *Tupler) PackTuple() []byte {
enc, err := tupler.abi.Pack("tuple")
if err != nil {
panic(err)
}
return enc
}
// TryPackTuple is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x3175aae2. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function tuple() returns(string a, int256 b, bytes32 c)
func (tupler *Tupler) TryPackTuple() ([]byte, error) {
return tupler.abi.Pack("tuple")
}
// TupleOutput serves as a container for the return parameters of contract
// method Tuple.
type TupleOutput struct {
A string
B *big.Int
C [32]byte
}
// UnpackTuple is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x3175aae2.
//
// Solidity: function tuple() returns(string a, int256 b, bytes32 c)
func (tupler *Tupler) UnpackTuple(data []byte) (TupleOutput, error) {
out, err := tupler.abi.Unpack("tuple", data)
outstruct := new(TupleOutput)
if err != nil {
return *outstruct, err
}
outstruct.A = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.B = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
outstruct.C = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
return *outstruct, nil
}

View file

@ -0,0 +1,395 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindtests
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// UnderscorerMetaData contains all meta data concerning the Underscorer contract.
var UnderscorerMetaData = bind.MetaData{
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"LowerUpperCollision\",\"outputs\":[{\"name\":\"_res\",\"type\":\"int256\"},{\"name\":\"Res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_under_scored_func\",\"outputs\":[{\"name\":\"_int\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"UnderscoredOutput\",\"outputs\":[{\"name\":\"_int\",\"type\":\"int256\"},{\"name\":\"_string\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PurelyUnderscoredOutput\",\"outputs\":[{\"name\":\"_\",\"type\":\"int256\"},{\"name\":\"res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"UpperLowerCollision\",\"outputs\":[{\"name\":\"_Res\",\"type\":\"int256\"},{\"name\":\"res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"AllPurelyUnderscoredOutput\",\"outputs\":[{\"name\":\"_\",\"type\":\"int256\"},{\"name\":\"__\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"UpperUpperCollision\",\"outputs\":[{\"name\":\"_Res\",\"type\":\"int256\"},{\"name\":\"Res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LowerLowerCollision\",\"outputs\":[{\"name\":\"_res\",\"type\":\"int256\"},{\"name\":\"res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
ID: "5873a90ab43c925dfced86ad53f871f01d",
Bin: "0x6060604052341561000f57600080fd5b6103858061001e6000396000f30060606040526004361061008e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303a592131461009357806346546dbe146100c357806367e6633d146100ec5780639df4848514610181578063af7486ab146101b1578063b564b34d146101e1578063e02ab24d14610211578063e409ca4514610241575b600080fd5b341561009e57600080fd5b6100a6610271565b604051808381526020018281526020019250505060405180910390f35b34156100ce57600080fd5b6100d6610286565b6040518082815260200191505060405180910390f35b34156100f757600080fd5b6100ff61028e565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561014557808201518184015260208101905061012a565b50505050905090810190601f1680156101725780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561018c57600080fd5b6101946102dc565b604051808381526020018281526020019250505060405180910390f35b34156101bc57600080fd5b6101c46102f1565b604051808381526020018281526020019250505060405180910390f35b34156101ec57600080fd5b6101f4610306565b604051808381526020018281526020019250505060405180910390f35b341561021c57600080fd5b61022461031b565b604051808381526020018281526020019250505060405180910390f35b341561024c57600080fd5b610254610330565b604051808381526020018281526020019250505060405180910390f35b60008060016002819150809050915091509091565b600080905090565b6000610298610345565b61013a8090506040805190810160405280600281526020017f7069000000000000000000000000000000000000000000000000000000000000815250915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b6020604051908101604052806000815250905600a165627a7a72305820d1a53d9de9d1e3d55cb3dc591900b63c4f1ded79114f7b79b332684840e186a40029",
}
// Underscorer is an auto generated Go binding around an Ethereum contract.
type Underscorer struct {
abi abi.ABI
}
// NewUnderscorer creates a new instance of Underscorer.
func NewUnderscorer() *Underscorer {
parsed, err := UnderscorerMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &Underscorer{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *Underscorer) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackAllPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xb564b34d. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __)
func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte {
enc, err := underscorer.abi.Pack("AllPurelyUnderscoredOutput")
if err != nil {
panic(err)
}
return enc
}
// TryPackAllPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xb564b34d. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __)
func (underscorer *Underscorer) TryPackAllPurelyUnderscoredOutput() ([]byte, error) {
return underscorer.abi.Pack("AllPurelyUnderscoredOutput")
}
// AllPurelyUnderscoredOutputOutput serves as a container for the return parameters of contract
// method AllPurelyUnderscoredOutput.
type AllPurelyUnderscoredOutputOutput struct {
Arg0 *big.Int
Arg1 *big.Int
}
// UnpackAllPurelyUnderscoredOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xb564b34d.
//
// Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __)
func (underscorer *Underscorer) UnpackAllPurelyUnderscoredOutput(data []byte) (AllPurelyUnderscoredOutputOutput, error) {
out, err := underscorer.abi.Unpack("AllPurelyUnderscoredOutput", data)
outstruct := new(AllPurelyUnderscoredOutputOutput)
if err != nil {
return *outstruct, err
}
outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackLowerLowerCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe409ca45. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res)
func (underscorer *Underscorer) PackLowerLowerCollision() []byte {
enc, err := underscorer.abi.Pack("LowerLowerCollision")
if err != nil {
panic(err)
}
return enc
}
// TryPackLowerLowerCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe409ca45. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res)
func (underscorer *Underscorer) TryPackLowerLowerCollision() ([]byte, error) {
return underscorer.abi.Pack("LowerLowerCollision")
}
// LowerLowerCollisionOutput serves as a container for the return parameters of contract
// method LowerLowerCollision.
type LowerLowerCollisionOutput struct {
Res *big.Int
Res0 *big.Int
}
// UnpackLowerLowerCollision is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xe409ca45.
//
// Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res)
func (underscorer *Underscorer) UnpackLowerLowerCollision(data []byte) (LowerLowerCollisionOutput, error) {
out, err := underscorer.abi.Unpack("LowerLowerCollision", data)
outstruct := new(LowerLowerCollisionOutput)
if err != nil {
return *outstruct, err
}
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackLowerUpperCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x03a59213. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res)
func (underscorer *Underscorer) PackLowerUpperCollision() []byte {
enc, err := underscorer.abi.Pack("LowerUpperCollision")
if err != nil {
panic(err)
}
return enc
}
// TryPackLowerUpperCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x03a59213. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res)
func (underscorer *Underscorer) TryPackLowerUpperCollision() ([]byte, error) {
return underscorer.abi.Pack("LowerUpperCollision")
}
// LowerUpperCollisionOutput serves as a container for the return parameters of contract
// method LowerUpperCollision.
type LowerUpperCollisionOutput struct {
Res *big.Int
Res0 *big.Int
}
// UnpackLowerUpperCollision is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x03a59213.
//
// Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res)
func (underscorer *Underscorer) UnpackLowerUpperCollision(data []byte) (LowerUpperCollisionOutput, error) {
out, err := underscorer.abi.Unpack("LowerUpperCollision", data)
outstruct := new(LowerUpperCollisionOutput)
if err != nil {
return *outstruct, err
}
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x9df48485. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res)
func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte {
enc, err := underscorer.abi.Pack("PurelyUnderscoredOutput")
if err != nil {
panic(err)
}
return enc
}
// TryPackPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x9df48485. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res)
func (underscorer *Underscorer) TryPackPurelyUnderscoredOutput() ([]byte, error) {
return underscorer.abi.Pack("PurelyUnderscoredOutput")
}
// PurelyUnderscoredOutputOutput serves as a container for the return parameters of contract
// method PurelyUnderscoredOutput.
type PurelyUnderscoredOutputOutput struct {
Arg0 *big.Int
Res *big.Int
}
// UnpackPurelyUnderscoredOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x9df48485.
//
// Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res)
func (underscorer *Underscorer) UnpackPurelyUnderscoredOutput(data []byte) (PurelyUnderscoredOutputOutput, error) {
out, err := underscorer.abi.Unpack("PurelyUnderscoredOutput", data)
outstruct := new(PurelyUnderscoredOutputOutput)
if err != nil {
return *outstruct, err
}
outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackUnderscoredOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x67e6633d. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function UnderscoredOutput() view returns(int256 _int, string _string)
func (underscorer *Underscorer) PackUnderscoredOutput() []byte {
enc, err := underscorer.abi.Pack("UnderscoredOutput")
if err != nil {
panic(err)
}
return enc
}
// TryPackUnderscoredOutput is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x67e6633d. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function UnderscoredOutput() view returns(int256 _int, string _string)
func (underscorer *Underscorer) TryPackUnderscoredOutput() ([]byte, error) {
return underscorer.abi.Pack("UnderscoredOutput")
}
// UnderscoredOutputOutput serves as a container for the return parameters of contract
// method UnderscoredOutput.
type UnderscoredOutputOutput struct {
Int *big.Int
String string
}
// UnpackUnderscoredOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x67e6633d.
//
// Solidity: function UnderscoredOutput() view returns(int256 _int, string _string)
func (underscorer *Underscorer) UnpackUnderscoredOutput(data []byte) (UnderscoredOutputOutput, error) {
out, err := underscorer.abi.Unpack("UnderscoredOutput", data)
outstruct := new(UnderscoredOutputOutput)
if err != nil {
return *outstruct, err
}
outstruct.Int = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.String = *abi.ConvertType(out[1], new(string)).(*string)
return *outstruct, nil
}
// PackUpperLowerCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xaf7486ab. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res)
func (underscorer *Underscorer) PackUpperLowerCollision() []byte {
enc, err := underscorer.abi.Pack("UpperLowerCollision")
if err != nil {
panic(err)
}
return enc
}
// TryPackUpperLowerCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xaf7486ab. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res)
func (underscorer *Underscorer) TryPackUpperLowerCollision() ([]byte, error) {
return underscorer.abi.Pack("UpperLowerCollision")
}
// UpperLowerCollisionOutput serves as a container for the return parameters of contract
// method UpperLowerCollision.
type UpperLowerCollisionOutput struct {
Res *big.Int
Res0 *big.Int
}
// UnpackUpperLowerCollision is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xaf7486ab.
//
// Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res)
func (underscorer *Underscorer) UnpackUpperLowerCollision(data []byte) (UpperLowerCollisionOutput, error) {
out, err := underscorer.abi.Unpack("UpperLowerCollision", data)
outstruct := new(UpperLowerCollisionOutput)
if err != nil {
return *outstruct, err
}
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackUpperUpperCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe02ab24d. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res)
func (underscorer *Underscorer) PackUpperUpperCollision() []byte {
enc, err := underscorer.abi.Pack("UpperUpperCollision")
if err != nil {
panic(err)
}
return enc
}
// TryPackUpperUpperCollision is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe02ab24d. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res)
func (underscorer *Underscorer) TryPackUpperUpperCollision() ([]byte, error) {
return underscorer.abi.Pack("UpperUpperCollision")
}
// UpperUpperCollisionOutput serves as a container for the return parameters of contract
// method UpperUpperCollision.
type UpperUpperCollisionOutput struct {
Res *big.Int
Res0 *big.Int
}
// UnpackUpperUpperCollision is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xe02ab24d.
//
// Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res)
func (underscorer *Underscorer) UnpackUpperUpperCollision(data []byte) (UpperUpperCollisionOutput, error) {
out, err := underscorer.abi.Unpack("UpperUpperCollision", data)
outstruct := new(UpperUpperCollisionOutput)
if err != nil {
return *outstruct, err
}
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackUnderScoredFunc is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x46546dbe. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function _under_scored_func() view returns(int256 _int)
func (underscorer *Underscorer) PackUnderScoredFunc() []byte {
enc, err := underscorer.abi.Pack("_under_scored_func")
if err != nil {
panic(err)
}
return enc
}
// TryPackUnderScoredFunc is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x46546dbe. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function _under_scored_func() view returns(int256 _int)
func (underscorer *Underscorer) TryPackUnderScoredFunc() ([]byte, error) {
return underscorer.abi.Pack("_under_scored_func")
}
// UnpackUnderScoredFunc is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x46546dbe.
//
// Solidity: function _under_scored_func() view returns(int256 _int)
func (underscorer *Underscorer) UnpackUnderScoredFunc(data []byte) (*big.Int, error) {
out, err := underscorer.abi.Unpack("_under_scored_func", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}

View file

@ -18,6 +18,7 @@ package abi
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
@ -76,31 +77,25 @@ func (arguments Arguments) isTuple() bool {
}
// Unpack performs the operation hexdata -> Go format.
func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
func (arguments Arguments) Unpack(data []byte) ([]any, error) {
if len(data) == 0 {
if len(arguments) != 0 {
return nil, fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
if len(arguments.NonIndexed()) != 0 {
return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
// Nothing to unmarshal, return default variables
nonIndexedArgs := arguments.NonIndexed()
defaultVars := make([]interface{}, len(nonIndexedArgs))
for index, arg := range nonIndexedArgs {
defaultVars[index] = reflect.New(arg.Type.GetType())
}
return defaultVars, nil
return make([]any, 0), nil
}
return arguments.UnpackValues(data)
}
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value.
func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
func (arguments Arguments) UnpackIntoMap(v map[string]any, data []byte) error {
// Make sure map is not nil
if v == nil {
return fmt.Errorf("abi: cannot unpack into a nil map")
return errors.New("abi: cannot unpack into a nil map")
}
if len(data) == 0 {
if len(arguments) != 0 {
return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
if len(arguments.NonIndexed()) != 0 {
return errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return nil // Nothing to unmarshal, return
}
@ -115,14 +110,14 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
}
// Copy performs the operation go format -> provided struct.
func (arguments Arguments) Copy(v interface{}, values []interface{}) error {
func (arguments Arguments) Copy(v any, values []any) error {
// make sure the passed value is arguments pointer
if reflect.Ptr != reflect.ValueOf(v).Kind() {
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
}
if len(values) == 0 {
if len(arguments) != 0 {
return fmt.Errorf("abi: attempting to copy no values while %d arguments are expected", len(arguments))
if len(arguments.NonIndexed()) != 0 {
return errors.New("abi: attempting to copy no values while arguments are expected")
}
return nil // Nothing to copy, return
}
@ -132,19 +127,19 @@ func (arguments Arguments) Copy(v interface{}, values []interface{}) error {
return arguments.copyAtomic(v, values[0])
}
// unpackAtomic unpacks ( hexdata -> go ) a single value
func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{}) error {
// copyAtomic copies ( hexdata -> go ) a single value
func (arguments Arguments) copyAtomic(v any, marshalledValues any) error {
dst := reflect.ValueOf(v).Elem()
src := reflect.ValueOf(marshalledValues)
if dst.Kind() == reflect.Struct && src.Kind() != reflect.Struct {
if dst.Kind() == reflect.Struct {
return set(dst.Field(0), src)
}
return set(dst, src)
}
// copyTuple copies a batch of values from marshalledValues to v.
func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface{}) error {
func (arguments Arguments) copyTuple(v any, marshalledValues []any) error {
value := reflect.ValueOf(v).Elem()
nonIndexedArgs := arguments.NonIndexed()
@ -186,12 +181,21 @@ func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
// without supplying a struct to unpack into. Instead, this method returns a list containing the
// values. An atomic argument will be a list with one element.
func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
nonIndexedArgs := arguments.NonIndexed()
retval := make([]interface{}, 0, len(nonIndexedArgs))
virtualArgs := 0
for index, arg := range nonIndexedArgs {
func (arguments Arguments) UnpackValues(data []byte) ([]any, error) {
var (
retval = make([]any, 0)
virtualArgs = 0
index = 0
)
for _, arg := range arguments {
if arg.Indexed {
continue
}
marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
if err != nil {
return nil, err
}
if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
// If we have a static array, like [3]uint256, these are coded as
// just like uint256,uint256,uint256.
@ -209,22 +213,20 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
// coded as just like uint256,bool,uint256
virtualArgs += getTypeSize(arg.Type)/32 - 1
}
if err != nil {
return nil, err
}
retval = append(retval, marshalledValue)
index++
}
return retval, nil
}
// PackValues performs the operation Go format -> Hexdata.
// It is the semantic opposite of UnpackValues.
func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
func (arguments Arguments) PackValues(args []any) ([]byte, error) {
return arguments.Pack(args...)
}
// Pack performs the operation Go format -> Hexdata.
func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
func (arguments Arguments) Pack(args ...any) ([]byte, error) {
// Make sure arguments match up and pack them
abiArgs := arguments
if len(args) != len(abiArgs) {

View file

@ -1,174 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind
import (
"crypto/ecdsa"
"errors"
"io"
"io/ioutil"
"math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)
// ErrNoChainID is returned whenever the user failed to specify a chain id.
var ErrNoChainID = errors.New("no chain id specified")
// ErrNotAuthorized is returned when an account is not properly unlocked.
var ErrNotAuthorized = errors.New("not authorized to sign this account")
// NewTransactor is a utility method to easily create a transaction signer from
// an encrypted json key stream and the associated passphrase.
//
// Deprecated: Use NewTransactorWithChainID instead.
func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
log.Warn("WARNING: NewTransactor has been deprecated in favour of NewTransactorWithChainID")
json, err := ioutil.ReadAll(keyin)
if err != nil {
return nil, err
}
key, err := keystore.DecryptKey(json, passphrase)
if err != nil {
return nil, err
}
return NewKeyedTransactor(key.PrivateKey), nil
}
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
// an decrypted key from a keystore.
//
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
log.Warn("WARNING: NewKeyStoreTransactor has been deprecated in favour of NewTransactorWithChainID")
signer := types.HomesteadSigner{}
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != account.Address {
return nil, ErrNotAuthorized
}
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
}, nil
}
// NewKeyedTransactor is a utility method to easily create a transaction signer
// from a single private key.
//
// Deprecated: Use NewKeyedTransactorWithChainID instead.
func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
log.Warn("WARNING: NewKeyedTransactor has been deprecated in favour of NewKeyedTransactorWithChainID")
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
signer := types.HomesteadSigner{}
return &TransactOpts{
From: keyAddr,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != keyAddr {
return nil, ErrNotAuthorized
}
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
}
}
// NewTransactorWithChainID is a utility method to easily create a transaction signer from
// an encrypted json key stream and the associated passphrase.
func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.Int) (*TransactOpts, error) {
json, err := ioutil.ReadAll(keyin)
if err != nil {
return nil, err
}
key, err := keystore.DecryptKey(json, passphrase)
if err != nil {
return nil, err
}
return NewKeyedTransactorWithChainID(key.PrivateKey, chainID)
}
// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
// an decrypted key from a keystore.
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
if chainID == nil {
return nil, ErrNoChainID
}
signer := types.NewEIP155Signer(chainID)
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != account.Address {
return nil, ErrNotAuthorized
}
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
}, nil
}
// NewKeyedTransactorWithChainID is a utility method to easily create a transaction signer
// from a single private key.
func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*TransactOpts, error) {
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
if chainID == nil {
return nil, ErrNoChainID
}
signer := types.NewEIP155Signer(chainID)
return &TransactOpts{
From: keyAddr,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != keyAddr {
return nil, ErrNotAuthorized
}
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
}, nil
}
// NewClefTransactor is a utility method to easily create a transaction signer
// with a clef backend.
func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) {
if address != account.Address {
return nil, ErrNotAuthorized
}
return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
},
}
}

View file

@ -18,779 +18,35 @@ package backends
import (
"context"
"errors"
"fmt"
"math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/ethclient/simulated"
)
// This nil assignment ensures at compile time that SimulatedBackend implements bind.ContractBackend.
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
var (
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
errBlockDoesNotExist = errors.New("block does not exist in blockchain")
errTransactionDoesNotExist = errors.New("transaction does not exist")
)
// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow for easy testing of contract bindings.
// Simulated backend implements the following interfaces:
// ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor,
// DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender
// SimulatedBackend is a simulated blockchain.
// Deprecated: use package github.com/ethereum/go-ethereum/ethclient/simulated instead.
type SimulatedBackend struct {
database ethdb.Database // In memory database to store our testing data
blockchain *core.BlockChain // Ethereum blockchain to handle the consensus
mu sync.Mutex
pendingBlock *types.Block // Currently pending block that will be imported on request
pendingState *state.StateDB // Currently pending state that will be the active on request
events *filters.EventSystem // Event system for filtering log events live
config *params.ChainConfig
*simulated.Backend
simulated.Client
}
// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database
// and uses a simulated blockchain for testing purposes.
// A simulated backend always uses chainID 1337.
func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
backend := &SimulatedBackend{
database: database,
blockchain: blockchain,
config: genesis.Config,
events: filters.NewEventSystem(&filterBackend{database, blockchain}, false),
}
backend.rollback()
return backend
// Fork sets the head to a new block, which is based on the provided parentHash.
func (b *SimulatedBackend) Fork(ctx context.Context, parentHash common.Hash) error {
return b.Backend.Fork(parentHash)
}
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
// A simulated backend always uses chainID 1337.
func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
return NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), alloc, gasLimit)
}
// Close terminates the underlying blockchain's update loop.
func (b *SimulatedBackend) Close() error {
b.blockchain.Stop()
return nil
}
// Commit imports all the pending transactions as a single block and starts a
// fresh new state.
func (b *SimulatedBackend) Commit() {
b.mu.Lock()
defer b.mu.Unlock()
if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
panic(err) // This cannot happen unless the simulator is wrong, fail in that case
}
b.rollback()
}
// Rollback aborts all pending transactions, reverting to the last committed state.
func (b *SimulatedBackend) Rollback() {
b.mu.Lock()
defer b.mu.Unlock()
b.rollback()
}
func (b *SimulatedBackend) rollback() {
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
stateDB, _ := b.blockchain.State()
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
}
// stateByBlockNumber retrieves a state by a given blocknumber.
func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) {
if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 {
return b.blockchain.State()
}
block, err := b.blockByNumberNoLock(ctx, blockNumber)
if err != nil {
return nil, err
}
return b.blockchain.StateAt(block.Root())
}
// CodeAt returns the code associated with a certain account in the blockchain.
func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil {
return nil, err
}
return stateDB.GetCode(contract), nil
}
// BalanceAt returns the wei balance of a certain account in the blockchain.
func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
b.mu.Lock()
defer b.mu.Unlock()
stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil {
return nil, err
}
return stateDB.GetBalance(contract), nil
}
// NonceAt returns the nonce of a certain account in the blockchain.
func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) {
b.mu.Lock()
defer b.mu.Unlock()
stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil {
return 0, err
}
return stateDB.GetNonce(contract), nil
}
// StorageAt returns the value of key in the storage of an account in the blockchain.
func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil {
return nil, err
}
val := stateDB.GetState(contract, key)
return val[:], nil
}
// TransactionReceipt returns the receipt of a transaction.
func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
b.mu.Lock()
defer b.mu.Unlock()
receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config)
return receipt, nil
}
// TransactionByHash checks the pool of pending transactions in addition to the
// blockchain. The isPending return value indicates whether the transaction has been
// mined yet. Note that the transaction may not be part of the canonical chain even if
// it's not pending.
func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
b.mu.Lock()
defer b.mu.Unlock()
tx := b.pendingBlock.Transaction(txHash)
if tx != nil {
return tx, true, nil
}
tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash)
if tx != nil {
return tx, false, nil
}
return nil, false, ethereum.NotFound
}
// BlockByHash retrieves a block based on the block hash.
func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
b.mu.Lock()
defer b.mu.Unlock()
if hash == b.pendingBlock.Hash() {
return b.pendingBlock, nil
}
block := b.blockchain.GetBlockByHash(hash)
if block != nil {
return block, nil
}
return nil, errBlockDoesNotExist
}
// BlockByNumber retrieves a block from the database by number, caching it
// (associated with its hash) if found.
func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
b.mu.Lock()
defer b.mu.Unlock()
return b.blockByNumberNoLock(ctx, number)
}
// blockByNumberNoLock retrieves a block from the database by number, caching it
// (associated with its hash) if found without Lock.
func (b *SimulatedBackend) blockByNumberNoLock(ctx context.Context, number *big.Int) (*types.Block, error) {
if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
return b.blockchain.CurrentBlock(), nil
}
block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
if block == nil {
return nil, errBlockDoesNotExist
}
return block, nil
}
// HeaderByHash returns a block header from the current canonical chain.
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
b.mu.Lock()
defer b.mu.Unlock()
if hash == b.pendingBlock.Hash() {
return b.pendingBlock.Header(), nil
}
header := b.blockchain.GetHeaderByHash(hash)
if header == nil {
return nil, errBlockDoesNotExist
}
return header, nil
}
// HeaderByNumber returns a block header from the current canonical chain. If number is
// nil, the latest known header is returned.
func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) {
b.mu.Lock()
defer b.mu.Unlock()
if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 {
return b.blockchain.CurrentHeader(), nil
}
return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
}
// TransactionCount returns the number of transactions in a given block.
func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
b.mu.Lock()
defer b.mu.Unlock()
if blockHash == b.pendingBlock.Hash() {
return uint(b.pendingBlock.Transactions().Len()), nil
}
block := b.blockchain.GetBlockByHash(blockHash)
if block == nil {
return uint(0), errBlockDoesNotExist
}
return uint(block.Transactions().Len()), nil
}
// TransactionInBlock returns the transaction for a specific block at a specific index.
func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
b.mu.Lock()
defer b.mu.Unlock()
if blockHash == b.pendingBlock.Hash() {
transactions := b.pendingBlock.Transactions()
if uint(len(transactions)) < index+1 {
return nil, errTransactionDoesNotExist
}
return transactions[index], nil
}
block := b.blockchain.GetBlockByHash(blockHash)
if block == nil {
return nil, errBlockDoesNotExist
}
transactions := block.Transactions()
if uint(len(transactions)) < index+1 {
return nil, errTransactionDoesNotExist
}
return transactions[index], nil
}
// PendingCodeAt returns the code associated with an account in the pending state.
func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
return b.pendingState.GetCode(contract), nil
}
func newRevertError(result *core.ExecutionResult) *revertError {
reason, errUnpack := abi.UnpackRevert(result.Revert())
err := errors.New("execution reverted")
if errUnpack == nil {
err = fmt.Errorf("execution reverted: %v", reason)
}
return &revertError{
error: err,
reason: hexutil.Encode(result.Revert()),
}
}
// revertError is an API error that encompasses an EVM revert with JSON error
// code and a binary data blob.
type revertError struct {
error
reason string // revert reason hex encoded
}
// ErrorCode returns the JSON error code for a revert.
// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
func (e *revertError) ErrorCode() int {
return 3
}
// ErrorData returns the hex encoded revert reason.
func (e *revertError) ErrorData() interface{} {
return e.reason
}
// CallContract executes a contract call.
func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 {
return nil, errBlockNumberUnsupported
}
stateDB, err := b.blockchain.State()
if err != nil {
return nil, err
}
res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB)
if err != nil {
return nil, err
}
// If the result contains a revert reason, try to unpack and return it.
if len(res.Revert()) > 0 {
return nil, newRevertError(res)
}
return res.Return(), res.Err
}
// PendingCallContract executes a contract call on the pending state.
func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
if err != nil {
return nil, err
}
// If the result contains a revert reason, try to unpack and return it.
if len(res.Revert()) > 0 {
return nil, newRevertError(res)
}
return res.Return(), res.Err
}
// PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving
// the nonce currently pending for the account.
func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
b.mu.Lock()
defer b.mu.Unlock()
return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
}
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
// chain doesn't have miners, we just return a gas price of 1 for any call.
func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
return big.NewInt(1), nil
}
// EstimateGas executes the requested code against the currently pending block/state and
// returns the used amount of gas.
func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
b.mu.Lock()
defer b.mu.Unlock()
// Determine the lowest and highest possible gas limits to binary search in between
var (
lo uint64 = params.TxGas - 1
hi uint64
cap uint64
)
if call.Gas >= params.TxGas {
hi = call.Gas
} else {
hi = b.pendingBlock.GasLimit()
}
// Recap the highest gas allowance with account's balance.
if call.GasPrice != nil && call.GasPrice.BitLen() != 0 {
balance := b.pendingState.GetBalance(call.From) // from can't be nil
available := new(big.Int).Set(balance)
if call.Value != nil {
if call.Value.Cmp(available) >= 0 {
return 0, errors.New("insufficient funds for transfer")
}
available.Sub(available, call.Value)
}
allowance := new(big.Int).Div(available, call.GasPrice)
if allowance.IsUint64() && hi > allowance.Uint64() {
transfer := call.Value
if transfer == nil {
transfer = new(big.Int)
}
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
"sent", transfer, "gasprice", call.GasPrice, "fundable", allowance)
hi = allowance.Uint64()
}
}
cap = hi
// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
call.Gas = gas
snapshot := b.pendingState.Snapshot()
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
b.pendingState.RevertToSnapshot(snapshot)
if err != nil {
if errors.Is(err, core.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
}
return true, nil, err // Bail out
}
return res.Failed(), res, nil
}
// Execute the binary search and hone in on an executable gas limit
for lo+1 < hi {
mid := (hi + lo) / 2
failed, _, err := executable(mid)
// If the error is not nil(consensus error), it means the provided message
// call or transaction will never be accepted no matter how much gas it is
// assigned. Return the error directly, don't struggle any more
if err != nil {
return 0, err
}
if failed {
lo = mid
} else {
hi = mid
}
}
// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
failed, result, err := executable(hi)
if err != nil {
return 0, err
}
if failed {
if result != nil && result.Err != vm.ErrOutOfGas {
if len(result.Revert()) > 0 {
return 0, newRevertError(result)
}
return 0, result.Err
}
// Otherwise, the specified gas cap is too low
return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
}
}
return hi, nil
}
// callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) {
// Ensure message is initialized properly.
if call.GasPrice == nil {
call.GasPrice = big.NewInt(1)
}
if call.Gas == 0 {
call.Gas = 50000000
}
if call.Value == nil {
call.Value = new(big.Int)
}
// Set infinite balance to the fake caller account.
from := stateDB.GetOrNewStateObject(call.From)
from.SetBalance(math.MaxBig256)
// Execute the call.
msg := callMsg{call}
txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{})
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()
}
// SendTransaction updates the pending block to include the given transaction.
// It panics if the transaction is invalid.
func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
b.mu.Lock()
defer b.mu.Unlock()
sender, err := types.Sender(types.NewEIP155Signer(b.config.ChainID), tx)
if err != nil {
panic(fmt.Errorf("invalid transaction: %v", err))
}
nonce := b.pendingState.GetNonce(sender)
if tx.Nonce() != nonce {
panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
}
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTxWithChain(b.blockchain, tx)
}
block.AddTxWithChain(b.blockchain, tx)
})
stateDB, _ := b.blockchain.State()
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
return nil
}
// FilterLogs executes a log filter operation, blocking during execution and
// returning all the results in one batch.
//
// TODO(karalabe): Deprecate when the subscription one can return past data too.
func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) {
var filter *filters.Filter
if query.BlockHash != nil {
// Block filter requested, construct a single-shot filter
filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain}, *query.BlockHash, query.Addresses, query.Topics)
} else {
// Initialize unset filter boundaries to run from genesis to chain head
from := int64(0)
if query.FromBlock != nil {
from = query.FromBlock.Int64()
}
to := int64(-1)
if query.ToBlock != nil {
to = query.ToBlock.Int64()
}
// Construct the range filter
filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain}, from, to, query.Addresses, query.Topics)
// A simulated backend always uses chainID 1337.
//
// Deprecated: please use simulated.Backend from package
// github.com/ethereum/go-ethereum/ethclient/simulated instead.
func NewSimulatedBackend(alloc types.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
b := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(gasLimit))
return &SimulatedBackend{
Backend: b,
Client: b.Client(),
}
// Run the filter and return all the logs
logs, err := filter.Logs(ctx)
if err != nil {
return nil, err
}
res := make([]types.Log, len(logs))
for i, nLog := range logs {
res[i] = *nLog
}
return res, nil
}
// SubscribeFilterLogs creates a background log filtering operation, returning a
// subscription immediately, which can be used to stream the found events.
func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
// Subscribe to contract events
sink := make(chan []*types.Log)
sub, err := b.events.SubscribeLogs(query, sink)
if err != nil {
return nil, err
}
// Since we're getting logs in batches, we need to flatten them into a plain stream
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case logs := <-sink:
for _, nlog := range logs {
select {
case ch <- *nlog:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// SubscribeNewHead returns an event subscription for a new header.
func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
// subscribe to a new head
sink := make(chan *types.Header)
sub := b.events.SubscribeNewHeads(sink)
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case head := <-sink:
select {
case ch <- head:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// AdjustTime adds a time shift to the simulated clock.
// It can only be called on empty blocks.
func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
b.mu.Lock()
defer b.mu.Unlock()
if len(b.pendingBlock.Transactions()) != 0 {
return errors.New("Could not adjust time on non-empty block")
}
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
block.OffsetTime(int64(adjustment.Seconds()))
})
stateDB, _ := b.blockchain.State()
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
return nil
}
// Blockchain returns the underlying blockchain.
func (b *SimulatedBackend) Blockchain() *core.BlockChain {
return b.blockchain
}
// callMsg implements core.Message to allow passing it as a transaction simulator.
type callMsg struct {
ethereum.CallMsg
}
func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callMsg) Nonce() uint64 { return 0 }
func (m callMsg) CheckNonce() bool { return false }
func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
type filterBackend struct {
db ethdb.Database
bc *core.BlockChain
}
func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) {
if block == rpc.LatestBlockNumber {
return fb.bc.CurrentHeader(), nil
}
return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil
}
func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
return fb.bc.GetHeaderByHash(hash), nil
}
func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
number := rawdb.ReadHeaderNumber(fb.db, hash)
if number == nil {
return nil, nil
}
return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil
}
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
number := rawdb.ReadHeaderNumber(fb.db, hash)
if number == nil {
return nil, nil
}
receipts := rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config())
if receipts == nil {
return nil, nil
}
logs := make([][]*types.Log, len(receipts))
for i, receipt := range receipts {
logs[i] = receipt.Logs
}
return logs, nil
}
func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
return nullSubscription()
}
func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
return fb.bc.SubscribeChainEvent(ch)
}
func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return fb.bc.SubscribeRemovedLogsEvent(ch)
}
func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
return fb.bc.SubscribeLogsEvent(ch)
}
func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
return nullSubscription()
}
func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }
func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) {
panic("not supported")
}
func nullSubscription() event.Subscription {
return event.NewSubscription(func(quit <-chan struct{}) error {
<-quit
return nil
})
}

File diff suppressed because it is too large Load diff

View file

@ -1,257 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind_test
import (
"context"
"math/big"
"reflect"
"strings"
"testing"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
type mockCaller struct {
codeAtBlockNumber *big.Int
callContractBlockNumber *big.Int
pendingCodeAtCalled bool
pendingCallContractCalled bool
}
func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
mc.codeAtBlockNumber = blockNumber
return []byte{1, 2, 3}, nil
}
func (mc *mockCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
mc.callContractBlockNumber = blockNumber
return nil, nil
}
func (mc *mockCaller) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
mc.pendingCodeAtCalled = true
return nil, nil
}
func (mc *mockCaller) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
mc.pendingCallContractCalled = true
return nil, nil
}
func TestPassingBlockNumber(t *testing.T) {
mc := &mockCaller{}
bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{
Methods: map[string]abi.Method{
"something": {
Name: "something",
Outputs: abi.Arguments{},
},
},
}, mc, nil, nil)
blockNumber := big.NewInt(42)
bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something")
if mc.callContractBlockNumber != blockNumber {
t.Fatalf("CallContract() was not passed the block number")
}
if mc.codeAtBlockNumber != blockNumber {
t.Fatalf("CodeAt() was not passed the block number")
}
bc.Call(&bind.CallOpts{}, nil, "something")
if mc.callContractBlockNumber != nil {
t.Fatalf("CallContract() was passed a block number when it should not have been")
}
if mc.codeAtBlockNumber != nil {
t.Fatalf("CodeAt() was passed a block number when it should not have been")
}
bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, nil, "something")
if !mc.pendingCallContractCalled {
t.Fatalf("CallContract() was not passed the block number")
}
if !mc.pendingCodeAtCalled {
t.Fatalf("CodeAt() was not passed the block number")
}
}
const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158"
func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
hash := crypto.Keccak256Hash([]byte("testName"))
topics := []common.Hash{
common.HexToHash("0x0"),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"name": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"})
if err != nil {
t.Fatal(err)
}
hash := crypto.Keccak256Hash(sliceBytes)
topics := []common.Hash{
common.HexToHash("0x0"),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"names","type":"string[]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"names": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")})
if err != nil {
t.Fatal(err)
}
hash := crypto.Keccak256Hash(arrBytes)
topics := []common.Hash{
common.HexToHash("0x0"),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"addresses","type":"address[2]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"addresses": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")
addrBytes := mockAddress.Bytes()
hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)"))
functionSelector := hash[:4]
functionTyBytes := append(addrBytes, functionSelector...)
var functionTy [24]byte
copy(functionTy[:], functionTyBytes[0:24])
topics := []common.Hash{
common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"),
common.BytesToHash(functionTyBytes),
}
mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"function","type":"function"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"function": functionTy,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
bytes := []byte{1, 2, 3, 4, 5}
hash := crypto.Keccak256Hash(bytes)
topics := []common.Hash{
common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"content","type":"bytes"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"content": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func unpackAndCheck(t *testing.T, bc *bind.BoundContract, expected map[string]interface{}, mockLog types.Log) {
received := make(map[string]interface{})
if err := bc.UnpackLogIntoMap(received, "received", mockLog); err != nil {
t.Error(err)
}
if len(received) != len(expected) {
t.Fatalf("unpacked map length %v not equal expected length of %v", len(received), len(expected))
}
for name, elem := range expected {
if !reflect.DeepEqual(elem, received[name]) {
t.Errorf("field %v does not match expected, want %v, got %v", name, elem, received[name])
}
}
}
func newMockLog(topics []common.Hash, txHash common.Hash) types.Log {
return types.Log{
Address: common.HexToAddress("0x0"),
Topics: topics,
Data: hexutil.MustDecode(hexData),
BlockNumber: uint64(26),
TxHash: txHash,
TxIndex: 111,
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
Index: 7,
Removed: false,
}
}

294
accounts/abi/bind/old.go Normal file
View file

@ -0,0 +1,294 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package bind is the runtime for abigen v1 generated contract bindings.
// Deprecated: please use github.com/ethereum/go-ethereum/bind/v2
package bind
import (
"context"
"crypto/ecdsa"
"errors"
"io"
"math/big"
"strings"
"sync"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/abigen"
bind2 "github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)
// Bind generates a v1 contract binding.
// Deprecated: binding generation has moved to github.com/ethereum/go-ethereum/accounts/abi/abigen
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
return abigen.Bind(types, abis, bytecodes, fsigs, pkg, libs, aliases)
}
// auth.go
// ErrNoChainID is returned whenever the user failed to specify a chain id.
var ErrNoChainID = errors.New("no chain id specified")
// ErrNotAuthorized is returned when an account is not properly unlocked.
var ErrNotAuthorized = bind2.ErrNotAuthorized
// NewTransactor is a utility method to easily create a transaction signer from
// an encrypted json key stream and the associated passphrase.
//
// Deprecated: Use NewTransactorWithChainID instead.
func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
log.Warn("WARNING: NewTransactor has been deprecated in favour of NewTransactorWithChainID")
json, err := io.ReadAll(keyin)
if err != nil {
return nil, err
}
key, err := keystore.DecryptKey(json, passphrase)
if err != nil {
return nil, err
}
return NewKeyedTransactor(key.PrivateKey), nil
}
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
// a decrypted key from a keystore.
//
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
log.Warn("WARNING: NewKeyStoreTransactor has been deprecated in favour of NewTransactorWithChainID")
signer := types.HomesteadSigner{}
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != account.Address {
return nil, ErrNotAuthorized
}
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
Context: context.Background(),
}, nil
}
// NewKeyedTransactor is a utility method to easily create a transaction signer
// from a single private key.
//
// Deprecated: Use NewKeyedTransactorWithChainID instead.
func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
log.Warn("WARNING: NewKeyedTransactor has been deprecated in favour of NewKeyedTransactorWithChainID")
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
signer := types.HomesteadSigner{}
return &TransactOpts{
From: keyAddr,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != keyAddr {
return nil, ErrNotAuthorized
}
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
Context: context.Background(),
}
}
// NewTransactorWithChainID is a utility method to easily create a transaction signer from
// an encrypted json key stream and the associated passphrase.
func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.Int) (*TransactOpts, error) {
json, err := io.ReadAll(keyin)
if err != nil {
return nil, err
}
key, err := keystore.DecryptKey(json, passphrase)
if err != nil {
return nil, err
}
return NewKeyedTransactorWithChainID(key.PrivateKey, chainID)
}
// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
// a decrypted key from a keystore.
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
// New version panics for chainID == nil, catch it here.
if chainID == nil {
return nil, ErrNoChainID
}
return bind2.NewKeyStoreTransactor(keystore, account, chainID), nil
}
// NewKeyedTransactorWithChainID is a utility method to easily create a transaction signer
// from a single private key.
func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*TransactOpts, error) {
// New version panics for chainID == nil, catch it here.
if chainID == nil {
return nil, ErrNoChainID
}
return bind2.NewKeyedTransactor(key, chainID), nil
}
// NewClefTransactor is a utility method to easily create a transaction signer
// with a clef backend.
func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
return bind2.NewClefTransactor(clef, account)
}
// backend.go
var (
// ErrNoCode is returned by call and transact operations for which the requested
// recipient contract to operate on does not exist in the state db or does not
// have any code associated with it (i.e. self-destructed).
ErrNoCode = bind2.ErrNoCode
// ErrNoPendingState is raised when attempting to perform a pending state action
// on a backend that doesn't implement PendingContractCaller.
ErrNoPendingState = bind2.ErrNoPendingState
// ErrNoBlockHashState is raised when attempting to perform a block hash action
// on a backend that doesn't implement BlockHashContractCaller.
ErrNoBlockHashState = bind2.ErrNoBlockHashState
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
// an empty contract behind.
ErrNoCodeAfterDeploy = bind2.ErrNoCodeAfterDeploy
)
// ContractCaller defines the methods needed to allow operating with a contract on a read
// only basis.
type ContractCaller = bind2.ContractCaller
// PendingContractCaller defines methods to perform contract calls on the pending state.
// Call will try to discover this interface when access to the pending state is requested.
// If the backend does not support the pending state, Call returns ErrNoPendingState.
type PendingContractCaller = bind2.PendingContractCaller
// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
// Call will try to discover this interface when access to a block by hash is requested.
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
type BlockHashContractCaller = bind2.BlockHashContractCaller
// ContractTransactor defines the methods needed to allow operating with a contract
// on a write only basis. Besides the transacting method, the remainder are helpers
// used when the user does not provide some needed values, but rather leaves it up
// to the transactor to decide.
type ContractTransactor = bind2.ContractTransactor
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
type DeployBackend = bind2.DeployBackend
// ContractFilterer defines the methods needed to access log events using one-off
// queries or continuous event subscriptions.
type ContractFilterer = bind2.ContractFilterer
// ContractBackend defines the methods needed to work with contracts on a read-write basis.
type ContractBackend = bind2.ContractBackend
// base.go
type SignerFn = bind2.SignerFn
type CallOpts = bind2.CallOpts
type TransactOpts = bind2.TransactOpts
type FilterOpts = bind2.FilterOpts
type WatchOpts = bind2.WatchOpts
type BoundContract = bind2.BoundContract
func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller, transactor ContractTransactor, filterer ContractFilterer) *BoundContract {
return bind2.NewBoundContract(address, abi, caller, transactor, filterer)
}
func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) {
packed, err := abi.Pack("", params...)
if err != nil {
return common.Address{}, nil, nil, err
}
addr, tx, err := bind2.DeployContract(opts, bytecode, backend, packed)
if err != nil {
return common.Address{}, nil, nil, err
}
contract := NewBoundContract(addr, abi, backend, backend, backend)
return addr, tx, contract, nil
}
// MetaData collects all metadata for a bound contract.
type MetaData struct {
Bin string // runtime bytecode (as a hex string)
ABI string // the raw ABI definition (JSON)
Sigs map[string]string // 4byte identifier -> function signature
mu sync.Mutex
parsedABI *abi.ABI
}
// GetAbi returns the parsed ABI definition.
func (m *MetaData) GetAbi() (*abi.ABI, error) {
m.mu.Lock()
defer m.mu.Unlock()
if m.parsedABI != nil {
return m.parsedABI, nil
}
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
return nil, err
} else {
m.parsedABI = &parsed
}
return m.parsedABI, nil
}
// util.go
// WaitMined waits for tx to be mined on the blockchain.
// It stops waiting when the context is canceled.
func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {
return bind2.WaitMined(ctx, b, tx.Hash())
}
// WaitMinedHash waits for a transaction with the provided hash to be mined on the blockchain.
// It stops waiting when the context is canceled.
func WaitMinedHash(ctx context.Context, b DeployBackend, hash common.Hash) (*types.Receipt, error) {
return bind2.WaitMined(ctx, b, hash)
}
// WaitDeployed waits for a contract deployment transaction and returns the on-chain
// contract address when it is mined. It stops waiting when ctx is canceled.
func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
if tx.To() != nil {
return common.Address{}, errors.New("tx is not contract creation")
}
return bind2.WaitDeployed(ctx, b, tx.Hash())
}
// WaitDeployedHash waits for a contract deployment transaction with the provided hash and returns the on-chain
// contract address when it is mined. It stops waiting when ctx is canceled.
func WaitDeployedHash(ctx context.Context, b DeployBackend, hash common.Hash) (common.Address, error) {
return bind2.WaitDeployed(ctx, b, hash)
}

View file

@ -1,134 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind_test
import (
"context"
"errors"
"math/big"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
var waitDeployedTests = map[string]struct {
code string
gas uint64
wantAddress common.Address
wantErr error
}{
"successful deploy": {
code: `6060604052600a8060106000396000f360606040526008565b00`,
gas: 3000000,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
},
"empty code": {
code: ``,
gas: 300000,
wantErr: bind.ErrNoCodeAfterDeploy,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
},
}
func TestWaitDeployed(t *testing.T) {
for name, test := range waitDeployedTests {
backend := backends.NewSimulatedBackend(
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
},
10000000,
)
defer backend.Close()
// Create the transaction.
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, big.NewInt(1), common.FromHex(test.code))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
// Wait for it to get mined in the background.
var (
err error
address common.Address
mined = make(chan struct{})
ctx = context.Background()
)
go func() {
address, err = bind.WaitDeployed(ctx, backend, tx)
close(mined)
}()
// Send and mine the transaction.
backend.SendTransaction(ctx, tx)
backend.Commit()
select {
case <-mined:
if err != test.wantErr {
t.Errorf("test %q: error mismatch: want %q, got %q", name, test.wantErr, err)
}
if address != test.wantAddress {
t.Errorf("test %q: unexpected contract address %s", name, address.Hex())
}
case <-time.After(2 * time.Second):
t.Errorf("test %q: timeout", name)
}
}
}
func TestWaitDeployedCornerCases(t *testing.T) {
backend := backends.NewSimulatedBackend(
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
},
10000000,
)
defer backend.Close()
// Create a transaction to an account.
code := "6060604052600a8060106000396000f360606040526008565b00"
tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, big.NewInt(1), common.FromHex(code))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
backend.SendTransaction(ctx, tx)
backend.Commit()
notContentCreation := errors.New("tx is not contract creation")
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContentCreation.Error() {
t.Errorf("error missmatch: want %q, got %q, ", notContentCreation, err)
}
// Create a transaction that is not mined.
tx = types.NewContractCreation(1, big.NewInt(0), 3000000, big.NewInt(1), common.FromHex(code))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
go func() {
contextCanceled := errors.New("context canceled")
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != contextCanceled.Error() {
t.Errorf("error missmatch: want %q, got %q, ", contextCanceled, err)
}
}()
backend.SendTransaction(ctx, tx)
cancel()
}

View file

@ -0,0 +1,96 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind
import (
"context"
"crypto/ecdsa"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
// ErrNotAuthorized is returned when an account is not properly unlocked.
var ErrNotAuthorized = errors.New("not authorized to sign this account")
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
// a decrypted key from a keystore.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) *TransactOpts {
if chainID == nil {
panic("nil chainID")
}
signer := types.LatestSignerForChainID(chainID)
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != account.Address {
return nil, ErrNotAuthorized
}
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
Context: context.Background(),
}
}
// NewKeyedTransactor is a utility method to easily create a transaction signer
// from a single private key.
func NewKeyedTransactor(key *ecdsa.PrivateKey, chainID *big.Int) *TransactOpts {
if chainID == nil {
panic("nil chainID")
}
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
signer := types.LatestSignerForChainID(chainID)
return &TransactOpts{
From: keyAddr,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != keyAddr {
return nil, ErrNotAuthorized
}
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
if err != nil {
return nil, err
}
return tx.WithSignature(signer, signature)
},
Context: context.Background(),
}
}
// NewClefTransactor is a utility method to easily create a transaction signer
// with a clef backend.
func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) {
if address != account.Address {
return nil, ErrNotAuthorized
}
return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
},
Context: context.Background(),
}
}

View file

@ -29,16 +29,25 @@ import (
var (
// ErrNoCode is returned by call and transact operations for which the requested
// recipient contract to operate on does not exist in the state db or does not
// have any code associated with it (i.e. suicided).
// have any code associated with it (i.e. self-destructed).
ErrNoCode = errors.New("no contract code at given address")
// This error is raised when attempting to perform a pending state action
// ErrNoPendingState is raised when attempting to perform a pending state action
// on a backend that doesn't implement PendingContractCaller.
ErrNoPendingState = errors.New("backend does not support pending state")
// This error is returned by WaitDeployed if contract creation leaves an
// empty contract behind.
// ErrNoBlockHashState is raised when attempting to perform a block hash action
// on a backend that doesn't implement BlockHashContractCaller.
ErrNoBlockHashState = errors.New("backend does not support block hash state")
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
// an empty contract behind.
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
// ErrNoAddressInReceipt is returned by WaitDeployed when the receipt for the
// transaction hash does not contain a contract address. This error may indicate
// that the transaction hash was not a CREATE transaction.
ErrNoAddressInReceipt = errors.New("no contract address in receipt")
)
// ContractCaller defines the methods needed to allow operating with a contract on a read
@ -47,7 +56,8 @@ type ContractCaller interface {
// CodeAt returns the code of the given account. This is needed to differentiate
// between contract internal errors and the local chain being out of sync.
CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error)
// ContractCall executes an Ethereum contract call with the specified data as the
// CallContract executes an Ethereum contract call with the specified data as the
// input.
CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
}
@ -58,44 +68,41 @@ type ContractCaller interface {
type PendingContractCaller interface {
// PendingCodeAt returns the code of the given account in the pending state.
PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error)
// PendingCallContract executes an Ethereum contract call against the pending state.
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
}
// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
// Call will try to discover this interface when access to a block by hash is requested.
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
type BlockHashContractCaller interface {
// CodeAtHash returns the code of the given account in the state at the specified block hash.
CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error)
// CallContractAtHash executes an Ethereum contract call against the state at the specified block hash.
CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error)
}
// ContractTransactor defines the methods needed to allow operating with a contract
// on a write only basis. Besides the transacting method, the remainder are helpers
// used when the user does not provide some needed values, but rather leaves it up
// to the transactor to decide.
type ContractTransactor interface {
ethereum.GasEstimator
ethereum.GasPricer
ethereum.GasPricer1559
ethereum.TransactionSender
// HeaderByNumber returns a block header from the current canonical chain. If
// number is nil, the latest known header is returned.
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
// PendingCodeAt returns the code of the given account in the pending state.
PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error)
// PendingNonceAt retrieves the current pending nonce associated with an account.
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
// execution of a transaction.
SuggestGasPrice(ctx context.Context) (*big.Int, error)
// EstimateGas tries to estimate the gas needed to execute a specific
// transaction based on the current pending state of the backend blockchain.
// There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default.
EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
// SendTransaction injects the transaction into the pending pool for execution.
SendTransaction(ctx context.Context, tx *types.Transaction) error
}
// ContractFilterer defines the methods needed to access log events using one-off
// queries or continuous event subscriptions.
type ContractFilterer interface {
// FilterLogs executes a log filter operation, blocking during execution and
// returning all the results in one batch.
//
// TODO(karalabe): Deprecate when the subscription one can return past data too.
FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error)
// SubscribeFilterLogs creates a background log filtering operation, returning
// a subscription immediately, which can be used to stream the found events.
SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
}
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
@ -104,9 +111,23 @@ type DeployBackend interface {
CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
}
// ContractFilterer defines the methods needed to access log events using one-off
// queries or continuous event subscriptions.
type ContractFilterer interface {
ethereum.LogFilterer
}
// ContractBackend defines the methods needed to work with contracts on a read-write basis.
type ContractBackend interface {
ContractCaller
ContractTransactor
ContractFilterer
}
// Backend combines all backend methods used in this package. This type is provided for
// convenience. It is meant to be used when you need to hold a reference to a backend that
// is used for both deployment and contract interaction.
type Backend interface {
DeployBackend
ContractBackend
}

View file

@ -21,15 +21,24 @@ import (
"errors"
"fmt"
"math/big"
"strings"
"sync"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
)
const basefeeWiggleMultiplier = 2
var (
errNoEventSignature = errors.New("no event signature")
errEventSignatureMismatch = errors.New("event signature mismatch")
)
// SignerFn is a signer function callback when a contract requires a method to
// sign the transaction before submission.
type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error)
@ -39,6 +48,7 @@ type CallOpts struct {
Pending bool // Whether to operate on the pending state or the last known one
From common.Address // Optional the sender address, otherwise the first account is used
BlockNumber *big.Int // Optional the block number on which the call should be performed
BlockHash common.Hash // Optional the block hash on which the call should be performed
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
@ -49,11 +59,16 @@ type TransactOpts struct {
Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state)
Signer SignerFn // Method to use for signing the transaction (mandatory)
Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle)
GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle)
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
AccessList types.AccessList // Access list to set for the transaction execution (nil = no access list)
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
NoSend bool // Do all transact steps but do not send the transaction
}
// FilterOpts is the collection of options to fine tune filtering for events
@ -72,6 +87,46 @@ type WatchOpts struct {
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
// MetaData collects all metadata for a bound contract.
type MetaData struct {
Bin string // deployer bytecode (as a hex string)
ABI string // the raw ABI definition (JSON)
Deps []*MetaData // library dependencies of the contract
// For bindings that were compiled from combined-json ID is the Solidity
// library pattern: a 34 character prefix of the hex encoding of the keccak256
// hash of the fully qualified 'library name', i.e. the path of the source file.
//
// For contracts compiled from the ABI definition alone, this is the type name
// of the contract (as specified in the ABI definition or overridden via the
// --type flag).
//
// This is a unique identifier of a contract within a compilation unit. When
// used as part of a multi-contract deployment with library dependencies, the
// ID is used to link contracts during deployment using [LinkAndDeploy].
ID string
mu sync.Mutex
parsedABI *abi.ABI
}
// ParseABI returns the parsed ABI specification, or an error if the string
// representation of the ABI set in the MetaData instance could not be parsed.
func (m *MetaData) ParseABI() (*abi.ABI, error) {
m.mu.Lock()
defer m.mu.Unlock()
if m.parsedABI != nil {
return m.parsedABI, nil
}
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
return nil, err
} else {
m.parsedABI = &parsed
}
return m.parsedABI, nil
}
// BoundContract is the base wrapper object that reflects a contract on the
// Ethereum network. It contains a collection of methods that are used by the
// higher level contract bindings to operate.
@ -95,74 +150,28 @@ func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller
}
}
// DeployContract deploys a contract onto the Ethereum blockchain and binds the
// deployment address with a Go wrapper.
func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) {
// Otherwise try to deploy the contract
c := NewBoundContract(common.Address{}, abi, backend, backend, backend)
input, err := c.abi.Pack("", params...)
if err != nil {
return common.Address{}, nil, nil, err
}
tx, err := c.transact(opts, nil, append(bytecode, input...))
if err != nil {
return common.Address{}, nil, nil, err
}
c.address = crypto.CreateAddress(opts.From, tx.Nonce())
return c.address, tx, c, nil
// Address returns the deployment address of the contract.
func (c *BoundContract) Address() common.Address {
return c.address
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method string, params ...interface{}) error {
// Don't crash on a lazy user
if opts == nil {
opts = new(CallOpts)
}
func (c *BoundContract) Call(opts *CallOpts, results *[]any, method string, params ...any) error {
if results == nil {
results = new([]interface{})
results = new([]any)
}
// Pack the input, call and unpack the results
input, err := c.abi.Pack(method, params...)
if err != nil {
return err
}
var (
msg = ethereum.CallMsg{From: opts.From, To: &c.address, Data: input}
ctx = ensureContext(opts.Context)
code []byte
output []byte
)
if opts.Pending {
pb, ok := c.caller.(PendingContractCaller)
if !ok {
return ErrNoPendingState
}
output, err = pb.PendingCallContract(ctx, msg)
if err == nil && len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise.
if code, err = pb.PendingCodeAt(ctx, c.address); err != nil {
return err
} else if len(code) == 0 {
return ErrNoCode
}
}
} else {
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
if err != nil {
return err
}
if len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise.
if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil {
return err
} else if len(code) == 0 {
return ErrNoCode
}
}
output, err := c.call(opts, input)
if err != nil {
return err
}
if len(*results) == 0 {
@ -174,85 +183,263 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri
return c.abi.UnpackIntoInterface(res[0], method, output)
}
// CallRaw executes an eth_call against the contract with the raw calldata as
// input. It returns the call's return data or an error.
func (c *BoundContract) CallRaw(opts *CallOpts, input []byte) ([]byte, error) {
return c.call(opts, input)
}
func (c *BoundContract) call(opts *CallOpts, input []byte) ([]byte, error) {
// Don't crash on a lazy user
if opts == nil {
opts = new(CallOpts)
}
var (
msg = ethereum.CallMsg{From: opts.From, To: &c.address, Data: input}
ctx = ensureContext(opts.Context)
code []byte
output []byte
err error
)
if opts.Pending {
pb, ok := c.caller.(PendingContractCaller)
if !ok {
return nil, ErrNoPendingState
}
output, err = pb.PendingCallContract(ctx, msg)
if err != nil {
return nil, err
}
if len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise.
if code, err = pb.PendingCodeAt(ctx, c.address); err != nil {
return nil, err
} else if len(code) == 0 {
return nil, ErrNoCode
}
}
} else if opts.BlockHash != (common.Hash{}) {
bh, ok := c.caller.(BlockHashContractCaller)
if !ok {
return nil, ErrNoBlockHashState
}
output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
if err != nil {
return nil, err
}
if len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise.
if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
return nil, err
} else if len(code) == 0 {
return nil, ErrNoCode
}
}
} else {
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
if err != nil {
return nil, err
}
if len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise.
if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil {
return nil, err
} else if len(code) == 0 {
return nil, ErrNoCode
}
}
}
return output, nil
}
// Transact invokes the (paid) contract method with params as input values.
func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...any) (*types.Transaction, error) {
// Otherwise pack up the parameters and invoke the contract
input, err := c.abi.Pack(method, params...)
if err != nil {
return nil, err
}
// todo(rjl493456442) check the method is payable or not,
// reject invalid transaction at the first place
return c.transact(opts, &c.address, input)
}
// RawTransact initiates a transaction with the given raw calldata as the input.
// It's usually used to initiate transactions for invoking **Fallback** function.
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
// todo(rjl493456442) check the method is payable or not,
// reject invalid transaction at the first place
return c.transact(opts, &c.address, calldata)
}
// RawCreationTransact creates and submits a contract-creation transaction with
// the given calldata as the input.
func (c *BoundContract) RawCreationTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
return c.transact(opts, nil, calldata)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error) {
// todo(rjl493456442) check the payable fallback or receive is defined
// or not, reject invalid transaction at the first place
// Check if payable fallback or receive is defined
if !c.abi.HasReceive() && !(c.abi.HasFallback() && c.abi.Fallback.IsPayable()) {
return nil, fmt.Errorf("contract does not have a payable fallback or receive function")
}
return c.transact(opts, &c.address, nil)
}
func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Address, input []byte, head *types.Header) (*types.Transaction, error) {
// Normalize value
value := opts.Value
if value == nil {
value = new(big.Int)
}
// Estimate TipCap
gasTipCap := opts.GasTipCap
if gasTipCap == nil {
tip, err := c.transactor.SuggestGasTipCap(ensureContext(opts.Context))
if err != nil {
return nil, err
}
gasTipCap = tip
}
// Estimate FeeCap
gasFeeCap := opts.GasFeeCap
if gasFeeCap == nil {
gasFeeCap = new(big.Int).Add(
gasTipCap,
new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)),
)
}
if gasFeeCap.Cmp(gasTipCap) < 0 {
return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap)
}
// Estimate GasLimit
gasLimit := opts.GasLimit
if opts.GasLimit == 0 {
var err error
gasLimit, err = c.estimateGasLimit(opts, contract, input, nil, gasTipCap, gasFeeCap, value)
if err != nil {
return nil, err
}
}
// create the transaction
nonce, err := c.getNonce(opts)
if err != nil {
return nil, err
}
baseTx := &types.DynamicFeeTx{
To: contract,
Nonce: nonce,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Gas: gasLimit,
Value: value,
Data: input,
AccessList: opts.AccessList,
}
return types.NewTx(baseTx), nil
}
func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
if opts.GasFeeCap != nil || opts.GasTipCap != nil || opts.AccessList != nil {
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas or accessList specified but london is not active yet")
}
// Normalize value
value := opts.Value
if value == nil {
value = new(big.Int)
}
// Estimate GasPrice
gasPrice := opts.GasPrice
if gasPrice == nil {
price, err := c.transactor.SuggestGasPrice(ensureContext(opts.Context))
if err != nil {
return nil, err
}
gasPrice = price
}
// Estimate GasLimit
gasLimit := opts.GasLimit
if opts.GasLimit == 0 {
var err error
gasLimit, err = c.estimateGasLimit(opts, contract, input, gasPrice, nil, nil, value)
if err != nil {
return nil, err
}
}
// create the transaction
nonce, err := c.getNonce(opts)
if err != nil {
return nil, err
}
baseTx := &types.LegacyTx{
To: contract,
Nonce: nonce,
GasPrice: gasPrice,
Gas: gasLimit,
Value: value,
Data: input,
}
return types.NewTx(baseTx), nil
}
func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Address, input []byte, gasPrice, gasTipCap, gasFeeCap, value *big.Int) (uint64, error) {
if contract != nil {
// Gas estimation cannot succeed without code for method invocations.
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {
return 0, err
} else if len(code) == 0 {
return 0, ErrNoCode
}
}
msg := ethereum.CallMsg{
From: opts.From,
To: contract,
GasPrice: gasPrice,
GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap,
Value: value,
Data: input,
AccessList: opts.AccessList,
}
return c.transactor.EstimateGas(ensureContext(opts.Context), msg)
}
func (c *BoundContract) getNonce(opts *TransactOpts) (uint64, error) {
if opts.Nonce == nil {
return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
} else {
return opts.Nonce.Uint64(), nil
}
}
// transact executes an actual transaction invocation, first deriving any missing
// authorization fields, and then scheduling the transaction for execution.
func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
var err error
// Ensure a valid value field and resolve the account nonce
value := opts.Value
if value == nil {
value = new(big.Int)
if opts.GasPrice != nil && (opts.GasFeeCap != nil || opts.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
var nonce uint64
if opts.Nonce == nil {
nonce, err = c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
if err != nil {
return nil, fmt.Errorf("failed to retrieve account nonce: %v", err)
}
// Create the transaction
var (
rawTx *types.Transaction
err error
)
if opts.GasPrice != nil {
rawTx, err = c.createLegacyTx(opts, contract, input)
} else if opts.GasFeeCap != nil && opts.GasTipCap != nil {
rawTx, err = c.createDynamicTx(opts, contract, input, nil)
} else {
nonce = opts.Nonce.Uint64()
}
// Figure out the gas allowance and gas price values
gasPrice := opts.GasPrice
if gasPrice == nil {
gasPrice, err = c.transactor.SuggestGasPrice(ensureContext(opts.Context))
if err != nil {
return nil, fmt.Errorf("failed to suggest gas price: %v", err)
// Only query for basefee if gasPrice not specified
if head, errHead := c.transactor.HeaderByNumber(ensureContext(opts.Context), nil); errHead != nil {
return nil, errHead
} else if head.BaseFee != nil {
rawTx, err = c.createDynamicTx(opts, contract, input, head)
} else {
// Chain is not London ready -> use legacy transaction
rawTx, err = c.createLegacyTx(opts, contract, input)
}
}
gasLimit := opts.GasLimit
if gasLimit == 0 {
// Gas estimation cannot succeed without code for method invocations
if contract != nil {
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {
return nil, err
} else if len(code) == 0 {
return nil, ErrNoCode
}
}
// If the contract surely has code (or code is not needed), estimate the transaction
msg := ethereum.CallMsg{From: opts.From, To: contract, GasPrice: gasPrice, Value: value, Data: input}
gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg)
if err != nil {
return nil, fmt.Errorf("failed to estimate gas needed: %v", err)
}
}
// Create the transaction, sign it and schedule it for execution
var rawTx *types.Transaction
if contract == nil {
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
} else {
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
if err != nil {
return nil, err
}
// Sign the transaction and schedule it for execution
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")
}
@ -260,6 +447,9 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if err != nil {
return nil, err
}
if opts.NoSend {
return signedTx, nil
}
if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil {
return nil, err
}
@ -268,14 +458,13 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
// FilterLogs filters contract logs for past blocks, returning the necessary
// channels to construct a strongly typed bound iterator on top of them.
func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error) {
// Don't crash on a lazy user
if opts == nil {
opts = new(FilterOpts)
}
// Append the event selector to the query parameters and construct the topic set
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
query = append([][]any{{c.abi.Events[name].ID}}, query...)
topics, err := abi.MakeTopics(query...)
if err != nil {
return nil, nil, err
@ -298,7 +487,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
if err != nil {
return nil, nil, err
}
sub, err := event.NewSubscription(func(quit <-chan struct{}) error {
sub := event.NewSubscription(func(quit <-chan struct{}) error {
for _, log := range buff {
select {
case logs <- log:
@ -307,23 +496,20 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
}
}
return nil
}), nil
})
if err != nil {
return nil, nil, err
}
return logs, sub, nil
}
// WatchLogs filters subscribes to contract logs for future blocks, returning a
// subscription object that can be used to tear down the watcher.
func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error) {
// Don't crash on a lazy user
if opts == nil {
opts = new(WatchOpts)
}
// Append the event selector to the query parameters and construct the topic set
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
query = append([][]any{{c.abi.Events[name].ID}}, query...)
topics, err := abi.MakeTopics(query...)
if err != nil {
@ -347,7 +533,14 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
}
// UnpackLog unpacks a retrieved log into the provided output structure.
func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error {
func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error {
// Anonymous events are not supported.
if len(log.Topics) == 0 {
return errNoEventSignature
}
if log.Topics[0] != c.abi.Events[event].ID {
return errEventSignatureMismatch
}
if len(log.Data) > 0 {
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return err
@ -363,7 +556,14 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log)
}
// UnpackLogIntoMap unpacks a retrieved log into the provided map.
func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event string, log types.Log) error {
func (c *BoundContract) UnpackLogIntoMap(out map[string]any, event string, log types.Log) error {
// Anonymous events are not supported.
if len(log.Topics) == 0 {
return errNoEventSignature
}
if log.Topics[0] != c.abi.Events[event].ID {
return errEventSignatureMismatch
}
if len(log.Data) > 0 {
if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil {
return err
@ -382,7 +582,7 @@ func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event strin
// user specified it as such.
func ensureContext(ctx context.Context) context.Context {
if ctx == nil {
return context.TODO()
return context.Background()
}
return ctx
}

View file

@ -0,0 +1,589 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind_test
import (
"context"
"errors"
"math/big"
"reflect"
"strings"
"testing"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/stretchr/testify/assert"
)
func mockSign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { return tx, nil }
type mockTransactor struct {
baseFee *big.Int
gasTipCap *big.Int
gasPrice *big.Int
suggestGasTipCapCalled bool
suggestGasPriceCalled bool
}
func (mt *mockTransactor) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
return &types.Header{BaseFee: mt.baseFee}, nil
}
func (mt *mockTransactor) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) {
return []byte{1}, nil
}
func (mt *mockTransactor) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
return 0, nil
}
func (mt *mockTransactor) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
mt.suggestGasPriceCalled = true
return mt.gasPrice, nil
}
func (mt *mockTransactor) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
mt.suggestGasTipCapCalled = true
return mt.gasTipCap, nil
}
func (mt *mockTransactor) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) {
return 0, nil
}
func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transaction) error {
return nil
}
type mockCaller struct {
codeAtBlockNumber *big.Int
callContractBlockNumber *big.Int
callContractBytes []byte
callContractErr error
codeAtBytes []byte
codeAtErr error
}
func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
mc.codeAtBlockNumber = blockNumber
return mc.codeAtBytes, mc.codeAtErr
}
func (mc *mockCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
mc.callContractBlockNumber = blockNumber
return mc.callContractBytes, mc.callContractErr
}
type mockPendingCaller struct {
*mockCaller
pendingCodeAtBytes []byte
pendingCodeAtErr error
pendingCodeAtCalled bool
pendingCallContractCalled bool
pendingCallContractBytes []byte
pendingCallContractErr error
}
func (mc *mockPendingCaller) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
mc.pendingCodeAtCalled = true
return mc.pendingCodeAtBytes, mc.pendingCodeAtErr
}
func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
mc.pendingCallContractCalled = true
return mc.pendingCallContractBytes, mc.pendingCallContractErr
}
type mockBlockHashCaller struct {
*mockCaller
codeAtHashBytes []byte
codeAtHashErr error
codeAtHashCalled bool
callContractAtHashCalled bool
callContractAtHashBytes []byte
callContractAtHashErr error
}
func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.Address, hash common.Hash) ([]byte, error) {
mc.codeAtHashCalled = true
return mc.codeAtHashBytes, mc.codeAtHashErr
}
func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) {
mc.callContractAtHashCalled = true
return mc.callContractAtHashBytes, mc.callContractAtHashErr
}
func TestPassingBlockNumber(t *testing.T) {
t.Parallel()
mc := &mockPendingCaller{
mockCaller: &mockCaller{
codeAtBytes: []byte{1, 2, 3},
},
}
bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{
Methods: map[string]abi.Method{
"something": {
Name: "something",
Outputs: abi.Arguments{},
},
},
}, mc, nil, nil)
blockNumber := big.NewInt(42)
bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something")
if mc.callContractBlockNumber != blockNumber {
t.Fatalf("CallContract() was not passed the block number")
}
if mc.codeAtBlockNumber != blockNumber {
t.Fatalf("CodeAt() was not passed the block number")
}
bc.Call(&bind.CallOpts{}, nil, "something")
if mc.callContractBlockNumber != nil {
t.Fatalf("CallContract() was passed a block number when it should not have been")
}
if mc.codeAtBlockNumber != nil {
t.Fatalf("CodeAt() was passed a block number when it should not have been")
}
bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, nil, "something")
if !mc.pendingCallContractCalled {
t.Fatalf("CallContract() was not passed the block number")
}
if !mc.pendingCodeAtCalled {
t.Fatalf("CodeAt() was not passed the block number")
}
}
const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158"
func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
t.Parallel()
hash := crypto.Keccak256Hash([]byte("testName"))
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(string,address,uint256,bytes)")),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"name": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackAnonymousLogIntoMap(t *testing.T) {
t.Parallel()
mockLog := newMockLog(nil, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
var received map[string]interface{}
err := bc.UnpackLogIntoMap(received, "received", mockLog)
if err == nil {
t.Error("unpacking anonymous event is not supported")
}
if err.Error() != "no event signature" {
t.Errorf("expected error 'no event signature', got '%s'", err)
}
}
func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
t.Parallel()
sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"})
if err != nil {
t.Fatal(err)
}
hash := crypto.Keccak256Hash(sliceBytes)
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(string[],address,uint256,bytes)")),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"names","type":"string[]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"names": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
t.Parallel()
arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")})
if err != nil {
t.Fatal(err)
}
hash := crypto.Keccak256Hash(arrBytes)
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(address[2],address,uint256,bytes)")),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"addresses","type":"address[2]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"addresses": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
t.Parallel()
mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")
addrBytes := mockAddress.Bytes()
hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)"))
functionSelector := hash[:4]
functionTyBytes := append(addrBytes, functionSelector...)
var functionTy [24]byte
copy(functionTy[:], functionTyBytes[0:24])
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(function,address,uint256,bytes)")),
common.BytesToHash(functionTyBytes),
}
mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"function","type":"function"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"function": functionTy,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
t.Parallel()
bytes := []byte{1, 2, 3, 4, 5}
hash := crypto.Keccak256Hash(bytes)
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(bytes,address,uint256,bytes)")),
hash,
}
mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"content","type":"bytes"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
expectedReceivedMap := map[string]interface{}{
"content": hash,
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
"amount": big.NewInt(1),
"memo": []byte{88},
}
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
}
func TestTransactGasFee(t *testing.T) {
t.Parallel()
assert := assert.New(t)
// GasTipCap and GasFeeCap
// When opts.GasTipCap and opts.GasFeeCap are nil
mt := &mockTransactor{baseFee: big.NewInt(100), gasTipCap: big.NewInt(5)}
bc := bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil)
opts := &bind.TransactOpts{Signer: mockSign}
tx, err := bc.Transact(opts, "")
assert.Nil(err)
assert.Equal(big.NewInt(5), tx.GasTipCap())
assert.Equal(big.NewInt(205), tx.GasFeeCap())
assert.Nil(opts.GasTipCap)
assert.Nil(opts.GasFeeCap)
assert.True(mt.suggestGasTipCapCalled)
// Second call to Transact should use latest suggested GasTipCap
mt.gasTipCap = big.NewInt(6)
mt.suggestGasTipCapCalled = false
tx, err = bc.Transact(opts, "")
assert.Nil(err)
assert.Equal(big.NewInt(6), tx.GasTipCap())
assert.Equal(big.NewInt(206), tx.GasFeeCap())
assert.True(mt.suggestGasTipCapCalled)
// GasPrice
// When opts.GasPrice is nil
mt = &mockTransactor{gasPrice: big.NewInt(5)}
bc = bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil)
opts = &bind.TransactOpts{Signer: mockSign}
tx, err = bc.Transact(opts, "")
assert.Nil(err)
assert.Equal(big.NewInt(5), tx.GasPrice())
assert.Nil(opts.GasPrice)
assert.True(mt.suggestGasPriceCalled)
// Second call to Transact should use latest suggested GasPrice
mt.gasPrice = big.NewInt(6)
mt.suggestGasPriceCalled = false
tx, err = bc.Transact(opts, "")
assert.Nil(err)
assert.Equal(big.NewInt(6), tx.GasPrice())
assert.True(mt.suggestGasPriceCalled)
}
func unpackAndCheck(t *testing.T, bc *bind.BoundContract, expected map[string]interface{}, mockLog types.Log) {
received := make(map[string]interface{})
if err := bc.UnpackLogIntoMap(received, "received", mockLog); err != nil {
t.Error(err)
}
if len(received) != len(expected) {
t.Fatalf("unpacked map length %v not equal expected length of %v", len(received), len(expected))
}
for name, elem := range expected {
if !reflect.DeepEqual(elem, received[name]) {
t.Errorf("field %v does not match expected, want %v, got %v", name, elem, received[name])
}
}
}
func newMockLog(topics []common.Hash, txHash common.Hash) types.Log {
return types.Log{
Address: common.HexToAddress("0x0"),
Topics: topics,
Data: hexutil.MustDecode(hexData),
BlockNumber: uint64(26),
TxHash: txHash,
TxIndex: 111,
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
Index: 7,
Removed: false,
}
}
func TestCall(t *testing.T) {
t.Parallel()
var method, methodWithArg = "something", "somethingArrrrg"
tests := []struct {
name, method string
opts *bind.CallOpts
mc bind.ContractCaller
results *[]interface{}
wantErr bool
wantErrExact error
}{{
name: "ok not pending",
mc: &mockCaller{
codeAtBytes: []byte{0},
},
method: method,
}, {
name: "ok pending",
mc: &mockPendingCaller{
pendingCodeAtBytes: []byte{0},
},
opts: &bind.CallOpts{
Pending: true,
},
method: method,
}, {
name: "ok hash",
mc: &mockBlockHashCaller{
codeAtHashBytes: []byte{0},
},
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
}, {
name: "pack error, no method",
mc: new(mockCaller),
method: "else",
wantErr: true,
}, {
name: "interface error, pending but not a PendingContractCaller",
mc: new(mockCaller),
opts: &bind.CallOpts{
Pending: true,
},
method: method,
wantErrExact: bind.ErrNoPendingState,
}, {
name: "interface error, blockHash but not a BlockHashContractCaller",
mc: new(mockCaller),
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErrExact: bind.ErrNoBlockHashState,
}, {
name: "pending call canceled",
mc: &mockPendingCaller{
pendingCallContractErr: context.DeadlineExceeded,
},
opts: &bind.CallOpts{
Pending: true,
},
method: method,
wantErrExact: context.DeadlineExceeded,
}, {
name: "pending code at error",
mc: &mockPendingCaller{
pendingCodeAtErr: errors.New(""),
},
opts: &bind.CallOpts{
Pending: true,
},
method: method,
wantErr: true,
}, {
name: "no pending code at",
mc: new(mockPendingCaller),
opts: &bind.CallOpts{
Pending: true,
},
method: method,
wantErrExact: bind.ErrNoCode,
}, {
name: "call contract error",
mc: &mockCaller{
callContractErr: context.DeadlineExceeded,
},
method: method,
wantErrExact: context.DeadlineExceeded,
}, {
name: "code at error",
mc: &mockCaller{
codeAtErr: errors.New(""),
},
method: method,
wantErr: true,
}, {
name: "no code at",
mc: new(mockCaller),
method: method,
wantErrExact: bind.ErrNoCode,
}, {
name: "call contract at hash error",
mc: &mockBlockHashCaller{
callContractAtHashErr: context.DeadlineExceeded,
},
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErrExact: context.DeadlineExceeded,
}, {
name: "code at error",
mc: &mockBlockHashCaller{
codeAtHashErr: errors.New(""),
},
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErr: true,
}, {
name: "no code at hash",
mc: new(mockBlockHashCaller),
opts: &bind.CallOpts{
BlockHash: common.Hash{0xaa},
},
method: method,
wantErrExact: bind.ErrNoCode,
}, {
name: "unpack error missing arg",
mc: &mockCaller{
codeAtBytes: []byte{0},
},
method: methodWithArg,
wantErr: true,
}, {
name: "interface unpack error",
mc: &mockCaller{
codeAtBytes: []byte{0},
},
method: method,
results: &[]interface{}{0},
wantErr: true,
}}
for _, test := range tests {
bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{
Methods: map[string]abi.Method{
method: {
Name: method,
Outputs: abi.Arguments{},
},
methodWithArg: {
Name: methodWithArg,
Outputs: abi.Arguments{abi.Argument{}},
},
},
}, test.mc, nil, nil)
err := bc.Call(test.opts, test.results, test.method)
if test.wantErr || test.wantErrExact != nil {
if err == nil {
t.Fatalf("%q expected error", test.name)
}
if test.wantErrExact != nil && !errors.Is(err, test.wantErrExact) {
t.Fatalf("%q expected error %q but got %q", test.name, test.wantErrExact, err)
}
continue
}
if err != nil {
t.Fatalf("%q unexpected error: %v", test.name, err)
}
}
}
// TestCrashers contains some strings which previously caused the abi codec to crash.
func TestCrashers(t *testing.T) {
t.Parallel()
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"foo.Bar"}]}]}]`))
}

View file

@ -0,0 +1,167 @@
// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind
import (
"encoding/hex"
"fmt"
"maps"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// DeploymentParams contains parameters needed to deploy one or more contracts via LinkAndDeploy
type DeploymentParams struct {
// list of all contracts targeted for the deployment
Contracts []*MetaData
// optional map of ABI-encoded constructor inputs keyed by the MetaData.ID.
Inputs map[string][]byte
// optional map of override addresses for specifying already-deployed
// contracts. It is keyed by the MetaData.ID.
Overrides map[string]common.Address
}
// validate determines whether the contracts specified in the DeploymentParams
// instance have embedded deployer code in their provided MetaData instances.
func (d *DeploymentParams) validate() error {
for _, meta := range d.Contracts {
if meta.Bin == "" {
return fmt.Errorf("cannot deploy contract %s: deployer code missing from metadata", meta.ID)
}
}
return nil
}
// DeploymentResult contains information about the result of a pending
// deployment made by LinkAndDeploy.
type DeploymentResult struct {
// Map of contract MetaData.ID to pending deployment transaction
Txs map[string]*types.Transaction
// Map of contract MetaData.ID to the address where it will be deployed
Addresses map[string]common.Address
}
// DeployFn deploys a contract given a deployer and optional input. It returns
// the address and a pending transaction, or an error if the deployment failed.
type DeployFn func(input, deployer []byte) (common.Address, *types.Transaction, error)
// depTreeDeployer is responsible for taking a dependency, deploying-and-linking
// its components in the proper order. A depTreeDeployer cannot be used after
// calling LinkAndDeploy other than to retrieve the deployment result.
type depTreeDeployer struct {
deployedAddrs map[string]common.Address
deployerTxs map[string]*types.Transaction
inputs map[string][]byte // map of the root contract pattern to the constructor input (if there is any)
deployFn DeployFn
}
func newDepTreeDeployer(deployParams *DeploymentParams, deployFn DeployFn) *depTreeDeployer {
deployedAddrs := maps.Clone(deployParams.Overrides)
if deployedAddrs == nil {
deployedAddrs = make(map[string]common.Address)
}
inputs := deployParams.Inputs
if inputs == nil {
inputs = make(map[string][]byte)
}
return &depTreeDeployer{
deployFn: deployFn,
deployedAddrs: deployedAddrs,
deployerTxs: make(map[string]*types.Transaction),
inputs: inputs,
}
}
// linkAndDeploy deploys a contract and it's dependencies. Because libraries
// can in-turn have their own library dependencies, linkAndDeploy performs
// deployment recursively (deepest-dependency first). The address of the
// pending contract deployment for the top-level contract is returned.
func (d *depTreeDeployer) linkAndDeploy(metadata *MetaData) (common.Address, error) {
// Don't re-deploy aliased or previously-deployed contracts
if addr, ok := d.deployedAddrs[metadata.ID]; ok {
return addr, nil
}
// If this contract/library depends on other libraries deploy them
// (and their dependencies) first
deployerCode := metadata.Bin
for _, dep := range metadata.Deps {
addr, err := d.linkAndDeploy(dep)
if err != nil {
return common.Address{}, err
}
// Link their deployed addresses into the bytecode to produce
deployerCode = strings.ReplaceAll(deployerCode, "__$"+dep.ID+"$__", strings.ToLower(addr.String()[2:]))
}
// Finally, deploy the top-level contract.
code, err := hex.DecodeString(deployerCode[2:])
if err != nil {
panic(fmt.Sprintf("error decoding contract deployer hex %s:\n%v", deployerCode[2:], err))
}
addr, tx, err := d.deployFn(d.inputs[metadata.ID], code)
if err != nil {
return common.Address{}, err
}
d.deployedAddrs[metadata.ID] = addr
d.deployerTxs[metadata.ID] = tx
return addr, nil
}
// result returns a DeploymentResult instance referencing contracts deployed
// and not including any overrides specified for this deployment.
func (d *depTreeDeployer) result() *DeploymentResult {
// filter the override addresses from the deployed address set.
for pattern := range d.deployedAddrs {
if _, ok := d.deployerTxs[pattern]; !ok {
delete(d.deployedAddrs, pattern)
}
}
return &DeploymentResult{
Txs: d.deployerTxs,
Addresses: d.deployedAddrs,
}
}
// LinkAndDeploy performs the contract deployment specified by params using the
// provided DeployFn to create, sign and submit transactions.
//
// Contracts can depend on libraries, which in-turn can have their own library
// dependencies. Therefore, LinkAndDeploy performs the deployment recursively,
// starting with libraries (and contracts) that don't have dependencies, and
// progressing through the contracts that depend upon them.
//
// If an error is encountered, the returned DeploymentResult only contains
// entries for the contracts whose deployment submission succeeded.
//
// LinkAndDeploy performs creation and submission of creation transactions,
// but does not ensure that the contracts are included in the chain.
func LinkAndDeploy(params *DeploymentParams, deploy DeployFn) (*DeploymentResult, error) {
if err := params.validate(); err != nil {
return nil, err
}
deployer := newDepTreeDeployer(params, deploy)
for _, contract := range params.Contracts {
if _, err := deployer.linkAndDeploy(contract); err != nil {
return deployer.result(), err
}
}
return deployer.result(), nil
}

View file

@ -0,0 +1,370 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind
import (
"fmt"
"regexp"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/exp/rand"
)
type linkTestCase struct {
// map of pattern to unlinked bytecode (for the purposes of tests just contains the patterns of its dependencies)
libCodes map[string]string
contractCodes map[string]string
overrides map[string]common.Address
}
func copyMetaData(m *MetaData) *MetaData {
m.mu.Lock()
defer m.mu.Unlock()
var deps []*MetaData
if len(m.Deps) > 0 {
for _, dep := range m.Deps {
deps = append(deps, copyMetaData(dep))
}
}
return &MetaData{
Bin: m.Bin,
ABI: m.ABI,
Deps: deps,
ID: m.ID,
parsedABI: m.parsedABI,
}
}
func makeLinkTestCase(input map[rune][]rune, overrides map[rune]common.Address) *linkTestCase {
codes := make(map[string]string)
libCodes := make(map[string]string)
contractCodes := make(map[string]string)
inputMap := make(map[rune]map[rune]struct{})
// set of solidity patterns for all contracts that are known to be libraries
libs := make(map[string]struct{})
// map of test contract id (rune) to the solidity library pattern (hash of that rune)
patternMap := map[rune]string{}
for contract, deps := range input {
inputMap[contract] = make(map[rune]struct{})
if _, ok := patternMap[contract]; !ok {
patternMap[contract] = crypto.Keccak256Hash([]byte(string(contract))).String()[2:36]
}
for _, dep := range deps {
if _, ok := patternMap[dep]; !ok {
patternMap[dep] = crypto.Keccak256Hash([]byte(string(dep))).String()[2:36]
}
codes[patternMap[contract]] = codes[patternMap[contract]] + fmt.Sprintf("__$%s$__", patternMap[dep])
inputMap[contract][dep] = struct{}{}
libs[patternMap[dep]] = struct{}{}
}
}
overridesPatterns := make(map[string]common.Address)
for contractId, overrideAddr := range overrides {
pattern := crypto.Keccak256Hash([]byte(string(contractId))).String()[2:36]
overridesPatterns[pattern] = overrideAddr
}
for _, pattern := range patternMap {
if _, ok := libs[pattern]; ok {
// if the library didn't depend on others, give it some dummy code to not bork deployment logic down-the-line
if len(codes[pattern]) == 0 {
libCodes[pattern] = "ff"
} else {
libCodes[pattern] = codes[pattern]
}
} else {
contractCodes[pattern] = codes[pattern]
}
}
return &linkTestCase{
libCodes,
contractCodes,
overridesPatterns,
}
}
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
type linkTestCaseInput struct {
input map[rune][]rune
overrides map[rune]struct{}
expectDeployed map[rune]struct{}
}
// linkDeps will return a set of root dependencies and their sub-dependencies connected via the Deps field
func linkDeps(deps map[string]*MetaData) []*MetaData {
roots := make(map[string]struct{})
for pattern := range deps {
roots[pattern] = struct{}{}
}
connectedDeps := make(map[string]*MetaData)
for pattern, dep := range deps {
connectedDeps[pattern] = internalLinkDeps(dep, deps, &roots)
}
var rootMetadatas []*MetaData
for pattern := range roots {
dep := connectedDeps[pattern]
rootMetadatas = append(rootMetadatas, dep)
}
return rootMetadatas
}
// internalLinkDeps is the internal recursing logic of linkDeps:
// It links the contract referred to by MetaData given the depMap (map of solidity
// link pattern to contract metadata object), deleting contract entries from the
// roots map if they were referenced as dependencies. It returns a new MetaData
// object which is the linked version of metadata parameter.
func internalLinkDeps(metadata *MetaData, depMap map[string]*MetaData, roots *map[string]struct{}) *MetaData {
linked := copyMetaData(metadata)
depPatterns := parseLibraryDeps(metadata.Bin)
for _, pattern := range depPatterns {
delete(*roots, pattern)
connectedDep := internalLinkDeps(depMap[pattern], depMap, roots)
linked.Deps = append(linked.Deps, connectedDep)
}
return linked
}
func testLinkCase(tcInput linkTestCaseInput) error {
var (
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
overridesAddrs = make(map[common.Address]struct{})
overrideAddrs = make(map[rune]common.Address)
)
// generate deterministic addresses for the override set.
rng := rand.New(rand.NewSource(42))
for contract := range tcInput.overrides {
var addr common.Address
rng.Read(addr[:])
overrideAddrs[contract] = addr
overridesAddrs[addr] = struct{}{}
}
tc := makeLinkTestCase(tcInput.input, overrideAddrs)
allContracts := make(map[rune]struct{})
for contract, deps := range tcInput.input {
allContracts[contract] = struct{}{}
for _, dep := range deps {
allContracts[dep] = struct{}{}
}
}
var testAddrNonce uint64
mockDeploy := func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
contractAddr := crypto.CreateAddress(testAddr, testAddrNonce)
testAddrNonce++
if len(deployer) >= 20 {
// assert that this contract only references libs that are known to be deployed or in the override set
for i := 0; i < len(deployer); i += 20 {
var dep common.Address
dep.SetBytes(deployer[i : i+20])
if _, ok := overridesAddrs[dep]; !ok {
return common.Address{}, nil, fmt.Errorf("reference to dependent contract that has not yet been deployed: %x\n", dep)
}
}
}
overridesAddrs[contractAddr] = struct{}{}
// we don't care about the txs themselves for the sake of the linking tests. so we can return nil for them in the mock deployer
return contractAddr, nil, nil
}
contracts := make(map[string]*MetaData)
overrides := make(map[string]common.Address)
for pattern, bin := range tc.contractCodes {
contracts[pattern] = &MetaData{ID: pattern, Bin: "0x" + bin}
}
for pattern, bin := range tc.libCodes {
contracts[pattern] = &MetaData{
Bin: "0x" + bin,
ID: pattern,
}
}
contractsList := linkDeps(contracts)
for pattern, override := range tc.overrides {
overrides[pattern] = override
}
deployParams := &DeploymentParams{
Contracts: contractsList,
Overrides: overrides,
}
res, err := LinkAndDeploy(deployParams, mockDeploy)
if err != nil {
return err
}
if len(res.Txs) != len(tcInput.expectDeployed) {
return fmt.Errorf("got %d deployed contracts. expected %d.\n", len(res.Addresses), len(tcInput.expectDeployed))
}
for contract := range tcInput.expectDeployed {
pattern := crypto.Keccak256Hash([]byte(string(contract))).String()[2:36]
if _, ok := res.Addresses[pattern]; !ok {
return fmt.Errorf("expected contract %s was not deployed\n", string(contract))
}
}
return nil
}
func TestContractLinking(t *testing.T) {
for i, tc := range []linkTestCaseInput{
// test simple contract without any dependencies or overrides
{
map[rune][]rune{
'a': {}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}},
},
// test deployment of a contract that depends on somes libraries.
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}},
},
// test deployment of a contract that depends on some libraries,
// one of which has its own library dependencies.
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'e': {'f', 'g', 'h', 'i'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}},
},
// test single contract only without deps
{
map[rune][]rune{
'a': {}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {},
},
},
// test that libraries at different levels of the tree can share deps,
// and that these shared deps will only be deployed once.
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'e': {'f', 'g', 'h', 'i', 'm'},
'i': {'j', 'k', 'l', 'm'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}, 'j': {}, 'k': {}, 'l': {}, 'm': {},
},
},
// test two contracts can be deployed which don't share deps
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'h', 'i', 'j'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}, 'j': {},
},
},
// test two contracts can be deployed which share deps
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'c', 'd', 'h'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {},
},
},
// test one contract with overrides for all lib deps
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'}},
map[rune]struct{}{'b': {}, 'c': {}, 'd': {}, 'e': {}},
map[rune]struct{}{
'a': {}},
},
// test one contract with overrides for some lib deps
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c'}},
map[rune]struct{}{'b': {}, 'c': {}},
map[rune]struct{}{
'a': {}},
},
// test deployment of a contract with overrides
linkTestCaseInput{
map[rune][]rune{
'a': {}},
map[rune]struct{}{'a': {}},
map[rune]struct{}{},
},
// two contracts ('a' and 'f') share some dependencies. contract 'a' is marked as an override. expect that any of
// its depdencies that aren't shared with 'f' are not deployed.
linkTestCaseInput{map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'c', 'd', 'h'}},
map[rune]struct{}{'a': {}},
map[rune]struct{}{
'f': {}, 'g': {}, 'c': {}, 'd': {}, 'h': {}},
},
// test nested libraries that share deps at different levels of the tree... with override.
// same condition as above test: no sub-dependencies of
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'e': {'f', 'g', 'h', 'i', 'm'},
'i': {'j', 'k', 'l', 'm'},
'l': {'n', 'o', 'p'}},
map[rune]struct{}{
'i': {},
},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'm': {}},
},
} {
if err := testLinkCase(tc); err != nil {
t.Fatalf("test case %d failed: %v", i, err)
}
}
}
func parseLibraryDeps(unlinkedCode string) (res []string) {
reMatchSpecificPattern, err := regexp.Compile(`__\$([a-f0-9]+)\$__`)
if err != nil {
panic(err)
}
for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(unlinkedCode, -1) {
res = append(res, match[1])
}
return res
}

View file

@ -0,0 +1,102 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind_test
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi/abigen"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/crypto"
)
// Run go generate to recreate the test bindings.
//
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/db/combined-abi.json -type DBStats -pkg db -out internal/contracts/db/bindings.go
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/events/combined-abi.json -type C -pkg events -out internal/contracts/events/bindings.go
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/nested_libraries/combined-abi.json -type C1 -pkg nested_libraries -out internal/contracts/nested_libraries/bindings.go
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/solc_errors/combined-abi.json -type C -pkg solc_errors -out internal/contracts/solc_errors/bindings.go
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/uint256arrayreturn/combined-abi.json -type C -pkg uint256arrayreturn -out internal/contracts/uint256arrayreturn/bindings.go
// TestBindingGeneration tests that re-running generation of bindings does not result in
// mutations to the binding code.
func TestBindingGeneration(t *testing.T) {
matches, _ := filepath.Glob("internal/contracts/*")
var dirs []string
for _, match := range matches {
f, _ := os.Stat(match)
if f.IsDir() {
dirs = append(dirs, f.Name())
}
}
for _, dir := range dirs {
var (
abis []string
bins []string
types []string
libs = make(map[string]string)
)
basePath := filepath.Join("internal/contracts", dir)
combinedJsonPath := filepath.Join(basePath, "combined-abi.json")
abiBytes, err := os.ReadFile(combinedJsonPath)
if err != nil {
t.Fatalf("error trying to read file %s: %v", combinedJsonPath, err)
}
contracts, err := compiler.ParseCombinedJSON(abiBytes, "", "", "", "")
if err != nil {
t.Fatalf("Failed to read contract information from json output: %v", err)
}
for name, contract := range contracts {
// fully qualified name is of the form <solFilePath>:<type>
nameParts := strings.Split(name, ":")
typeName := nameParts[len(nameParts)-1]
abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
if err != nil {
utils.Fatalf("Failed to parse ABIs from compiler output: %v", err)
}
abis = append(abis, string(abi))
bins = append(bins, contract.Code)
types = append(types, typeName)
// Derive the library placeholder which is a 34 character prefix of the
// hex encoding of the keccak256 hash of the fully qualified library name.
// Note that the fully qualified library name is the path of its source
// file and the library name separated by ":".
libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x
libs[libPattern] = typeName
}
code, err := abigen.BindV2(types, abis, bins, dir, libs, make(map[string]string))
if err != nil {
t.Fatalf("error creating bindings for package %s: %v", dir, err)
}
existingBindings, err := os.ReadFile(filepath.Join(basePath, "bindings.go"))
if err != nil {
t.Fatalf("ReadFile returned error: %v", err)
}
if code != string(existingBindings) {
t.Fatalf("code mismatch for %s", dir)
}
}
}

View file

@ -0,0 +1,341 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package db
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// DBStats is an auto generated low-level Go binding around an user-defined struct.
type DBStats struct {
Gets *big.Int
Inserts *big.Int
Mods *big.Int
}
// DBMetaData contains all meta data concerning the DB contract.
var DBMetaData = bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"key\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"Insert\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"key\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"KeyedInsert\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"k\",\"type\":\"uint256\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNamedStatParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gets\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inserts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mods\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatsStruct\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gets\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inserts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mods\",\"type\":\"uint256\"}],\"internalType\":\"structDB.Stats\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"k\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"}],\"name\":\"insert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
ID: "253cc2574e2f8b5e909644530e4934f6ac",
Bin: "0x60806040525f5f553480156011575f5ffd5b5060405180606001604052805f81526020015f81526020015f81525060035f820151815f015560208201518160010155604082015181600201559050506105f78061005b5f395ff3fe60806040526004361061004d575f3560e01c80631d834a1b146100cb5780636fcb9c70146101075780639507d39a14610133578063e369ba3b1461016f578063ee8161e01461019b5761006a565b3661006a57345f5f82825461006291906103eb565b925050819055005b348015610075575f5ffd5b505f36606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050509050915050805190602001f35b3480156100d6575f5ffd5b506100f160048036038101906100ec919061044c565b6101c5565b6040516100fe9190610499565b60405180910390f35b348015610112575f5ffd5b5061011b6102ef565b60405161012a939291906104b2565b60405180910390f35b34801561013e575f5ffd5b50610159600480360381019061015491906104e7565b61030e565b6040516101669190610499565b60405180910390f35b34801561017a575f5ffd5b50610183610341565b604051610192939291906104b2565b60405180910390f35b3480156101a6575f5ffd5b506101af610360565b6040516101bc9190610561565b60405180910390f35b5f5f82036101da5760028054905090506102e9565b5f60015f8581526020019081526020015f20540361023757600283908060018154018082558091505060019003905f5260205f20015f909190919091505560036001015f81548092919061022d9061057a565b9190505550610252565b60036002015f81548092919061024c9061057a565b91905055505b8160015f8581526020019081526020015f20819055507f8b39ff47dca36ab5b8b80845238af53aa579625ac7fb173dc09376adada4176983836002805490506040516102a0939291906104b2565b60405180910390a1827f40bed843c6c5f72002f9b469cf4c1ee9f7fb1eb48f091c1267970f98522ac02d836040516102d89190610499565b60405180910390a260028054905090505b92915050565b5f5f5f60035f0154600360010154600360020154925092509250909192565b5f60035f015f8154809291906103239061057a565b919050555060015f8381526020019081526020015f20549050919050565b5f5f5f60035f0154600360010154600360020154925092509250909192565b610368610397565b60036040518060600160405290815f820154815260200160018201548152602001600282015481525050905090565b60405180606001604052805f81526020015f81526020015f81525090565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6103f5826103b5565b9150610400836103b5565b9250828201905080821115610418576104176103be565b5b92915050565b5f5ffd5b61042b816103b5565b8114610435575f5ffd5b50565b5f8135905061044681610422565b92915050565b5f5f604083850312156104625761046161041e565b5b5f61046f85828601610438565b925050602061048085828601610438565b9150509250929050565b610493816103b5565b82525050565b5f6020820190506104ac5f83018461048a565b92915050565b5f6060820190506104c55f83018661048a565b6104d2602083018561048a565b6104df604083018461048a565b949350505050565b5f602082840312156104fc576104fb61041e565b5b5f61050984828501610438565b91505092915050565b61051b816103b5565b82525050565b606082015f8201516105355f850182610512565b5060208201516105486020850182610512565b50604082015161055b6040850182610512565b50505050565b5f6060820190506105745f830184610521565b92915050565b5f610584826103b5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036105b6576105b56103be565b5b60018201905091905056fea264697066735822122063e58431f2afdc667f8e687d3e6a99085a93c1fd3ce40b218463b8ddd3cc093664736f6c634300081c0033",
}
// DB is an auto generated Go binding around an Ethereum contract.
type DB struct {
abi abi.ABI
}
// NewDB creates a new instance of DB.
func NewDB() *DB {
parsed, err := DBMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &DB{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *DB) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackGet is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x9507d39a. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function get(uint256 k) returns(uint256)
func (dB *DB) PackGet(k *big.Int) []byte {
enc, err := dB.abi.Pack("get", k)
if err != nil {
panic(err)
}
return enc
}
// TryPackGet is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x9507d39a. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function get(uint256 k) returns(uint256)
func (dB *DB) TryPackGet(k *big.Int) ([]byte, error) {
return dB.abi.Pack("get", k)
}
// UnpackGet is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x9507d39a.
//
// Solidity: function get(uint256 k) returns(uint256)
func (dB *DB) UnpackGet(data []byte) (*big.Int, error) {
out, err := dB.abi.Unpack("get", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// PackGetNamedStatParams is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe369ba3b. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods)
func (dB *DB) PackGetNamedStatParams() []byte {
enc, err := dB.abi.Pack("getNamedStatParams")
if err != nil {
panic(err)
}
return enc
}
// TryPackGetNamedStatParams is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe369ba3b. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods)
func (dB *DB) TryPackGetNamedStatParams() ([]byte, error) {
return dB.abi.Pack("getNamedStatParams")
}
// GetNamedStatParamsOutput serves as a container for the return parameters of contract
// method GetNamedStatParams.
type GetNamedStatParamsOutput struct {
Gets *big.Int
Inserts *big.Int
Mods *big.Int
}
// UnpackGetNamedStatParams is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xe369ba3b.
//
// Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods)
func (dB *DB) UnpackGetNamedStatParams(data []byte) (GetNamedStatParamsOutput, error) {
out, err := dB.abi.Unpack("getNamedStatParams", data)
outstruct := new(GetNamedStatParamsOutput)
if err != nil {
return *outstruct, err
}
outstruct.Gets = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Inserts = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
outstruct.Mods = abi.ConvertType(out[2], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackGetStatParams is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6fcb9c70. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function getStatParams() view returns(uint256, uint256, uint256)
func (dB *DB) PackGetStatParams() []byte {
enc, err := dB.abi.Pack("getStatParams")
if err != nil {
panic(err)
}
return enc
}
// TryPackGetStatParams is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x6fcb9c70. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function getStatParams() view returns(uint256, uint256, uint256)
func (dB *DB) TryPackGetStatParams() ([]byte, error) {
return dB.abi.Pack("getStatParams")
}
// GetStatParamsOutput serves as a container for the return parameters of contract
// method GetStatParams.
type GetStatParamsOutput struct {
Arg0 *big.Int
Arg1 *big.Int
Arg2 *big.Int
}
// UnpackGetStatParams is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6fcb9c70.
//
// Solidity: function getStatParams() view returns(uint256, uint256, uint256)
func (dB *DB) UnpackGetStatParams(data []byte) (GetStatParamsOutput, error) {
out, err := dB.abi.Unpack("getStatParams", data)
outstruct := new(GetStatParamsOutput)
if err != nil {
return *outstruct, err
}
outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
outstruct.Arg2 = abi.ConvertType(out[2], new(big.Int)).(*big.Int)
return *outstruct, nil
}
// PackGetStatsStruct is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xee8161e0. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function getStatsStruct() view returns((uint256,uint256,uint256))
func (dB *DB) PackGetStatsStruct() []byte {
enc, err := dB.abi.Pack("getStatsStruct")
if err != nil {
panic(err)
}
return enc
}
// TryPackGetStatsStruct is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xee8161e0. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function getStatsStruct() view returns((uint256,uint256,uint256))
func (dB *DB) TryPackGetStatsStruct() ([]byte, error) {
return dB.abi.Pack("getStatsStruct")
}
// UnpackGetStatsStruct is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xee8161e0.
//
// Solidity: function getStatsStruct() view returns((uint256,uint256,uint256))
func (dB *DB) UnpackGetStatsStruct(data []byte) (DBStats, error) {
out, err := dB.abi.Unpack("getStatsStruct", data)
if err != nil {
return *new(DBStats), err
}
out0 := *abi.ConvertType(out[0], new(DBStats)).(*DBStats)
return out0, nil
}
// PackInsert is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x1d834a1b. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function insert(uint256 k, uint256 v) returns(uint256)
func (dB *DB) PackInsert(k *big.Int, v *big.Int) []byte {
enc, err := dB.abi.Pack("insert", k, v)
if err != nil {
panic(err)
}
return enc
}
// TryPackInsert is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x1d834a1b. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function insert(uint256 k, uint256 v) returns(uint256)
func (dB *DB) TryPackInsert(k *big.Int, v *big.Int) ([]byte, error) {
return dB.abi.Pack("insert", k, v)
}
// UnpackInsert is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x1d834a1b.
//
// Solidity: function insert(uint256 k, uint256 v) returns(uint256)
func (dB *DB) UnpackInsert(data []byte) (*big.Int, error) {
out, err := dB.abi.Unpack("insert", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// DBInsert represents a Insert event raised by the DB contract.
type DBInsert struct {
Key *big.Int
Value *big.Int
Length *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const DBInsertEventName = "Insert"
// ContractEventName returns the user-defined event name.
func (DBInsert) ContractEventName() string {
return DBInsertEventName
}
// UnpackInsertEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event Insert(uint256 key, uint256 value, uint256 length)
func (dB *DB) UnpackInsertEvent(log *types.Log) (*DBInsert, error) {
event := "Insert"
if len(log.Topics) == 0 || log.Topics[0] != dB.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(DBInsert)
if len(log.Data) > 0 {
if err := dB.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range dB.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// DBKeyedInsert represents a KeyedInsert event raised by the DB contract.
type DBKeyedInsert struct {
Key *big.Int
Value *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const DBKeyedInsertEventName = "KeyedInsert"
// ContractEventName returns the user-defined event name.
func (DBKeyedInsert) ContractEventName() string {
return DBKeyedInsertEventName
}
// UnpackKeyedInsertEvent is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event KeyedInsert(uint256 indexed key, uint256 value)
func (dB *DB) UnpackKeyedInsertEvent(log *types.Log) (*DBKeyedInsert, error) {
event := "KeyedInsert"
if len(log.Topics) == 0 || log.Topics[0] != dB.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(DBKeyedInsert)
if len(log.Data) > 0 {
if err := dB.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range dB.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract DB {
uint balance = 0;
mapping(uint => uint) private _store;
uint[] private _keys;
struct Stats {
uint gets;
uint inserts;
uint mods; // modifications
}
Stats _stats;
event KeyedInsert(uint indexed key, uint value);
event Insert(uint key, uint value, uint length);
constructor() {
_stats = Stats(0, 0, 0);
}
// insert adds a key value to the store, returning the new length of the store.
function insert(uint k, uint v) external returns (uint) {
// No need to store 0 values
if (v == 0) {
return _keys.length;
}
// Check if a key is being overriden
if (_store[k] == 0) {
_keys.push(k);
_stats.inserts++;
} else {
_stats.mods++;
}
_store[k] = v;
emit Insert(k, v, _keys.length);
emit KeyedInsert(k, v);
return _keys.length;
}
function get(uint k) public returns (uint) {
_stats.gets++;
return _store[k];
}
function getStatParams() public view returns (uint, uint, uint) {
return (_stats.gets, _stats.inserts, _stats.mods);
}
function getNamedStatParams() public view returns (uint gets, uint inserts, uint mods) {
return (_stats.gets, _stats.inserts, _stats.mods);
}
function getStatsStruct() public view returns (Stats memory) {
return _stats;
}
receive() external payable {
balance += msg.value;
}
fallback(bytes calldata _input) external returns (bytes memory _output) {
_output = _input;
}
}

View file

@ -0,0 +1,180 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package events
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// CMetaData contains all meta data concerning the C contract.
var CMetaData = bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"basic1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"basic2\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EmitMulti\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EmitOne\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
ID: "55ef3c19a0ab1c1845f9e347540c1e51f5",
Bin: "0x6080604052348015600e575f5ffd5b506101a08061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063cb49374914610038578063e8e49a7114610042575b5f5ffd5b61004061004c565b005b61004a6100fd565b005b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161007e9190610151565b60405180910390a260037f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd20760046040516100b89190610151565b60405180910390a25f15157f3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e60016040516100f39190610151565b60405180910390a2565b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161012f9190610151565b60405180910390a2565b5f819050919050565b61014b81610139565b82525050565b5f6020820190506101645f830184610142565b9291505056fea26469706673582212207331c79de16a73a1639c4c4b3489ea78a3ed35fe62a178824f586df12672ac0564736f6c634300081c0033",
}
// C is an auto generated Go binding around an Ethereum contract.
type C struct {
abi abi.ABI
}
// NewC creates a new instance of C.
func NewC() *C {
parsed, err := CMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &C{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *C) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackEmitMulti is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xcb493749. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function EmitMulti() returns()
func (c *C) PackEmitMulti() []byte {
enc, err := c.abi.Pack("EmitMulti")
if err != nil {
panic(err)
}
return enc
}
// TryPackEmitMulti is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xcb493749. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function EmitMulti() returns()
func (c *C) TryPackEmitMulti() ([]byte, error) {
return c.abi.Pack("EmitMulti")
}
// PackEmitOne is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe8e49a71. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function EmitOne() returns()
func (c *C) PackEmitOne() []byte {
enc, err := c.abi.Pack("EmitOne")
if err != nil {
panic(err)
}
return enc
}
// TryPackEmitOne is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xe8e49a71. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function EmitOne() returns()
func (c *C) TryPackEmitOne() ([]byte, error) {
return c.abi.Pack("EmitOne")
}
// CBasic1 represents a basic1 event raised by the C contract.
type CBasic1 struct {
Id *big.Int
Data *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const CBasic1EventName = "basic1"
// ContractEventName returns the user-defined event name.
func (CBasic1) ContractEventName() string {
return CBasic1EventName
}
// UnpackBasic1Event is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event basic1(uint256 indexed id, uint256 data)
func (c *C) UnpackBasic1Event(log *types.Log) (*CBasic1, error) {
event := "basic1"
if len(log.Topics) == 0 || log.Topics[0] != c.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(CBasic1)
if len(log.Data) > 0 {
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range c.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}
// CBasic2 represents a basic2 event raised by the C contract.
type CBasic2 struct {
Flag bool
Data *big.Int
Raw *types.Log // Blockchain specific contextual infos
}
const CBasic2EventName = "basic2"
// ContractEventName returns the user-defined event name.
func (CBasic2) ContractEventName() string {
return CBasic2EventName
}
// UnpackBasic2Event is the Go binding that unpacks the event data emitted
// by contract.
//
// Solidity: event basic2(bool indexed flag, uint256 data)
func (c *C) UnpackBasic2Event(log *types.Log) (*CBasic2, error) {
event := "basic2"
if len(log.Topics) == 0 || log.Topics[0] != c.abi.Events[event].ID {
return nil, errors.New("event signature mismatch")
}
out := new(CBasic2)
if len(log.Data) > 0 {
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return nil, err
}
}
var indexed abi.Arguments
for _, arg := range c.abi.Events[event].Inputs {
if arg.Indexed {
indexed = append(indexed, arg)
}
}
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
return nil, err
}
out.Raw = log
return out, nil
}

View file

@ -0,0 +1 @@
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"basic1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"flag","type":"bool"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"basic2","type":"event"},{"inputs":[],"name":"EmitMulti","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"EmitOne","outputs":[],"stateMutability":"nonpayable","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101a08061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063cb49374914610038578063e8e49a7114610042575b5f5ffd5b61004061004c565b005b61004a6100fd565b005b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161007e9190610151565b60405180910390a260037f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd20760046040516100b89190610151565b60405180910390a25f15157f3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e60016040516100f39190610151565b60405180910390a2565b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161012f9190610151565b60405180910390a2565b5f819050919050565b61014b81610139565b82525050565b5f6020820190506101645f830184610142565b9291505056fea26469706673582212207331c79de16a73a1639c4c4b3489ea78a3ed35fe62a178824f586df12672ac0564736f6c634300081c0033"}},"version":"0.8.28+commit.7893614a.Darwin.appleclang"}

View file

@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract C {
event basic1(
uint256 indexed id,
uint256 data
);
event basic2(
bool indexed flag,
uint256 data
);
function EmitOne() public {
emit basic1(
uint256(1),
uint256(2));
}
// emit multiple events, different types
function EmitMulti() public {
emit basic1(
uint256(1),
uint256(2));
emit basic1(
uint256(3),
uint256(4));
emit basic2(
false,
uint256(1));
}
constructor() {
// do something with these
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,566 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package nested_libraries
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// C1MetaData contains all meta data concerning the C1 contract.
var C1MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"v2\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"res\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "ae26158f1824f3918bd66724ee8b6eb7c9",
Bin: "0x6080604052348015600e575f5ffd5b506040516103983803806103988339818101604052810190602e91906066565b5050609d565b5f5ffd5b5f819050919050565b6048816038565b81146051575f5ffd5b50565b5f815190506060816041565b92915050565b5f5f6040838503121560795760786034565b5b5f6084858286016054565b92505060206093858286016054565b9150509250929050565b6102ee806100aa5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80632ad112721461002d575b5f5ffd5b6100476004803603810190610042919061019e565b61005d565b60405161005491906101d8565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad112725f6040518263ffffffff1660e01b81526004016100979190610200565b602060405180830381865af41580156100b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100d6919061022d565b73__$5f33a1fab8ea7d932b4bc8c5e7dcd90bc2$__632ad11272856040518263ffffffff1660e01b815260040161010d9190610200565b602060405180830381865af4158015610128573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014c919061022d565b6101569190610285565b6101609190610285565b9050919050565b5f5ffd5b5f819050919050565b61017d8161016b565b8114610187575f5ffd5b50565b5f8135905061019881610174565b92915050565b5f602082840312156101b3576101b2610167565b5b5f6101c08482850161018a565b91505092915050565b6101d28161016b565b82525050565b5f6020820190506101eb5f8301846101c9565b92915050565b6101fa8161016b565b82525050565b5f6020820190506102135f8301846101f1565b92915050565b5f8151905061022781610174565b92915050565b5f6020828403121561024257610241610167565b5b5f61024f84828501610219565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61028f8261016b565b915061029a8361016b565b92508282019050808211156102b2576102b1610258565b5b9291505056fea26469706673582212205d4715a8d20a3a0a43113e268ec8868b3c3ce24f7cbdb8735b4eeeebf0b5565164736f6c634300081c0033",
Deps: []*bind.MetaData{
&L1MetaData,
&L4MetaData,
},
}
// C1 is an auto generated Go binding around an Ethereum contract.
type C1 struct {
abi abi.ABI
}
// NewC1 creates a new instance of C1.
func NewC1() *C1 {
parsed, err := C1MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &C1{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *C1) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackConstructor is the Go binding used to pack the parameters required for
// contract deployment.
//
// Solidity: constructor(uint256 v1, uint256 v2) returns()
func (c1 *C1) PackConstructor(v1 *big.Int, v2 *big.Int) []byte {
enc, err := c1.abi.Pack("", v1, v2)
if err != nil {
panic(err)
}
return enc
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c1 *C1) PackDo(val *big.Int) []byte {
enc, err := c1.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c1 *C1) TryPackDo(val *big.Int) ([]byte, error) {
return c1.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c1 *C1) UnpackDo(data []byte) (*big.Int, error) {
out, err := c1.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// C2MetaData contains all meta data concerning the C2 contract.
var C2MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"v2\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"res\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "78ef2840de5b706112ca2dbfa765501a89",
Bin: "0x6080604052348015600e575f5ffd5b506040516103983803806103988339818101604052810190602e91906066565b5050609d565b5f5ffd5b5f819050919050565b6048816038565b81146051575f5ffd5b50565b5f815190506060816041565b92915050565b5f5f6040838503121560795760786034565b5b5f6084858286016054565b92505060206093858286016054565b9150509250929050565b6102ee806100aa5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80632ad112721461002d575b5f5ffd5b6100476004803603810190610042919061019e565b61005d565b60405161005491906101d8565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad112725f6040518263ffffffff1660e01b81526004016100979190610200565b602060405180830381865af41580156100b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100d6919061022d565b73__$6070639404c39b5667691bb1f9177e1eac$__632ad11272856040518263ffffffff1660e01b815260040161010d9190610200565b602060405180830381865af4158015610128573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014c919061022d565b6101569190610285565b6101609190610285565b9050919050565b5f5ffd5b5f819050919050565b61017d8161016b565b8114610187575f5ffd5b50565b5f8135905061019881610174565b92915050565b5f602082840312156101b3576101b2610167565b5b5f6101c08482850161018a565b91505092915050565b6101d28161016b565b82525050565b5f6020820190506101eb5f8301846101c9565b92915050565b6101fa8161016b565b82525050565b5f6020820190506102135f8301846101f1565b92915050565b5f8151905061022781610174565b92915050565b5f6020828403121561024257610241610167565b5b5f61024f84828501610219565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61028f8261016b565b915061029a8361016b565b92508282019050808211156102b2576102b1610258565b5b9291505056fea2646970667358221220dd394981f1e9fefa4d88bac1c4f1da4131779c7d3bd4189958d278e57e96d96f64736f6c634300081c0033",
Deps: []*bind.MetaData{
&L1MetaData,
&L4bMetaData,
},
}
// C2 is an auto generated Go binding around an Ethereum contract.
type C2 struct {
abi abi.ABI
}
// NewC2 creates a new instance of C2.
func NewC2() *C2 {
parsed, err := C2MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &C2{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *C2) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackConstructor is the Go binding used to pack the parameters required for
// contract deployment.
//
// Solidity: constructor(uint256 v1, uint256 v2) returns()
func (c2 *C2) PackConstructor(v1 *big.Int, v2 *big.Int) []byte {
enc, err := c2.abi.Pack("", v1, v2)
if err != nil {
panic(err)
}
return enc
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c2 *C2) PackDo(val *big.Int) []byte {
enc, err := c2.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c2 *C2) TryPackDo(val *big.Int) ([]byte, error) {
return c2.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c2 *C2) UnpackDo(data []byte) (*big.Int, error) {
out, err := c2.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// L1MetaData contains all meta data concerning the L1 contract.
var L1MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "ffc1393672b8ed81d0c8093ffcb0e7fbe8",
Bin: "0x61011c61004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106032575f3560e01c80632ad11272146036575b5f5ffd5b604c600480360381019060489190609c565b6060565b6040516057919060cf565b60405180910390f35b5f60019050919050565b5f5ffd5b5f819050919050565b607e81606e565b81146087575f5ffd5b50565b5f813590506096816077565b92915050565b5f6020828403121560ae5760ad606a565b5b5f60b984828501608a565b91505092915050565b60c981606e565b82525050565b5f60208201905060e05f83018460c2565b9291505056fea26469706673582212200161c5f22d130a2b7ec6cf22e0910e42e32c2881fa4a8a01455f524f63cf218d64736f6c634300081c0033",
}
// L1 is an auto generated Go binding around an Ethereum contract.
type L1 struct {
abi abi.ABI
}
// NewL1 creates a new instance of L1.
func NewL1() *L1 {
parsed, err := L1MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &L1{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *L1) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l1 *L1) PackDo(val *big.Int) []byte {
enc, err := l1.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l1 *L1) TryPackDo(val *big.Int) ([]byte, error) {
return l1.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l1 *L1) UnpackDo(data []byte) (*big.Int, error) {
out, err := l1.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// L2MetaData contains all meta data concerning the L2 contract.
var L2MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "2ce896a6dd38932d354f317286f90bc675",
Bin: "0x61025161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d9190610129565b610068565b60405161005f9190610163565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad11272846040518263ffffffff1660e01b81526004016100a29190610163565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610190565b6100eb91906101e8565b9050919050565b5f5ffd5b5f819050919050565b610108816100f6565b8114610112575f5ffd5b50565b5f81359050610123816100ff565b92915050565b5f6020828403121561013e5761013d6100f2565b5b5f61014b84828501610115565b91505092915050565b61015d816100f6565b82525050565b5f6020820190506101765f830184610154565b92915050565b5f8151905061018a816100ff565b92915050565b5f602082840312156101a5576101a46100f2565b5b5f6101b28482850161017c565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6101f2826100f6565b91506101fd836100f6565b9250828201905080821115610215576102146101bb565b5b9291505056fea264697066735822122026999f96e14b0e279909ca5972343113c358e93a904569409a86866e2064f0fa64736f6c634300081c0033",
Deps: []*bind.MetaData{
&L1MetaData,
},
}
// L2 is an auto generated Go binding around an Ethereum contract.
type L2 struct {
abi abi.ABI
}
// NewL2 creates a new instance of L2.
func NewL2() *L2 {
parsed, err := L2MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &L2{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *L2) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l2 *L2) PackDo(val *big.Int) []byte {
enc, err := l2.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l2 *L2) TryPackDo(val *big.Int) ([]byte, error) {
return l2.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l2 *L2) UnpackDo(data []byte) (*big.Int, error) {
out, err := l2.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// L2bMetaData contains all meta data concerning the L2b contract.
var L2bMetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "fd1474cf57f7ed48491e8bfdfd0d172adf",
Bin: "0x61025161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d9190610129565b610068565b60405161005f9190610163565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad11272846040518263ffffffff1660e01b81526004016100a29190610163565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610190565b6100eb91906101e8565b9050919050565b5f5ffd5b5f819050919050565b610108816100f6565b8114610112575f5ffd5b50565b5f81359050610123816100ff565b92915050565b5f6020828403121561013e5761013d6100f2565b5b5f61014b84828501610115565b91505092915050565b61015d816100f6565b82525050565b5f6020820190506101765f830184610154565b92915050565b5f8151905061018a816100ff565b92915050565b5f602082840312156101a5576101a46100f2565b5b5f6101b28482850161017c565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6101f2826100f6565b91506101fd836100f6565b9250828201905080821115610215576102146101bb565b5b9291505056fea2646970667358221220d6e7078682642d273736fd63baaa28538fe72495816c810fa0e77034de385dc564736f6c634300081c0033",
Deps: []*bind.MetaData{
&L1MetaData,
},
}
// L2b is an auto generated Go binding around an Ethereum contract.
type L2b struct {
abi abi.ABI
}
// NewL2b creates a new instance of L2b.
func NewL2b() *L2b {
parsed, err := L2bMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &L2b{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *L2b) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l2b *L2b) PackDo(val *big.Int) []byte {
enc, err := l2b.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l2b *L2b) TryPackDo(val *big.Int) ([]byte, error) {
return l2b.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l2b *L2b) UnpackDo(data []byte) (*big.Int, error) {
out, err := l2b.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// L3MetaData contains all meta data concerning the L3 contract.
var L3MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "d03b97f5e1a564374023a72ac7d1806773",
Bin: "0x61011c61004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106032575f3560e01c80632ad11272146036575b5f5ffd5b604c600480360381019060489190609c565b6060565b6040516057919060cf565b60405180910390f35b5f60019050919050565b5f5ffd5b5f819050919050565b607e81606e565b81146087575f5ffd5b50565b5f813590506096816077565b92915050565b5f6020828403121560ae5760ad606a565b5b5f60b984828501608a565b91505092915050565b60c981606e565b82525050565b5f60208201905060e05f83018460c2565b9291505056fea264697066735822122094cfcb0ce039318885cc58f6d8e609e6e4bec575e1a046d3d15ea2e01e97241e64736f6c634300081c0033",
}
// L3 is an auto generated Go binding around an Ethereum contract.
type L3 struct {
abi abi.ABI
}
// NewL3 creates a new instance of L3.
func NewL3() *L3 {
parsed, err := L3MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &L3{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *L3) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l3 *L3) PackDo(val *big.Int) []byte {
enc, err := l3.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l3 *L3) TryPackDo(val *big.Int) ([]byte, error) {
return l3.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l3 *L3) UnpackDo(data []byte) (*big.Int, error) {
out, err := l3.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// L4MetaData contains all meta data concerning the L4 contract.
var L4MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "5f33a1fab8ea7d932b4bc8c5e7dcd90bc2",
Bin: "0x6102d161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d91906101a9565b610068565b60405161005f91906101e3565b60405180910390f35b5f600173__$d03b97f5e1a564374023a72ac7d1806773$__632ad11272846040518263ffffffff1660e01b81526004016100a291906101e3565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610210565b73__$2ce896a6dd38932d354f317286f90bc675$__632ad11272856040518263ffffffff1660e01b815260040161011891906101e3565b602060405180830381865af4158015610133573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101579190610210565b6101619190610268565b61016b9190610268565b9050919050565b5f5ffd5b5f819050919050565b61018881610176565b8114610192575f5ffd5b50565b5f813590506101a38161017f565b92915050565b5f602082840312156101be576101bd610172565b5b5f6101cb84828501610195565b91505092915050565b6101dd81610176565b82525050565b5f6020820190506101f65f8301846101d4565b92915050565b5f8151905061020a8161017f565b92915050565b5f6020828403121561022557610224610172565b5b5f610232848285016101fc565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61027282610176565b915061027d83610176565b92508282019050808211156102955761029461023b565b5b9291505056fea2646970667358221220531485f0b9ff78ba5ef06ef345aaddccec3ad15d1460014ccd7c2a58d36d0d4464736f6c634300081c0033",
Deps: []*bind.MetaData{
&L2MetaData,
&L3MetaData,
},
}
// L4 is an auto generated Go binding around an Ethereum contract.
type L4 struct {
abi abi.ABI
}
// NewL4 creates a new instance of L4.
func NewL4() *L4 {
parsed, err := L4MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &L4{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *L4) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l4 *L4) PackDo(val *big.Int) []byte {
enc, err := l4.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l4 *L4) TryPackDo(val *big.Int) ([]byte, error) {
return l4.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l4 *L4) UnpackDo(data []byte) (*big.Int, error) {
out, err := l4.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}
// L4bMetaData contains all meta data concerning the L4b contract.
var L4bMetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "6070639404c39b5667691bb1f9177e1eac",
Bin: "0x61025161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d9190610129565b610068565b60405161005f9190610163565b60405180910390f35b5f600173__$fd1474cf57f7ed48491e8bfdfd0d172adf$__632ad11272846040518263ffffffff1660e01b81526004016100a29190610163565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610190565b6100eb91906101e8565b9050919050565b5f5ffd5b5f819050919050565b610108816100f6565b8114610112575f5ffd5b50565b5f81359050610123816100ff565b92915050565b5f6020828403121561013e5761013d6100f2565b5b5f61014b84828501610115565b91505092915050565b61015d816100f6565b82525050565b5f6020820190506101765f830184610154565b92915050565b5f8151905061018a816100ff565b92915050565b5f602082840312156101a5576101a46100f2565b5b5f6101b28482850161017c565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6101f2826100f6565b91506101fd836100f6565b9250828201905080821115610215576102146101bb565b5b9291505056fea264697066735822122008a2478fd2427f180ace529e137b69337cb655dc21d6426de37054c32e821c6a64736f6c634300081c0033",
Deps: []*bind.MetaData{
&L2bMetaData,
},
}
// L4b is an auto generated Go binding around an Ethereum contract.
type L4b struct {
abi abi.ABI
}
// NewL4b creates a new instance of L4b.
func NewL4b() *L4b {
parsed, err := L4bMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &L4b{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *L4b) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l4b *L4b) PackDo(val *big.Int) []byte {
enc, err := l4b.abi.Pack("Do", val)
if err != nil {
panic(err)
}
return enc
}
// TryPackDo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0x2ad11272. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l4b *L4b) TryPackDo(val *big.Int) ([]byte, error) {
return l4b.abi.Pack("Do", val)
}
// UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272.
//
// Solidity: function Do(uint256 val) pure returns(uint256)
func (l4b *L4b) UnpackDo(data []byte) (*big.Int, error) {
out, err := l4b.abi.Unpack("Do", data)
if err != nil {
return new(big.Int), err
}
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, nil
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
// L1
// \
// L2 L3 L1
// \ / /
// L4 /
// \ /
// C1
//
library L1 {
function Do(uint256 val) public pure returns (uint256) {
return uint256(1);
}
}
library L2 {
function Do(uint256 val) public pure returns (uint256) {
return L1.Do(val) + uint256(1);
}
}
library L3 {
function Do(uint256 val) public pure returns (uint256) {
return uint256(1);
}
}
library L4 {
function Do(uint256 val) public pure returns (uint256) {
return L2.Do(uint256(val)) + L3.Do(uint256(val)) + uint256(1);
}
}
contract C1 {
function Do(uint256 val) public pure returns (uint256 res) {
return L4.Do(uint256(val)) + L1.Do(uint256(0)) + uint256(1);
}
constructor(uint256 v1, uint256 v2) {
// do something with these
}
}
// second contract+libraries: slightly different library deps than V1, but sharing several
// L1
// \
// L2b L3 L1
// \ / /
// L4b /
// \ /
// C2
//
library L4b {
function Do(uint256 val) public pure returns (uint256) {
return L2b.Do(uint256(val)) + uint256(1);
}
}
library L2b {
function Do(uint256 val) public pure returns (uint256) {
return L1.Do(uint256(val)) + uint256(1);
}
}
contract C2 {
function Do(uint256 val) public pure returns (uint256 res) {
return L4b.Do(uint256(val)) + L1.Do(uint256(0)) + uint256(1);
}
constructor(uint256 v1, uint256 v2) {
// do something with these
}
}

View file

@ -0,0 +1,247 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package solc_errors
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// CMetaData contains all meta data concerning the C contract.
var CMetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"arg1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg2\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg3\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"arg4\",\"type\":\"bool\"}],\"name\":\"BadThing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"arg1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg2\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg3\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg4\",\"type\":\"uint256\"}],\"name\":\"BadThing2\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Bar\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Foo\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "55ef3c19a0ab1c1845f9e347540c1e51f5",
Bin: "0x6080604052348015600e575f5ffd5b506101c58061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063b0a378b014610038578063bfb4ebcf14610042575b5f5ffd5b61004061004c565b005b61004a610092565b005b5f6001600260036040517fd233a24f00000000000000000000000000000000000000000000000000000000815260040161008994939291906100ef565b60405180910390fd5b5f600160025f6040517fbb6a82f10000000000000000000000000000000000000000000000000000000081526004016100ce949392919061014c565b60405180910390fd5b5f819050919050565b6100e9816100d7565b82525050565b5f6080820190506101025f8301876100e0565b61010f60208301866100e0565b61011c60408301856100e0565b61012960608301846100e0565b95945050505050565b5f8115159050919050565b61014681610132565b82525050565b5f60808201905061015f5f8301876100e0565b61016c60208301866100e0565b61017960408301856100e0565b610186606083018461013d565b9594505050505056fea26469706673582212206a82b4c28576e4483a81102558271cfefc891cd63b95440dea521185c1ff6a2a64736f6c634300081c0033",
}
// C is an auto generated Go binding around an Ethereum contract.
type C struct {
abi abi.ABI
}
// NewC creates a new instance of C.
func NewC() *C {
parsed, err := CMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &C{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *C) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackBar is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xb0a378b0. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Bar() pure returns()
func (c *C) PackBar() []byte {
enc, err := c.abi.Pack("Bar")
if err != nil {
panic(err)
}
return enc
}
// TryPackBar is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xb0a378b0. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Bar() pure returns()
func (c *C) TryPackBar() ([]byte, error) {
return c.abi.Pack("Bar")
}
// PackFoo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbfb4ebcf. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Foo() pure returns()
func (c *C) PackFoo() []byte {
enc, err := c.abi.Pack("Foo")
if err != nil {
panic(err)
}
return enc
}
// TryPackFoo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbfb4ebcf. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Foo() pure returns()
func (c *C) TryPackFoo() ([]byte, error) {
return c.abi.Pack("Foo")
}
// UnpackError attempts to decode the provided error data using user-defined
// error definitions.
func (c *C) UnpackError(raw []byte) (any, error) {
if bytes.Equal(raw[:4], c.abi.Errors["BadThing"].ID.Bytes()[:4]) {
return c.UnpackBadThingError(raw[4:])
}
if bytes.Equal(raw[:4], c.abi.Errors["BadThing2"].ID.Bytes()[:4]) {
return c.UnpackBadThing2Error(raw[4:])
}
return nil, errors.New("Unknown error")
}
// CBadThing represents a BadThing error raised by the C contract.
type CBadThing struct {
Arg1 *big.Int
Arg2 *big.Int
Arg3 *big.Int
Arg4 bool
}
// ErrorID returns the hash of canonical representation of the error's signature.
//
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
func CBadThingErrorID() common.Hash {
return common.HexToHash("0xbb6a82f123854747ef4381e30e497f934a3854753fec99a69c35c30d4b46714d")
}
// UnpackBadThingError is the Go binding used to decode the provided
// error data into the corresponding Go error struct.
//
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
func (c *C) UnpackBadThingError(raw []byte) (*CBadThing, error) {
out := new(CBadThing)
if err := c.abi.UnpackIntoInterface(out, "BadThing", raw); err != nil {
return nil, err
}
return out, nil
}
// CBadThing2 represents a BadThing2 error raised by the C contract.
type CBadThing2 struct {
Arg1 *big.Int
Arg2 *big.Int
Arg3 *big.Int
Arg4 *big.Int
}
// ErrorID returns the hash of canonical representation of the error's signature.
//
// Solidity: error BadThing2(uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4)
func CBadThing2ErrorID() common.Hash {
return common.HexToHash("0xd233a24f02271fe7c9470e060d0fda6447a142bf12ab31fed7ab65affd546175")
}
// UnpackBadThing2Error is the Go binding used to decode the provided
// error data into the corresponding Go error struct.
//
// Solidity: error BadThing2(uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4)
func (c *C) UnpackBadThing2Error(raw []byte) (*CBadThing2, error) {
out := new(CBadThing2)
if err := c.abi.UnpackIntoInterface(out, "BadThing2", raw); err != nil {
return nil, err
}
return out, nil
}
// C2MetaData contains all meta data concerning the C2 contract.
var C2MetaData = bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"arg1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg2\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg3\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"arg4\",\"type\":\"bool\"}],\"name\":\"BadThing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Foo\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "78ef2840de5b706112ca2dbfa765501a89",
Bin: "0x6080604052348015600e575f5ffd5b506101148061001c5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063bfb4ebcf14602a575b5f5ffd5b60306032565b005b5f600160025f6040517fbb6a82f1000000000000000000000000000000000000000000000000000000008152600401606c949392919060a3565b60405180910390fd5b5f819050919050565b6085816075565b82525050565b5f8115159050919050565b609d81608b565b82525050565b5f60808201905060b45f830187607e565b60bf6020830186607e565b60ca6040830185607e565b60d560608301846096565b9594505050505056fea2646970667358221220e90bf647ffc897060e44b88d54995ed0c03c988fbccaf034375c2ff4e594690764736f6c634300081c0033",
}
// C2 is an auto generated Go binding around an Ethereum contract.
type C2 struct {
abi abi.ABI
}
// NewC2 creates a new instance of C2.
func NewC2() *C2 {
parsed, err := C2MetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &C2{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *C2) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackFoo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbfb4ebcf. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function Foo() pure returns()
func (c2 *C2) PackFoo() []byte {
enc, err := c2.abi.Pack("Foo")
if err != nil {
panic(err)
}
return enc
}
// TryPackFoo is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbfb4ebcf. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function Foo() pure returns()
func (c2 *C2) TryPackFoo() ([]byte, error) {
return c2.abi.Pack("Foo")
}
// UnpackError attempts to decode the provided error data using user-defined
// error definitions.
func (c2 *C2) UnpackError(raw []byte) (any, error) {
if bytes.Equal(raw[:4], c2.abi.Errors["BadThing"].ID.Bytes()[:4]) {
return c2.UnpackBadThingError(raw[4:])
}
return nil, errors.New("Unknown error")
}
// C2BadThing represents a BadThing error raised by the C2 contract.
type C2BadThing struct {
Arg1 *big.Int
Arg2 *big.Int
Arg3 *big.Int
Arg4 bool
}
// ErrorID returns the hash of canonical representation of the error's signature.
//
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
func C2BadThingErrorID() common.Hash {
return common.HexToHash("0xbb6a82f123854747ef4381e30e497f934a3854753fec99a69c35c30d4b46714d")
}
// UnpackBadThingError is the Go binding used to decode the provided
// error data into the corresponding Go error struct.
//
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
func (c2 *C2) UnpackBadThingError(raw []byte) (*C2BadThing, error) {
out := new(C2BadThing)
if err := c2.abi.UnpackIntoInterface(out, "BadThing", raw); err != nil {
return nil, err
}
return out, nil
}

View file

@ -0,0 +1 @@
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"uint256","name":"arg4","type":"uint256"}],"name":"BadThing2","type":"error"},{"inputs":[],"name":"Bar","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101c58061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063b0a378b014610038578063bfb4ebcf14610042575b5f5ffd5b61004061004c565b005b61004a610092565b005b5f6001600260036040517fd233a24f00000000000000000000000000000000000000000000000000000000815260040161008994939291906100ef565b60405180910390fd5b5f600160025f6040517fbb6a82f10000000000000000000000000000000000000000000000000000000081526004016100ce949392919061014c565b60405180910390fd5b5f819050919050565b6100e9816100d7565b82525050565b5f6080820190506101025f8301876100e0565b61010f60208301866100e0565b61011c60408301856100e0565b61012960608301846100e0565b95945050505050565b5f8115159050919050565b61014681610132565b82525050565b5f60808201905061015f5f8301876100e0565b61016c60208301866100e0565b61017960408301856100e0565b610186606083018461013d565b9594505050505056fea26469706673582212206a82b4c28576e4483a81102558271cfefc891cd63b95440dea521185c1ff6a2a64736f6c634300081c0033"},"contract.sol:C2":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101148061001c5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063bfb4ebcf14602a575b5f5ffd5b60306032565b005b5f600160025f6040517fbb6a82f1000000000000000000000000000000000000000000000000000000008152600401606c949392919060a3565b60405180910390fd5b5f819050919050565b6085816075565b82525050565b5f8115159050919050565b609d81608b565b82525050565b5f60808201905060b45f830187607e565b60bf6020830186607e565b60ca6040830185607e565b60d560608301846096565b9594505050505056fea2646970667358221220e90bf647ffc897060e44b88d54995ed0c03c988fbccaf034375c2ff4e594690764736f6c634300081c0033"}},"version":"0.8.28+commit.7893614a.Darwin.appleclang"}

View file

@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4);
error BadThing2(uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4);
contract C {
function Foo() public pure {
revert BadThing({
arg1: uint256(0),
arg2: uint256(1),
arg3: uint256(2),
arg4: false
});
}
function Bar() public pure {
revert BadThing2({
arg1: uint256(0),
arg2: uint256(1),
arg3: uint256(2),
arg4: uint256(3)
});
}
}
// purpose of this is to test that generation of metadata for contract that emits one error produces valid Go code
contract C2 {
function Foo() public pure {
revert BadThing({
arg1: uint256(0),
arg2: uint256(1),
arg3: uint256(2),
arg4: false
});
}
}

View file

@ -0,0 +1,87 @@
// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package uint256arrayreturn
import (
"bytes"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = bytes.Equal
_ = errors.New
_ = big.NewInt
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
// MyContractMetaData contains all meta data concerning the MyContract contract.
var MyContractMetaData = bind.MetaData{
ABI: "[{\"inputs\":[],\"name\":\"GetNums\",\"outputs\":[{\"internalType\":\"uint256[5]\",\"name\":\"\",\"type\":\"uint256[5]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
ID: "e48e83c9c45b19a47bd451eedc725a6bff",
Bin: "0x6080604052348015600e575f5ffd5b506101a78061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063bd6d10071461002d575b5f5ffd5b61003561004b565b6040516100429190610158565b60405180910390f35b610053610088565b5f6040518060a001604052805f8152602001600181526020016002815260200160038152602001600481525090508091505090565b6040518060a00160405280600590602082028036833780820191505090505090565b5f60059050919050565b5f81905092915050565b5f819050919050565b5f819050919050565b6100d9816100c7565b82525050565b5f6100ea83836100d0565b60208301905092915050565b5f602082019050919050565b61010b816100aa565b61011581846100b4565b9250610120826100be565b805f5b8381101561015057815161013787826100df565b9650610142836100f6565b925050600181019050610123565b505050505050565b5f60a08201905061016b5f830184610102565b9291505056fea2646970667358221220ef76cc678ca215c3e9e5261e3f33ac1cb9901c3186c2af167bfcd8f03b3b864c64736f6c634300081c0033",
}
// MyContract is an auto generated Go binding around an Ethereum contract.
type MyContract struct {
abi abi.ABI
}
// NewMyContract creates a new instance of MyContract.
func NewMyContract() *MyContract {
parsed, err := MyContractMetaData.ParseABI()
if err != nil {
panic(errors.New("invalid ABI: " + err.Error()))
}
return &MyContract{abi: *parsed}
}
// Instance creates a wrapper for a deployed contract instance at the given address.
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
func (c *MyContract) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
}
// PackGetNums is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbd6d1007. This method will panic if any
// invalid/nil inputs are passed.
//
// Solidity: function GetNums() pure returns(uint256[5])
func (myContract *MyContract) PackGetNums() []byte {
enc, err := myContract.abi.Pack("GetNums")
if err != nil {
panic(err)
}
return enc
}
// TryPackGetNums is the Go binding used to pack the parameters required for calling
// the contract method with ID 0xbd6d1007. This method will return an error
// if any inputs are invalid/nil.
//
// Solidity: function GetNums() pure returns(uint256[5])
func (myContract *MyContract) TryPackGetNums() ([]byte, error) {
return myContract.abi.Pack("GetNums")
}
// UnpackGetNums is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xbd6d1007.
//
// Solidity: function GetNums() pure returns(uint256[5])
func (myContract *MyContract) UnpackGetNums(data []byte) ([5]*big.Int, error) {
out, err := myContract.abi.Unpack("GetNums", data)
if err != nil {
return *new([5]*big.Int), err
}
out0 := *abi.ConvertType(out[0], new([5]*big.Int)).(*[5]*big.Int)
return out0, nil
}

View file

@ -0,0 +1 @@
{"contracts":{"contract.sol:MyContract":{"abi":[{"inputs":[],"name":"GetNums","outputs":[{"internalType":"uint256[5]","name":"","type":"uint256[5]"}],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101a78061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063bd6d10071461002d575b5f5ffd5b61003561004b565b6040516100429190610158565b60405180910390f35b610053610088565b5f6040518060a001604052805f8152602001600181526020016002815260200160038152602001600481525090508091505090565b6040518060a00160405280600590602082028036833780820191505090505090565b5f60059050919050565b5f81905092915050565b5f819050919050565b5f819050919050565b6100d9816100c7565b82525050565b5f6100ea83836100d0565b60208301905092915050565b5f602082019050919050565b61010b816100aa565b61011581846100b4565b9250610120826100be565b805f5b8381101561015057815161013787826100df565b9650610142836100f6565b925050600181019050610123565b505050505050565b5f60a08201905061016b5f830184610102565b9291505056fea2646970667358221220ef76cc678ca215c3e9e5261e3f33ac1cb9901c3186c2af167bfcd8f03b3b864c64736f6c634300081c0033"}},"version":"0.8.28+commit.7893614a.Darwin.appleclang"}

View file

@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract MyContract {
// emit multiple events, different types
function GetNums() public pure returns (uint256[5] memory) {
uint256[5] memory myNums = [uint256(0), uint256(1), uint256(2), uint256(3), uint256(4)];
return myNums;
}
}

268
accounts/abi/bind/v2/lib.go Normal file
View file

@ -0,0 +1,268 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package bind implements utilities for interacting with Solidity contracts.
// This is the 'runtime' for contract bindings generated with the abigen command.
// It includes methods for calling/transacting, filtering chain history for
// specific custom Solidity event types, and creating event subscriptions to monitor the
// chain for event occurrences.
//
// Two methods for contract deployment are provided:
// - [DeployContract] is intended to be used for deployment of a single contract.
// - [LinkAndDeploy] is intended for the deployment of multiple
// contracts, potentially with library dependencies.
package bind
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
)
// ContractEvent is a type constraint for ABI event types.
type ContractEvent interface {
ContractEventName() string
}
// FilterEvents filters a historical block range for instances of emission of a
// specific event type from a specified contract. It returns an error if the
// provided filter opts are invalid or the backend is closed.
//
// FilterEvents is intended to be used with contract event unpack methods in
// bindings generated with the abigen --v2 flag. It should be
// preferred over BoundContract.FilterLogs.
func FilterEvents[Ev ContractEvent](c *BoundContract, opts *FilterOpts, unpack func(*types.Log) (*Ev, error), topics ...[]any) (*EventIterator[Ev], error) {
var e Ev
logs, sub, err := c.FilterLogs(opts, e.ContractEventName(), topics...)
if err != nil {
return nil, err
}
return &EventIterator[Ev]{unpack: unpack, logs: logs, sub: sub}, nil
}
// WatchEvents creates an event subscription to notify when logs of the
// specified event type are emitted from the given contract. Received logs are
// unpacked and forwarded to sink. If topics are specified, only events are
// forwarded which match the topics.
//
// WatchEvents returns a subscription or an error if the provided WatchOpts are
// invalid or the backend is closed.
//
// WatchEvents is intended to be used with contract event unpack methods in
// bindings generated with the abigen --v2 flag. It should be
// preferred over BoundContract.WatchLogs.
func WatchEvents[Ev ContractEvent](c *BoundContract, opts *WatchOpts, unpack func(*types.Log) (*Ev, error), sink chan<- *Ev, topics ...[]any) (event.Subscription, error) {
var e Ev
logs, sub, err := c.WatchLogs(opts, e.ContractEventName(), topics...)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
ev, err := unpack(&log)
if err != nil {
return err
}
select {
case sink <- ev:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// EventIterator is an object for iterating over the results of a event log
// filter call.
type EventIterator[T any] struct {
current *T
unpack func(*types.Log) (*T, error)
logs <-chan types.Log
sub ethereum.Subscription
fail error // error to hold reason for iteration failure
closed bool // true if Close has been called
}
// Value returns the current value of the iterator, or nil if there isn't one.
func (it *EventIterator[T]) Value() *T {
return it.current
}
// Next advances the iterator to the subsequent event (if there is one),
// returning true if the iterator advanced.
//
// If the attempt to convert the raw log object to an instance of T using the
// unpack function provided via FilterEvents returns an error: that error is
// returned and subsequent calls to Next will not advance the iterator.
func (it *EventIterator[T]) Next() (advanced bool) {
// If the iterator failed with an error, don't proceed
if it.fail != nil || it.closed {
return false
}
// if the iterator is still active, block until a log is received or the
// underlying subscription terminates.
select {
case log := <-it.logs:
res, err := it.unpack(&log)
if err != nil {
it.fail = err
return false
}
it.current = res
return true
case <-it.sub.Err():
// regardless of how the subscription ends, still be able to iterate
// over any unread logs.
select {
case log := <-it.logs:
res, err := it.unpack(&log)
if err != nil {
it.fail = err
return false
}
it.current = res
return true
default:
return false
}
}
}
// Error returns an error if iteration has failed.
func (it *EventIterator[T]) Error() error {
return it.fail
}
// Close releases any pending underlying resources. Any subsequent calls to
// Next will not advance the iterator, but the current value remains accessible.
func (it *EventIterator[T]) Close() error {
it.closed = true
it.sub.Unsubscribe()
return nil
}
// Call performs an eth_call to a contract with optional call data.
//
// To call a function that doesn't return any output, pass nil as the unpack
// function. This can be useful if you just want to check that the function
// doesn't revert.
//
// Call is intended to be used with contract method unpack methods in
// bindings generated with the abigen --v2 flag. It should be
// preferred over BoundContract.Call
func Call[T any](c *BoundContract, opts *CallOpts, calldata []byte, unpack func([]byte) (T, error)) (T, error) {
var defaultResult T
packedOutput, err := c.CallRaw(opts, calldata)
if err != nil {
return defaultResult, err
}
if unpack == nil {
if len(packedOutput) > 0 {
return defaultResult, errors.New("contract returned data, but no unpack function was given")
}
return defaultResult, nil
}
res, err := unpack(packedOutput)
if err != nil {
return defaultResult, err
}
return res, err
}
// Transact creates and submits a transaction to a contract with optional input
// data.
//
// Transact is identical to BoundContract.RawTransact, and is provided as a
// package-level method so that interactions with contracts whose bindings were
// generated with the abigen --v2 flag are consistent (they do not require
// calling methods on the BoundContract instance).
func Transact(c *BoundContract, opt *TransactOpts, data []byte) (*types.Transaction, error) {
return c.RawTransact(opt, data)
}
// DeployContract creates and submits a deployment transaction based on the
// deployer bytecode and optional ABI-encoded constructor input. It returns
// the address and creation transaction of the pending contract, or an error
// if the creation failed.
//
// To initiate the deployment of multiple contracts with one method call, see the
// [LinkAndDeploy] method.
func DeployContract(opts *TransactOpts, bytecode []byte, backend ContractBackend, constructorInput []byte) (common.Address, *types.Transaction, error) {
c := NewBoundContract(common.Address{}, abi.ABI{}, backend, backend, backend)
tx, err := c.RawCreationTransact(opts, append(bytecode, constructorInput...))
if err != nil {
return common.Address{}, nil, err
}
return crypto.CreateAddress(opts.From, tx.Nonce()), tx, nil
}
// DefaultDeployer returns a DeployFn that signs and submits creation transactions
// using the given signer.
//
// The DeployFn returned by DefaultDeployer should be used by LinkAndDeploy in
// almost all cases, unless a custom DeployFn implementation is needed.
func DefaultDeployer(opts *TransactOpts, backend ContractBackend) DeployFn {
return func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
addr, tx, err := DeployContract(opts, deployer, backend, input)
if err != nil {
return common.Address{}, nil, err
}
return addr, tx, nil
}
}
// DeployerWithNonceAssignment is basically identical to DefaultDeployer,
// but it additionally tracks the nonce to enable automatic assignment.
//
// This is especially useful when deploying multiple contracts
// from the same address — whether they are independent contracts
// or part of a dependency chain that must be deployed in order.
func DeployerWithNonceAssignment(opts *TransactOpts, backend ContractBackend) DeployFn {
var pendingNonce int64
if opts.Nonce != nil {
pendingNonce = opts.Nonce.Int64()
}
return func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
if pendingNonce != 0 {
opts.Nonce = big.NewInt(pendingNonce)
}
addr, tx, err := DeployContract(opts, deployer, backend, input)
if err != nil {
return common.Address{}, nil, err
}
pendingNonce = int64(tx.Nonce() + 1)
return addr, tx, nil
}
}

View file

@ -0,0 +1,394 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind_test
import (
"context"
"math/big"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/events"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/nested_libraries"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/solc_errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/simulated"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
)
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
var testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
func testSetup() (*backends.SimulatedBackend, error) {
backend := simulated.NewBackend(
types.GenesisAlloc{
testAddr: {Balance: big.NewInt(10000000000000000)},
},
func(nodeConf *node.Config, ethConf *ethconfig.Config) {
ethConf.Genesis.Difficulty = big.NewInt(0)
},
)
// we should just be able to use the backend directly, instead of using
// this deprecated interface. However, the simulated backend no longer
// implements backends.SimulatedBackend...
bindBackend := backends.SimulatedBackend{
Backend: backend,
Client: backend.Client(),
}
return &bindBackend, nil
}
func makeTestDeployer(backend simulated.Client) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
chainId, _ := backend.ChainID(context.Background())
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), backend)
}
// makeTestDeployerWithNonceAssignment is similar to makeTestDeployer,
// but it returns a deployer that automatically tracks nonce,
// enabling the deployment of multiple contracts from the same account.
func makeTestDeployerWithNonceAssignment(backend simulated.Client) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
chainId, _ := backend.ChainID(context.Background())
return bind.DeployerWithNonceAssignment(bind.NewKeyedTransactor(testKey, chainId), backend)
}
// test that deploying a contract with library dependencies works,
// verifying by calling method on the deployed contract.
func TestDeploymentLibraries(t *testing.T) {
bindBackend, err := testSetup()
if err != nil {
t.Fatalf("err setting up test: %v", err)
}
defer bindBackend.Backend.Close()
c := nested_libraries.NewC1()
constructorInput := c.PackConstructor(big.NewInt(42), big.NewInt(1))
deploymentParams := &bind.DeploymentParams{
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
}
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend.Client))
if err != nil {
t.Fatalf("err: %+v\n", err)
}
bindBackend.Commit()
if len(res.Addresses) != 5 {
t.Fatalf("deployment should have generated 5 addresses. got %d", len(res.Addresses))
}
for _, tx := range res.Txs {
_, err = bind.WaitDeployed(context.Background(), bindBackend, tx.Hash())
if err != nil {
t.Fatalf("error deploying library: %+v", err)
}
}
doInput := c.PackDo(big.NewInt(1))
contractAddr := res.Addresses[nested_libraries.C1MetaData.ID]
callOpts := &bind.CallOpts{From: common.Address{}, Context: context.Background()}
instance := c.Instance(bindBackend, contractAddr)
internalCallCount, err := bind.Call(instance, callOpts, doInput, c.UnpackDo)
if err != nil {
t.Fatalf("err unpacking result: %v", err)
}
if internalCallCount.Uint64() != 6 {
t.Fatalf("expected internal call count of 6. got %d.", internalCallCount.Uint64())
}
}
// Same as TestDeployment. However, stagger the deployments with overrides:
// first deploy the library deps and then the contract.
func TestDeploymentWithOverrides(t *testing.T) {
bindBackend, err := testSetup()
if err != nil {
t.Fatalf("err setting up test: %v", err)
}
defer bindBackend.Backend.Close()
// deploy all the library dependencies of our target contract, but not the target contract itself.
deploymentParams := &bind.DeploymentParams{
Contracts: nested_libraries.C1MetaData.Deps,
}
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployerWithNonceAssignment(bindBackend))
if err != nil {
t.Fatalf("err: %+v\n", err)
}
bindBackend.Commit()
if len(res.Addresses) != 4 {
t.Fatalf("deployment should have generated 4 addresses. got %d", len(res.Addresses))
}
for _, tx := range res.Txs {
_, err = bind.WaitDeployed(context.Background(), bindBackend, tx.Hash())
if err != nil {
t.Fatalf("error deploying library: %+v", err)
}
}
c := nested_libraries.NewC1()
constructorInput := c.PackConstructor(big.NewInt(42), big.NewInt(1))
overrides := res.Addresses
// deploy the contract
deploymentParams = &bind.DeploymentParams{
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
Overrides: overrides,
}
res, err = bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend))
if err != nil {
t.Fatalf("err: %+v\n", err)
}
bindBackend.Commit()
if len(res.Addresses) != 1 {
t.Fatalf("deployment should have generated 1 address. got %d", len(res.Addresses))
}
for _, tx := range res.Txs {
_, err = bind.WaitDeployed(context.Background(), bindBackend, tx.Hash())
if err != nil {
t.Fatalf("error deploying library: %+v", err)
}
}
// call the deployed contract and make sure it returns the correct result
doInput := c.PackDo(big.NewInt(1))
instance := c.Instance(bindBackend, res.Addresses[nested_libraries.C1MetaData.ID])
callOpts := new(bind.CallOpts)
internalCallCount, err := bind.Call(instance, callOpts, doInput, c.UnpackDo)
if err != nil {
t.Fatalf("error calling contract: %v", err)
}
if internalCallCount.Uint64() != 6 {
t.Fatalf("expected internal call count of 6. got %d.", internalCallCount.Uint64())
}
}
// returns transaction auth to send a basic transaction from testAddr
func defaultTxAuth() *bind.TransactOpts {
signer := types.LatestSigner(params.AllDevChainProtocolChanges)
opts := &bind.TransactOpts{
From: testAddr,
Nonce: nil,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
if err != nil {
return nil, err
}
signedTx, err := tx.WithSignature(signer, signature)
if err != nil {
return nil, err
}
return signedTx, nil
},
Context: context.Background(),
}
return opts
}
func TestEvents(t *testing.T) {
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
backend, err := testSetup()
if err != nil {
t.Fatalf("error setting up testing env: %v", err)
}
deploymentParams := &bind.DeploymentParams{
Contracts: []*bind.MetaData{&events.CMetaData},
}
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(backend))
if err != nil {
t.Fatalf("error deploying contract for testing: %v", err)
}
backend.Commit()
if _, err := bind.WaitDeployed(context.Background(), backend, res.Txs[events.CMetaData.ID].Hash()); err != nil {
t.Fatalf("WaitDeployed failed %v", err)
}
c := events.NewC()
instance := c.Instance(backend, res.Addresses[events.CMetaData.ID])
newCBasic1Ch := make(chan *events.CBasic1)
newCBasic2Ch := make(chan *events.CBasic2)
watchOpts := &bind.WatchOpts{}
sub1, err := bind.WatchEvents(instance, watchOpts, c.UnpackBasic1Event, newCBasic1Ch)
if err != nil {
t.Fatalf("WatchEvents returned error: %v", err)
}
sub2, err := bind.WatchEvents(instance, watchOpts, c.UnpackBasic2Event, newCBasic2Ch)
if err != nil {
t.Fatalf("WatchEvents returned error: %v", err)
}
defer sub1.Unsubscribe()
defer sub2.Unsubscribe()
packedInput := c.PackEmitMulti()
tx, err := bind.Transact(instance, defaultTxAuth(), packedInput)
if err != nil {
t.Fatalf("failed to send transaction: %v", err)
}
backend.Commit()
if _, err := bind.WaitMined(context.Background(), backend, tx.Hash()); err != nil {
t.Fatalf("error waiting for tx to be mined: %v", err)
}
timeout := time.NewTimer(2 * time.Second)
e1Count := 0
e2Count := 0
for {
select {
case <-newCBasic1Ch:
e1Count++
case <-newCBasic2Ch:
e2Count++
case <-timeout.C:
goto done
}
if e1Count == 2 && e2Count == 1 {
break
}
}
done:
if e1Count != 2 {
t.Fatalf("expected event type 1 count to be 2. got %d", e1Count)
}
if e2Count != 1 {
t.Fatalf("expected event type 2 count to be 1. got %d", e2Count)
}
// now, test that we can filter those same logs after they were included in the chain
filterOpts := &bind.FilterOpts{
Start: 0,
Context: context.Background(),
}
it, err := bind.FilterEvents(instance, filterOpts, c.UnpackBasic1Event)
if err != nil {
t.Fatalf("error filtering logs %v\n", err)
}
it2, err := bind.FilterEvents(instance, filterOpts, c.UnpackBasic2Event)
if err != nil {
t.Fatalf("error filtering logs %v\n", err)
}
e1Count = 0
e2Count = 0
for it.Next() {
if err := it.Error(); err != nil {
t.Fatalf("got error while iterating events for e1: %v", err)
}
e1Count++
}
for it2.Next() {
if err := it2.Error(); err != nil {
t.Fatalf("got error while iterating events for e2: %v", err)
}
e2Count++
}
if e1Count != 2 {
t.Fatalf("expected e1Count of 2 from filter call. got %d", e1Count)
}
if e2Count != 1 {
t.Fatalf("expected e2Count of 1 from filter call. got %d", e1Count)
}
}
func TestErrors(t *testing.T) {
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
backend, err := testSetup()
if err != nil {
t.Fatalf("error setting up testing env: %v", err)
}
deploymentParams := &bind.DeploymentParams{
Contracts: []*bind.MetaData{&solc_errors.CMetaData},
}
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(backend))
if err != nil {
t.Fatalf("error deploying contract for testing: %v", err)
}
backend.Commit()
if _, err := bind.WaitDeployed(context.Background(), backend, res.Txs[solc_errors.CMetaData.ID].Hash()); err != nil {
t.Fatalf("WaitDeployed failed %v", err)
}
c := solc_errors.NewC()
instance := c.Instance(backend, res.Addresses[solc_errors.CMetaData.ID])
packedInput := c.PackFoo()
opts := &bind.CallOpts{From: res.Addresses[solc_errors.CMetaData.ID]}
_, err = bind.Call[struct{}](instance, opts, packedInput, nil)
if err == nil {
t.Fatalf("expected call to fail")
}
raw, hasRevertErrorData := ethclient.RevertErrorData(err)
if !hasRevertErrorData {
t.Fatalf("expected call error to contain revert error data.")
}
rawUnpackedErr, err := c.UnpackError(raw)
if err != nil {
t.Fatalf("expected to unpack error")
}
unpackedErr, ok := rawUnpackedErr.(*solc_errors.CBadThing)
if !ok {
t.Fatalf("unexpected type for error")
}
if unpackedErr.Arg1.Cmp(big.NewInt(0)) != 0 {
t.Fatalf("bad unpacked error result: expected Arg1 field to be 0. got %s", unpackedErr.Arg1.String())
}
if unpackedErr.Arg2.Cmp(big.NewInt(1)) != 0 {
t.Fatalf("bad unpacked error result: expected Arg2 field to be 1. got %s", unpackedErr.Arg2.String())
}
if unpackedErr.Arg3.Cmp(big.NewInt(2)) != 0 {
t.Fatalf("bad unpacked error result: expected Arg3 to be 2. got %s", unpackedErr.Arg3.String())
}
if unpackedErr.Arg4 != false {
t.Fatalf("bad unpacked error result: expected Arg4 to be false. got true")
}
}
func TestEventUnpackEmptyTopics(t *testing.T) {
c := events.NewC()
for _, log := range []*types.Log{
{Topics: []common.Hash{}},
{Topics: nil},
} {
_, err := c.UnpackBasic1Event(log)
if err == nil {
t.Fatal("expected error when unpacking event with empty topics, got nil")
}
if err.Error() != "event signature mismatch" {
t.Fatalf("expected 'event signature mismatch' error, got: %v", err)
}
_, err = c.UnpackBasic2Event(log)
if err == nil {
t.Fatal("expected error when unpacking event with empty topics, got nil")
}
if err.Error() != "event signature mismatch" {
t.Fatalf("expected 'event signature mismatch' error, got: %v", err)
}
}
}

View file

@ -21,6 +21,7 @@ import (
"errors"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
@ -28,21 +29,23 @@ import (
// WaitMined waits for tx to be mined on the blockchain.
// It stops waiting when the context is canceled.
func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {
func WaitMined(ctx context.Context, b DeployBackend, txHash common.Hash) (*types.Receipt, error) {
queryTicker := time.NewTicker(time.Second)
defer queryTicker.Stop()
logger := log.New("hash", tx.Hash())
logger := log.New("hash", txHash)
for {
receipt, err := b.TransactionReceipt(ctx, tx.Hash())
if receipt != nil {
receipt, err := b.TransactionReceipt(ctx, txHash)
if err == nil {
return receipt, nil
}
if err != nil {
logger.Trace("Receipt retrieval failed", "err", err)
} else {
if errors.Is(err, ethereum.NotFound) {
logger.Trace("Transaction not yet mined")
} else {
logger.Trace("Receipt retrieval failed", "err", err)
}
// Wait for the next round.
select {
case <-ctx.Done():
@ -52,18 +55,16 @@ func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*ty
}
}
// WaitDeployed waits for a contract deployment transaction and returns the on-chain
// contract address when it is mined. It stops waiting when ctx is canceled.
func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
if tx.To() != nil {
return common.Address{}, errors.New("tx is not contract creation")
}
receipt, err := WaitMined(ctx, b, tx)
// WaitDeployed waits for a contract deployment transaction with the provided hash and
// returns the on-chain contract address when it is mined. It stops waiting when ctx is
// canceled.
func WaitDeployed(ctx context.Context, b DeployBackend, hash common.Hash) (common.Address, error) {
receipt, err := WaitMined(ctx, b, hash)
if err != nil {
return common.Address{}, err
}
if receipt.ContractAddress == (common.Address{}) {
return common.Address{}, errors.New("zero address")
return common.Address{}, ErrNoAddressInReceipt
}
// Check that code has indeed been deployed at the address.
// This matters on pre-Homestead chains: OOG in the constructor

View file

@ -0,0 +1,164 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bind_test
import (
"context"
"errors"
"math/big"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient/simulated"
"github.com/ethereum/go-ethereum/params"
)
var waitDeployedTests = map[string]struct {
code string
gas uint64
wantAddress common.Address
wantErr error
}{
"successful deploy": {
code: `6060604052600a8060106000396000f360606040526008565b00`,
gas: 3000000,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
},
"empty code": {
code: ``,
gas: 300000,
wantErr: bind.ErrNoCodeAfterDeploy,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
},
}
func TestWaitDeployed(t *testing.T) {
t.Parallel()
for name, test := range waitDeployedTests {
backend := simulated.NewBackend(
types.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
)
defer backend.Close()
// Create the transaction
head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code))
tx, _ = types.SignTx(tx, types.LatestSignerForChainID(big.NewInt(1337)), testKey)
// Wait for it to get mined in the background.
var (
err error
address common.Address
mined = make(chan struct{})
ctx = context.Background()
)
go func() {
address, err = bind.WaitDeployed(ctx, backend.Client(), tx.Hash())
close(mined)
}()
// Send and mine the transaction.
if err := backend.Client().SendTransaction(ctx, tx); err != nil {
t.Errorf("test %q: failed to send transaction: %v", name, err)
}
backend.Commit()
select {
case <-mined:
if err != test.wantErr {
t.Errorf("test %q: error mismatch: want %q, got %q", name, test.wantErr, err)
}
if address != test.wantAddress {
t.Errorf("test %q: unexpected contract address %s", name, address.Hex())
}
case <-time.After(2 * time.Second):
t.Errorf("test %q: timeout", name)
}
}
}
func TestWaitDeployedCornerCases(t *testing.T) {
var (
backend = simulated.NewBackend(
types.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
)
head, _ = backend.Client().HeaderByNumber(t.Context(), nil) // Should be child's, good enough
gasPrice = new(big.Int).Add(head.BaseFee, big.NewInt(1))
signer = types.LatestSigner(params.AllDevChainProtocolChanges)
code = common.FromHex("6060604052600a8060106000396000f360606040526008565b00")
ctx, cancel = context.WithCancel(t.Context())
)
defer backend.Close()
// 1. WaitDeploy on a transaction that does not deploy a contract, verify it
// returns an error.
tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{
Nonce: 0,
To: &common.Address{0x01},
Gas: 300000,
GasPrice: gasPrice,
Data: code,
})
if err := backend.Client().SendTransaction(ctx, tx); err != nil {
t.Errorf("failed to send transaction: %q", err)
}
backend.Commit()
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash()); err != bind.ErrNoAddressInReceipt {
t.Errorf("error mismatch: want %q, got %q, ", bind.ErrNoAddressInReceipt, err)
}
// 2. Create a contract, but cancel the WaitDeploy before it is mined.
tx = types.MustSignNewTx(testKey, signer, &types.LegacyTx{
Nonce: 1,
Gas: 300000,
GasPrice: gasPrice,
Data: code,
})
// Wait in another thread so that we can quickly cancel it after submitting
// the transaction.
done := make(chan struct{})
go func() {
defer close(done)
_, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash())
if !errors.Is(err, context.Canceled) {
t.Errorf("error mismatch: want %v, got %v", context.Canceled, err)
}
}()
if err := backend.Client().SendTransaction(ctx, tx); err != nil {
t.Errorf("failed to send transaction: %q", err)
}
cancel()
// Wait for goroutine to exit or for a timeout.
select {
case <-done:
case <-time.After(time.Second * 2):
t.Fatalf("failed to cancel wait deploy")
}
}

View file

@ -17,66 +17,76 @@
package abi
import (
"errors"
"bytes"
"fmt"
"reflect"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
var (
errBadBool = errors.New("abi: improperly encoded boolean value")
)
type Error struct {
Name string
Inputs Arguments
str string
// formatSliceString formats the reflection kind with the given slice size
// and returns a formatted string representation.
func formatSliceString(kind reflect.Kind, sliceSize int) string {
if sliceSize == -1 {
return fmt.Sprintf("[]%v", kind)
}
return fmt.Sprintf("[%d]%v", sliceSize, kind)
// Sig contains the string signature according to the ABI spec.
// e.g. error foo(uint32 a, int b) = "foo(uint32,int256)"
// Please note that "int" is substitute for its canonical representation "int256"
Sig string
// ID returns the canonical representation of the error's signature used by the
// abi definition to identify event names and types.
ID common.Hash
}
// sliceTypeCheck checks that the given slice can by assigned to the reflection
// type in t.
func sliceTypeCheck(t Type, val reflect.Value) error {
if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
return typeErr(formatSliceString(t.GetType().Kind(), t.Size), val.Type())
}
if t.T == ArrayTy && val.Len() != t.Size {
return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
}
if t.Elem.T == SliceTy || t.Elem.T == ArrayTy {
if val.Len() > 0 {
return sliceTypeCheck(*t.Elem, val.Index(0))
func NewError(name string, inputs Arguments) Error {
// sanitize inputs to remove inputs without names
// and precompute string and sig representation.
names := make([]string, len(inputs))
types := make([]string, len(inputs))
for i, input := range inputs {
if input.Name == "" {
inputs[i] = Argument{
Name: fmt.Sprintf("arg%d", i),
Indexed: input.Indexed,
Type: input.Type,
}
} else {
inputs[i] = input
}
// string representation
names[i] = fmt.Sprintf("%v %v", input.Type, inputs[i].Name)
if input.Indexed {
names[i] = fmt.Sprintf("%v indexed %v", input.Type, inputs[i].Name)
}
// sig representation
types[i] = input.Type.String()
}
if val.Type().Elem().Kind() != t.Elem.GetType().Kind() {
return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), val.Type())
str := fmt.Sprintf("error %v(%v)", name, strings.Join(names, ", "))
sig := fmt.Sprintf("%v(%v)", name, strings.Join(types, ","))
id := common.BytesToHash(crypto.Keccak256([]byte(sig)))
return Error{
Name: name,
Inputs: inputs,
str: str,
Sig: sig,
ID: id,
}
return nil
}
// typeCheck checks that the given reflection value can be assigned to the reflection
// type in t.
func typeCheck(t Type, value reflect.Value) error {
if t.T == SliceTy || t.T == ArrayTy {
return sliceTypeCheck(t, value)
}
// Check base type validity. Element types will be checked later on.
if t.GetType().Kind() != value.Kind() {
return typeErr(t.GetType().Kind(), value.Kind())
} else if t.T == FixedBytesTy && t.Size != value.Len() {
return typeErr(t.GetType(), value.Type())
} else {
return nil
}
func (e Error) String() string {
return e.str
}
// typeErr returns a formatted type casting error.
func typeErr(expected, got interface{}) error {
return fmt.Errorf("abi: cannot use %v as type %v as argument", got, expected)
func (e *Error) Unpack(data []byte) (interface{}, error) {
if len(data) < 4 {
return "", fmt.Errorf("insufficient data for unpacking: have %d, want at least 4", len(data))
}
if !bytes.Equal(data[:4], e.ID[:4]) {
return "", fmt.Errorf("invalid identifier, have %#x want %#x", data[:4], e.ID[:4])
}
return e.Inputs.Unpack(data[4:])
}

View file

@ -0,0 +1,90 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi
import (
"errors"
"fmt"
"reflect"
)
var (
errBadBool = errors.New("abi: improperly encoded boolean value")
errBadUint8 = errors.New("abi: improperly encoded uint8 value")
errBadUint16 = errors.New("abi: improperly encoded uint16 value")
errBadUint32 = errors.New("abi: improperly encoded uint32 value")
errBadUint64 = errors.New("abi: improperly encoded uint64 value")
errBadInt8 = errors.New("abi: improperly encoded int8 value")
errBadInt16 = errors.New("abi: improperly encoded int16 value")
errBadInt32 = errors.New("abi: improperly encoded int32 value")
errBadInt64 = errors.New("abi: improperly encoded int64 value")
errInvalidSign = errors.New("abi: negatively-signed value cannot be packed into uint parameter")
)
// formatSliceString formats the reflection kind with the given slice size
// and returns a formatted string representation.
func formatSliceString(kind reflect.Kind, sliceSize int) string {
if sliceSize == -1 {
return fmt.Sprintf("[]%v", kind)
}
return fmt.Sprintf("[%d]%v", sliceSize, kind)
}
// sliceTypeCheck checks that the given slice can by assigned to the reflection
// type in t.
func sliceTypeCheck(t Type, val reflect.Value) error {
if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
return typeErr(formatSliceString(t.GetType().Kind(), t.Size), val.Type())
}
if t.T == ArrayTy && val.Len() != t.Size {
return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
}
if t.Elem.T == SliceTy || t.Elem.T == ArrayTy {
if val.Len() > 0 {
return sliceTypeCheck(*t.Elem, val.Index(0))
}
}
if val.Type().Elem().Kind() != t.Elem.GetType().Kind() {
return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), val.Type())
}
return nil
}
// typeCheck checks that the given reflection value can be assigned to the reflection
// type in t.
func typeCheck(t Type, value reflect.Value) error {
if t.T == SliceTy || t.T == ArrayTy {
return sliceTypeCheck(t, value)
}
// Check base type validity. Element types will be checked later on.
if t.GetType().Kind() != value.Kind() {
return typeErr(t.GetType().Kind(), value.Kind())
} else if t.T == FixedBytesTy && t.Size != value.Len() {
return typeErr(t.GetType(), value.Type())
} else {
return nil
}
}
// typeErr returns a formatted type casting error.
func typeErr(expected, got interface{}) error {
return fmt.Errorf("abi: cannot use %v as type %v as argument", got, expected)
}

View file

@ -29,24 +29,27 @@ import (
// don't get the signature canonical representation as the first LOG topic.
type Event struct {
// Name is the event name used for internal representation. It's derived from
// the raw name and a suffix will be added in the case of a event overload.
// the raw name and a suffix will be added in the case of event overloading.
//
// e.g.
// These are two events that have the same name:
// * foo(int,int)
// * foo(uint,uint)
// The event name of the first one wll be resolved as foo while the second one
// The event name of the first one will be resolved as foo while the second one
// will be resolved as foo0.
Name string
// RawName is the raw event name parsed from ABI.
RawName string
Anonymous bool
Inputs Arguments
str string
// Sig contains the string signature according to the ABI spec.
// e.g. event foo(uint32 a, int b) = "foo(uint32,int256)"
// Please note that "int" is substitute for its canonical representation "int256"
Sig string
// ID returns the canonical representation of the event's signature used by the
// abi definition to identify event names and types.
ID common.Hash

View file

@ -81,6 +81,7 @@ var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa
var mixedCaseData1 = "00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000020489e8000000000000000000000000000000000000000000000000000000000000000f4241"
func TestEventId(t *testing.T) {
t.Parallel()
var table = []struct {
definition string
expectations map[string]common.Hash
@ -112,6 +113,7 @@ func TestEventId(t *testing.T) {
}
func TestEventString(t *testing.T) {
t.Parallel()
var table = []struct {
definition string
expectations map[string]string
@ -146,6 +148,7 @@ func TestEventString(t *testing.T) {
// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
func TestEventMultiValueWithArrayUnpack(t *testing.T) {
t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
abi, err := JSON(strings.NewReader(definition))
require.NoError(t, err)
@ -161,7 +164,7 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
}
func TestEventTupleUnpack(t *testing.T) {
t.Parallel()
type EventTransfer struct {
Value *big.Int
}
@ -328,7 +331,6 @@ func TestEventTupleUnpack(t *testing.T) {
for _, tc := range testCases {
assert := assert.New(t)
tc := tc
t.Run(tc.name, func(t *testing.T) {
err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
if tc.error == "" {
@ -352,6 +354,7 @@ func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, ass
// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
func TestEventUnpackIndexed(t *testing.T) {
t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
type testStruct struct {
Value1 uint8 // indexed
@ -369,6 +372,7 @@ func TestEventUnpackIndexed(t *testing.T) {
// TestEventIndexedWithArrayUnpack verifies that decoder will not overflow when static array is indexed input.
func TestEventIndexedWithArrayUnpack(t *testing.T) {
t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
type testStruct struct {
Value1 [2]uint8 // indexed

View file

@ -117,24 +117,23 @@ func NewMethod(name string, rawName string, funType FunctionType, mutability str
sig = fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ","))
id = crypto.Keccak256([]byte(sig))[:4]
}
// Extract meaningful state mutability of solidity method.
// If it's default value, never print it.
state := mutability
if state == "nonpayable" {
state = ""
}
if state != "" {
state = state + " "
}
identity := fmt.Sprintf("function %v", rawName)
if funType == Fallback {
switch funType {
case Fallback:
identity = "fallback"
} else if funType == Receive {
case Receive:
identity = "receive"
} else if funType == Constructor {
case Constructor:
identity = "constructor"
}
str := fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputNames, ", "), state, strings.Join(outputNames, ", "))
var str string
// Extract meaningful state mutability of solidity method.
// If it's empty string or default value "nonpayable", never print it.
if mutability == "" || mutability == "nonpayable" {
str = fmt.Sprintf("%v(%v) returns(%v)", identity, strings.Join(inputNames, ", "), strings.Join(outputNames, ", "))
} else {
str = fmt.Sprintf("%v(%v) %s returns(%v)", identity, strings.Join(inputNames, ", "), mutability, strings.Join(outputNames, ", "))
}
return Method{
Name: name,

View file

@ -35,6 +35,7 @@ const methoddata = `
]`
func TestMethodString(t *testing.T) {
t.Parallel()
var table = []struct {
method string
expectation string
@ -84,11 +85,12 @@ func TestMethodString(t *testing.T) {
for _, test := range table {
var got string
if test.method == "fallback" {
switch test.method {
case "fallback":
got = abi.Fallback.String()
} else if test.method == "receive" {
case "receive":
got = abi.Receive.String()
} else {
default:
got = abi.Methods[test.method].String()
}
if got != test.expectation {
@ -98,6 +100,7 @@ func TestMethodString(t *testing.T) {
}
func TestMethodSig(t *testing.T) {
t.Parallel()
var cases = []struct {
method string
expect string

View file

@ -37,7 +37,16 @@ func packBytesSlice(bytes []byte, l int) []byte {
// t.
func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
switch t.T {
case IntTy, UintTy:
case UintTy:
// make sure to not pack a negative value into a uint type.
if reflectValue.Kind() == reflect.Ptr {
val := new(big.Int).Set(reflectValue.Interface().(*big.Int))
if val.Sign() == -1 {
return nil, errInvalidSign
}
}
return packNum(reflectValue), nil
case IntTy:
return packNum(reflectValue), nil
case StringTy:
return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil
@ -57,7 +66,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
reflectValue = mustArrayToByteSlice(reflectValue)
}
if reflectValue.Type() != reflect.TypeOf([]byte{}) {
return []byte{}, errors.New("Bytes type is neither slice nor array")
return []byte{}, errors.New("bytes type is neither slice nor array")
}
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil
case FixedBytesTy, FunctionTy:
@ -66,7 +75,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
}
return common.RightPadBytes(reflectValue.Bytes(), 32), nil
default:
return []byte{}, fmt.Errorf("Could not pack element, unknown type: %v", t.T)
return []byte{}, fmt.Errorf("could not pack element, unknown type: %v", t.T)
}
}

View file

@ -32,8 +32,10 @@ import (
// TestPack tests the general pack/unpack tests in packing_test.go
func TestPack(t *testing.T) {
t.Parallel()
for i, test := range packUnpackTests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Parallel()
encb, err := hex.DecodeString(test.packed)
if err != nil {
t.Fatalf("invalid hex %s: %v", test.packed, err)
@ -57,6 +59,7 @@ func TestPack(t *testing.T) {
}
func TestMethodPack(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@ -174,9 +177,15 @@ func TestMethodPack(t *testing.T) {
if !bytes.Equal(packed, sig) {
t.Errorf("expected %x got %x", sig, packed)
}
// test that we can't pack a negative value for a parameter that is specified as a uint
if _, err := abi.Pack("send", big.NewInt(-1)); err == nil {
t.Fatal("expected error when trying to pack negative big.Int into uint256 value")
}
}
func TestPackNumber(t *testing.T) {
t.Parallel()
tests := []struct {
value reflect.Value
packed []byte

View file

@ -24,17 +24,20 @@ import (
"strings"
)
// ConvertType converts an interface of a runtime type into a interface of the
// given type
// e.g. turn
// var fields []reflect.StructField
// fields = append(fields, reflect.StructField{
// Name: "X",
// Type: reflect.TypeOf(new(big.Int)),
// Tag: reflect.StructTag("json:\"" + "x" + "\""),
// }
// into
// type TupleT struct { X *big.Int }
// ConvertType converts an interface of a runtime type into an interface of the
// given type, e.g. turn this code:
//
// var fields []reflect.StructField
//
// fields = append(fields, reflect.StructField{
// Name: "X",
// Type: reflect.TypeOf(new(big.Int)),
// Tag: reflect.StructTag("json:\"" + "x" + "\""),
// })
//
// into:
//
// type TupleT struct { X *big.Int }
func ConvertType(in interface{}, proto interface{}) interface{} {
protoType := reflect.TypeOf(proto)
if reflect.TypeOf(in).ConvertibleTo(protoType) {
@ -50,7 +53,7 @@ func ConvertType(in interface{}, proto interface{}) interface{} {
// indirect recursively dereferences the value until it either gets the value
// or finds a big.Int
func indirect(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeOf(big.Int{}) {
if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeFor[big.Int]() {
return indirect(v.Elem())
}
return v
@ -62,32 +65,32 @@ func reflectIntType(unsigned bool, size int) reflect.Type {
if unsigned {
switch size {
case 8:
return reflect.TypeOf(uint8(0))
return reflect.TypeFor[uint8]()
case 16:
return reflect.TypeOf(uint16(0))
return reflect.TypeFor[uint16]()
case 32:
return reflect.TypeOf(uint32(0))
return reflect.TypeFor[uint32]()
case 64:
return reflect.TypeOf(uint64(0))
return reflect.TypeFor[uint64]()
}
}
switch size {
case 8:
return reflect.TypeOf(int8(0))
return reflect.TypeFor[int8]()
case 16:
return reflect.TypeOf(int16(0))
return reflect.TypeFor[int16]()
case 32:
return reflect.TypeOf(int32(0))
return reflect.TypeFor[int32]()
case 64:
return reflect.TypeOf(int64(0))
return reflect.TypeFor[int64]()
}
return reflect.TypeOf(&big.Int{})
return reflect.TypeFor[*big.Int]()
}
// mustArrayToByteSlice creates a new byte slice with the exact same size as value
// and copies the bytes in value to the new slice.
func mustArrayToByteSlice(value reflect.Value) reflect.Value {
slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())
slice := reflect.ValueOf(make([]byte, value.Len()))
reflect.Copy(slice, value)
return slice
}
@ -99,9 +102,9 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value {
func set(dst, src reflect.Value) error {
dstType, srcType := dst.Type(), src.Type()
switch {
case dstType.Kind() == reflect.Interface && dst.Elem().IsValid():
case dstType.Kind() == reflect.Interface && dst.Elem().IsValid() && (dst.Elem().Type().Kind() == reflect.Ptr || dst.Elem().CanSet()):
return set(dst.Elem(), src)
case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}):
case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeFor[big.Int]():
return set(dst.Elem(), src)
case srcType.AssignableTo(dstType) && dst.CanSet():
dst.Set(src)
@ -123,22 +126,15 @@ func set(dst, src reflect.Value) error {
func setSlice(dst, src reflect.Value) error {
slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len())
for i := 0; i < src.Len(); i++ {
if src.Index(i).Kind() == reflect.Struct {
if err := set(slice.Index(i), src.Index(i)); err != nil {
return err
}
} else {
// e.g. [][32]uint8 to []common.Hash
if err := set(slice.Index(i), src.Index(i)); err != nil {
return err
}
if err := set(slice.Index(i), src.Index(i)); err != nil {
return err
}
}
if dst.CanSet() {
dst.Set(slice)
return nil
}
return errors.New("Cannot set slice, destination not settable")
return errors.New("cannot set slice, destination not settable")
}
func setArray(dst, src reflect.Value) error {
@ -159,7 +155,7 @@ func setArray(dst, src reflect.Value) error {
dst.Set(array)
return nil
}
return errors.New("Cannot set array, destination not settable")
return errors.New("cannot set array, destination not settable")
}
func setStruct(dst, src reflect.Value) error {
@ -167,7 +163,7 @@ func setStruct(dst, src reflect.Value) error {
srcField := src.Field(i)
dstField := dst.Field(i)
if !dstField.IsValid() || !srcField.IsValid() {
return fmt.Errorf("Could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
return fmt.Errorf("could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
}
if err := set(dstField, srcField); err != nil {
return err
@ -177,11 +173,13 @@ func setStruct(dst, src reflect.Value) error {
}
// mapArgNamesToStructFields maps a slice of argument names to struct fields.
// first round: for each Exportable field that contains a `abi:""` tag
// and this field name exists in the given argument name list, pair them together.
// second round: for each argument name that has not been already linked,
// find what variable is expected to be mapped into, if it exists and has not been
// used, pair them.
//
// first round: for each Exportable field that contains a `abi:""` tag and this field name
// exists in the given argument name list, pair them together.
//
// second round: for each argument name that has not been already linked, find what
// variable is expected to be mapped into, if it exists and has not been used, pair them.
//
// Note this function assumes the given value is a struct value.
func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) {
typ := value.Type()
@ -227,11 +225,10 @@ func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[stri
// second round ~~~
for _, argName := range argNames {
structFieldName := ToCamelCase(argName)
if structFieldName == "" {
return nil, fmt.Errorf("abi: purely underscored output cannot unpack to struct")
return nil, errors.New("abi: purely underscored output cannot unpack to struct")
}
// this abi has already been paired, skip it... unless there exists another, yet unassigned

View file

@ -32,7 +32,7 @@ type reflectTest struct {
var reflectTests = []reflectTest{
{
name: "OneToOneCorrespondance",
name: "OneToOneCorrespondence",
args: []string{"fieldA"},
struc: struct {
FieldA int `abi:"fieldA"`
@ -170,8 +170,10 @@ var reflectTests = []reflectTest{
}
func TestReflectNameToStruct(t *testing.T) {
t.Parallel()
for _, test := range reflectTests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
if len(test.err) > 0 {
if err == nil || err.Error() != test.err {
@ -192,6 +194,7 @@ func TestReflectNameToStruct(t *testing.T) {
}
func TestConvertType(t *testing.T) {
t.Parallel()
// Test Basic Struct
type T struct {
X *big.Int
@ -201,12 +204,12 @@ func TestConvertType(t *testing.T) {
var fields []reflect.StructField
fields = append(fields, reflect.StructField{
Name: "X",
Type: reflect.TypeOf(new(big.Int)),
Type: reflect.TypeFor[*big.Int](),
Tag: "json:\"" + "x" + "\"",
})
fields = append(fields, reflect.StructField{
Name: "Y",
Type: reflect.TypeOf(new(big.Int)),
Type: reflect.TypeFor[*big.Int](),
Tag: "json:\"" + "y" + "\"",
})
val := reflect.New(reflect.StructOf(fields))

View file

@ -0,0 +1,177 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi
import (
"errors"
"fmt"
)
type SelectorMarshaling struct {
Name string `json:"name"`
Type string `json:"type"`
Inputs []ArgumentMarshaling `json:"inputs"`
}
func isDigit(c byte) bool {
return c >= '0' && c <= '9'
}
func isAlpha(c byte) bool {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
func isIdentifierSymbol(c byte) bool {
return c == '$' || c == '_'
}
func parseToken(unescapedSelector string, isIdent bool) (string, string, error) {
if len(unescapedSelector) == 0 {
return "", "", errors.New("empty token")
}
firstChar := unescapedSelector[0]
position := 1
if !(isAlpha(firstChar) || (isIdent && isIdentifierSymbol(firstChar))) {
return "", "", fmt.Errorf("invalid token start: %c", firstChar)
}
for position < len(unescapedSelector) {
char := unescapedSelector[position]
if !(isAlpha(char) || isDigit(char) || (isIdent && isIdentifierSymbol(char))) {
break
}
position++
}
return unescapedSelector[:position], unescapedSelector[position:], nil
}
func parseIdentifier(unescapedSelector string) (string, string, error) {
return parseToken(unescapedSelector, true)
}
func parseElementaryType(unescapedSelector string) (string, string, error) {
parsedType, rest, err := parseToken(unescapedSelector, false)
if err != nil {
return "", "", fmt.Errorf("failed to parse elementary type: %v", err)
}
// handle arrays
for len(rest) > 0 && rest[0] == '[' {
parsedType = parsedType + string(rest[0])
rest = rest[1:]
for len(rest) > 0 && isDigit(rest[0]) {
parsedType = parsedType + string(rest[0])
rest = rest[1:]
}
if len(rest) == 0 || rest[0] != ']' {
return "", "", fmt.Errorf("failed to parse array: expected ']', got %c", unescapedSelector[0])
}
parsedType = parsedType + string(rest[0])
rest = rest[1:]
}
return parsedType, rest, nil
}
func parseCompositeType(unescapedSelector string) ([]interface{}, string, error) {
if len(unescapedSelector) == 0 || unescapedSelector[0] != '(' {
return nil, "", fmt.Errorf("expected '(', got %c", unescapedSelector[0])
}
parsedType, rest, err := parseType(unescapedSelector[1:])
if err != nil {
return nil, "", fmt.Errorf("failed to parse type: %v", err)
}
result := []interface{}{parsedType}
for len(rest) > 0 && rest[0] != ')' {
parsedType, rest, err = parseType(rest[1:])
if err != nil {
return nil, "", fmt.Errorf("failed to parse type: %v", err)
}
result = append(result, parsedType)
}
if len(rest) == 0 || rest[0] != ')' {
return nil, "", fmt.Errorf("expected ')', got '%s'", rest)
}
if len(rest) >= 3 && rest[1] == '[' && rest[2] == ']' {
return append(result, "[]"), rest[3:], nil
}
return result, rest[1:], nil
}
func parseType(unescapedSelector string) (interface{}, string, error) {
if len(unescapedSelector) == 0 {
return nil, "", errors.New("empty type")
}
if unescapedSelector[0] == '(' {
return parseCompositeType(unescapedSelector)
} else {
return parseElementaryType(unescapedSelector)
}
}
func assembleArgs(args []interface{}) ([]ArgumentMarshaling, error) {
arguments := make([]ArgumentMarshaling, 0)
for i, arg := range args {
// generate dummy name to avoid unmarshal issues
name := fmt.Sprintf("name%d", i)
if s, ok := arg.(string); ok {
arguments = append(arguments, ArgumentMarshaling{name, s, s, nil, false})
} else if components, ok := arg.([]interface{}); ok {
subArgs, err := assembleArgs(components)
if err != nil {
return nil, fmt.Errorf("failed to assemble components: %v", err)
}
tupleType := "tuple"
if len(subArgs) != 0 && subArgs[len(subArgs)-1].Type == "[]" {
subArgs = subArgs[:len(subArgs)-1]
tupleType = "tuple[]"
}
arguments = append(arguments, ArgumentMarshaling{name, tupleType, tupleType, subArgs, false})
} else {
return nil, fmt.Errorf("failed to assemble args: unexpected type %T", arg)
}
}
return arguments, nil
}
// ParseSelector converts a method selector into a struct that can be JSON encoded
// and consumed by other functions in this package.
// Note, although uppercase letters are not part of the ABI spec, this function
// still accepts it as the general format is valid.
func ParseSelector(unescapedSelector string) (SelectorMarshaling, error) {
name, rest, err := parseIdentifier(unescapedSelector)
if err != nil {
return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': %v", unescapedSelector, err)
}
args := []interface{}{}
if len(rest) >= 2 && rest[0] == '(' && rest[1] == ')' {
rest = rest[2:]
} else {
args, rest, err = parseCompositeType(rest)
if err != nil {
return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': %v", unescapedSelector, err)
}
}
if len(rest) > 0 {
return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': unexpected string '%s'", unescapedSelector, rest)
}
// Reassemble the fake ABI and construct the JSON
fakeArgs, err := assembleArgs(args)
if err != nil {
return SelectorMarshaling{}, fmt.Errorf("failed to parse selector: %v", err)
}
return SelectorMarshaling{name, "function", fakeArgs}, nil
}

View file

@ -0,0 +1,80 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi
import (
"fmt"
"log"
"reflect"
"testing"
)
func TestParseSelector(t *testing.T) {
t.Parallel()
mkType := func(types ...interface{}) []ArgumentMarshaling {
var result []ArgumentMarshaling
for i, typeOrComponents := range types {
name := fmt.Sprintf("name%d", i)
if typeName, ok := typeOrComponents.(string); ok {
result = append(result, ArgumentMarshaling{name, typeName, typeName, nil, false})
} else if components, ok := typeOrComponents.([]ArgumentMarshaling); ok {
result = append(result, ArgumentMarshaling{name, "tuple", "tuple", components, false})
} else if components, ok := typeOrComponents.([][]ArgumentMarshaling); ok {
result = append(result, ArgumentMarshaling{name, "tuple[]", "tuple[]", components[0], false})
} else {
log.Fatalf("unexpected type %T", typeOrComponents)
}
}
return result
}
tests := []struct {
input string
name string
args []ArgumentMarshaling
}{
{"noargs()", "noargs", []ArgumentMarshaling{}},
{"simple(uint256,uint256,uint256)", "simple", mkType("uint256", "uint256", "uint256")},
{"other(uint256,address)", "other", mkType("uint256", "address")},
{"withArray(uint256[],address[2],uint8[4][][5])", "withArray", mkType("uint256[]", "address[2]", "uint8[4][][5]")},
{"singleNest(bytes32,uint8,(uint256,uint256),address)", "singleNest", mkType("bytes32", "uint8", mkType("uint256", "uint256"), "address")},
{"multiNest(address,(uint256[],uint256),((address,bytes32),uint256))", "multiNest",
mkType("address", mkType("uint256[]", "uint256"), mkType(mkType("address", "bytes32"), "uint256"))},
{"arrayNest((uint256,uint256)[],bytes32)", "arrayNest", mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, "bytes32")},
{"multiArrayNest((uint256,uint256)[],(uint256,uint256)[])", "multiArrayNest",
mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, [][]ArgumentMarshaling{mkType("uint256", "uint256")})},
{"singleArrayNestAndArray((uint256,uint256)[],bytes32[])", "singleArrayNestAndArray",
mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, "bytes32[]")},
{"singleArrayNestWithArrayAndArray((uint256[],address[2],uint8[4][][5])[],bytes32[])", "singleArrayNestWithArrayAndArray",
mkType([][]ArgumentMarshaling{mkType("uint256[]", "address[2]", "uint8[4][][5]")}, "bytes32[]")},
}
for i, tt := range tests {
selector, err := ParseSelector(tt.input)
if err != nil {
t.Errorf("test %d: failed to parse selector '%v': %v", i, tt.input, err)
}
if selector.Name != tt.name {
t.Errorf("test %d: unexpected function name: '%s' != '%s'", i, selector.Name, tt.name)
}
if selector.Type != "function" {
t.Errorf("test %d: unexpected type: '%s' != '%s'", i, selector.Type, "function")
}
if !reflect.DeepEqual(selector.Inputs, tt.args) {
t.Errorf("test %d: unexpected args: '%v' != '%v'", i, selector.Inputs, tt.args)
}
}
}

View file

@ -24,6 +24,7 @@ import (
"reflect"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
)
@ -41,8 +42,7 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
case common.Address:
copy(topic[common.HashLength-common.AddressLength:], rule[:])
case *big.Int:
blob := rule.Bytes()
copy(topic[common.HashLength-len(blob):], blob)
copy(topic[:], math.U256Bytes(new(big.Int).Set(rule)))
case bool:
if rule {
topic[common.HashLength-1] = 1
@ -75,7 +75,7 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
copy(topic[:], hash[:])
default:
// todo(rjl493456442) according solidity documentation, indexed event
// todo(rjl493456442) according to solidity documentation, indexed event
// parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored.
//

View file

@ -1,4 +1,4 @@
// Copyright 2019 The go-ethereum Authors
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@ -17,6 +17,7 @@
package abi
import (
"math"
"math/big"
"reflect"
"testing"
@ -26,6 +27,7 @@ import (
)
func TestMakeTopics(t *testing.T) {
t.Parallel()
type args struct {
query [][]interface{}
}
@ -54,9 +56,27 @@ func TestMakeTopics(t *testing.T) {
false,
},
{
"support *big.Int types in topics",
args{[][]interface{}{{big.NewInt(1).Lsh(big.NewInt(2), 254)}}},
[][]common.Hash{{common.Hash{128}}},
"support positive *big.Int types in topics",
args{[][]interface{}{
{big.NewInt(1)},
{big.NewInt(1).Lsh(big.NewInt(2), 254)},
}},
[][]common.Hash{
{common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001")},
{common.Hash{128}},
},
false,
},
{
"support negative *big.Int types in topics",
args{[][]interface{}{
{big.NewInt(-1)},
{big.NewInt(math.MinInt64)},
}},
[][]common.Hash{
{common.MaxHash},
{common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")},
},
false,
},
{
@ -118,6 +138,7 @@ func TestMakeTopics(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := MakeTopics(tt.args.query...)
if (err != nil) != tt.wantErr {
t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
@ -128,6 +149,23 @@ func TestMakeTopics(t *testing.T) {
}
})
}
t.Run("does not mutate big.Int", func(t *testing.T) {
t.Parallel()
want := [][]common.Hash{{common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")}}
in := big.NewInt(-1)
got, err := MakeTopics([]interface{}{in})
if err != nil {
t.Fatalf("makeTopics() error = %v", err)
}
if !reflect.DeepEqual(got, want) {
t.Fatalf("makeTopics() = %v, want %v", got, want)
}
if orig := big.NewInt(-1); in.Cmp(orig) != 0 {
t.Fatalf("makeTopics() mutated an input parameter from %v to %v", orig, in)
}
})
}
type args struct {
@ -347,10 +385,12 @@ func setupTopicsTests() []topicTest {
}
func TestParseTopics(t *testing.T) {
t.Parallel()
tests := setupTopicsTests()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
createObj := tt.args.createObj()
if err := ParseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
@ -364,10 +404,12 @@ func TestParseTopics(t *testing.T) {
}
func TestParseTopicsIntoMap(t *testing.T) {
t.Parallel()
tests := setupTopicsTests()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
outMap := make(map[string]interface{})
if err := ParseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr)

View file

@ -23,6 +23,8 @@ import (
"regexp"
"strconv"
"strings"
"unicode"
"unicode/utf8"
"github.com/ethereum/go-ethereum/common"
)
@ -62,13 +64,16 @@ type Type struct {
var (
// typeRegex parses the abi sub types
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
// sliceSizeRegex grab the slice size
sliceSizeRegex = regexp.MustCompile("[0-9]+")
)
// NewType creates a new reflection type of abi type given in t.
func NewType(t string, internalType string, components []ArgumentMarshaling) (typ Type, err error) {
// check that array brackets are equal if they exist
if strings.Count(t, "[") != strings.Count(t, "]") {
return Type{}, fmt.Errorf("invalid arg type in abi")
return Type{}, errors.New("invalid arg type in abi")
}
typ.stringKind = t
@ -89,8 +94,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
// grab the last cell and create a type from there
sliced := t[i:]
// grab the slice size with regexp
re := regexp.MustCompile("[0-9]+")
intz := re.FindAllString(sliced, -1)
intz := sliceSizeRegex.FindAllString(sliced, -1)
if len(intz) == 0 {
// is a slice
@ -107,7 +111,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
}
typ.stringKind = embeddedType.stringKind + sliced
} else {
return Type{}, fmt.Errorf("invalid formatting of array type")
return Type{}, errors.New("invalid formatting of array type")
}
return typ, err
}
@ -152,6 +156,9 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
if varSize == 0 {
typ.T = BytesTy
} else {
if varSize > 32 {
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
}
typ.T = FixedBytesTy
typ.Size = varSize
}
@ -161,19 +168,23 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
elems []*Type
names []string
expression string // canonical parameter expression
used = make(map[string]bool)
)
expression += "("
overloadedNames := make(map[string]string)
for idx, c := range components {
cType, err := NewType(c.Type, c.InternalType, c.Components)
if err != nil {
return Type{}, err
}
fieldName, err := overloadedArgName(c.Name, overloadedNames)
if err != nil {
return Type{}, err
name := ToCamelCase(c.Name)
if name == "" {
return Type{}, errors.New("abi: purely anonymous or underscored field is not supported")
}
fieldName := ResolveNameConflict(name, func(s string) bool { return used[s] })
used[fieldName] = true
if !isValidFieldName(fieldName) {
return Type{}, fmt.Errorf("field %d has invalid name", idx)
}
overloadedNames[fieldName] = fieldName
fields = append(fields, reflect.StructField{
Name: fieldName, // reflect.StructOf will panic for any exported field.
Type: cType.GetType(),
@ -201,14 +212,19 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
if internalType != "" && strings.HasPrefix(internalType, structPrefix) {
// Foo.Bar type definition is not allowed in golang,
// convert the format to FooBar
typ.TupleRawName = strings.Replace(internalType[len(structPrefix):], ".", "", -1)
typ.TupleRawName = strings.ReplaceAll(internalType[len(structPrefix):], ".", "")
}
case "function":
typ.T = FunctionTy
typ.Size = 24
default:
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
if strings.HasPrefix(internalType, "contract ") {
typ.Size = 20
typ.T = AddressTy
} else {
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
}
}
return
@ -222,9 +238,9 @@ func (t Type) GetType() reflect.Type {
case UintTy:
return reflectIntType(true, t.Size)
case BoolTy:
return reflect.TypeOf(false)
return reflect.TypeFor[bool]()
case StringTy:
return reflect.TypeOf("")
return reflect.TypeFor[string]()
case SliceTy:
return reflect.SliceOf(t.Elem.GetType())
case ArrayTy:
@ -232,38 +248,20 @@ func (t Type) GetType() reflect.Type {
case TupleTy:
return t.TupleType
case AddressTy:
return reflect.TypeOf(common.Address{})
return reflect.TypeFor[common.Address]()
case FixedBytesTy:
return reflect.ArrayOf(t.Size, reflect.TypeOf(byte(0)))
return reflect.ArrayOf(t.Size, reflect.TypeFor[byte]())
case BytesTy:
return reflect.SliceOf(reflect.TypeOf(byte(0)))
case HashTy:
// hashtype currently not used
return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
case FixedPointTy:
// fixedpoint type currently not used
return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
return reflect.TypeFor[[]byte]()
case HashTy, FixedPointTy: // currently not used
return reflect.TypeFor[[32]byte]()
case FunctionTy:
return reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
return reflect.TypeFor[[24]byte]()
default:
panic("Invalid type")
}
}
func overloadedArgName(rawName string, names map[string]string) (string, error) {
fieldName := ToCamelCase(rawName)
if fieldName == "" {
return "", errors.New("abi: purely anonymous or underscored field is not supported")
}
// Handle overloaded fieldNames
_, ok := names[fieldName]
for idx := 0; ok; idx++ {
fieldName = fmt.Sprintf("%s%d", ToCamelCase(rawName), idx)
_, ok = names[fieldName]
}
return fieldName, nil
}
// String implements Stringer.
func (t Type) String() (out string) {
return t.stringKind
@ -350,7 +348,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
}
}
// requireLengthPrefix returns whether the type requires any sort of length
// requiresLengthPrefix returns whether the type requires any sort of length
// prefixing.
func (t Type) requiresLengthPrefix() bool {
return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
@ -399,3 +397,30 @@ func getTypeSize(t Type) int {
}
return 32
}
// isLetter reports whether a given 'rune' is classified as a Letter.
// This method is copied from reflect/type.go
func isLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
}
// isValidFieldName checks if a string is a valid (struct) field name or not.
//
// According to the language spec, a field name should be an identifier.
//
// identifier = letter { letter | unicode_digit } .
// letter = unicode_letter | "_" .
// This method is copied from reflect/type.go
func isValidFieldName(fieldName string) bool {
for i, c := range fieldName {
if i == 0 && !isLetter(c) {
return false
}
if !(isLetter(c) || unicode.IsDigit(c)) {
return false
}
}
return len(fieldName) > 0
}

Some files were not shown because too many files have changed in this diff Show more