From 4457bd3bdac5b0a36363ad9aa882d93eddcc1088 Mon Sep 17 00:00:00 2001 From: Lucas Menendez Date: Wed, 4 Oct 2023 13:48:20 +0200 Subject: [PATCH 1/4] basic support for ERC20Votes OpenZeppelin contract: it tracks the DelegateVoteChange event to keep the voting power between holders updated --- contracts/erc/erc20votes/ERC20Votes.abi | 1 + contracts/erc/erc20votes/erc20Votes.go | 1576 +++++++++++++++++++++++ db/migrations/0001_census3.sql | 1 + state/const.go | 2 + state/tokens.go | 2 + state/web3.go | 30 +- 6 files changed, 1611 insertions(+), 1 deletion(-) create mode 100644 contracts/erc/erc20votes/ERC20Votes.abi create mode 100644 contracts/erc/erc20votes/erc20Votes.go diff --git a/contracts/erc/erc20votes/ERC20Votes.abi b/contracts/erc/erc20votes/ERC20Votes.abi new file mode 100644 index 00000000..83b67e84 --- /dev/null +++ b/contracts/erc/erc20votes/ERC20Votes.abi @@ -0,0 +1 @@ +[{"inputs":[],"name":"CheckpointUnorderedInsertion","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"uint256","name":"increasedSupply","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"}],"name":"ERC20ExceededSafeSupply","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"},{"internalType":"uint48","name":"clock","type":"uint48"}],"name":"ERC5805FutureLookup","type":"error"},{"inputs":[],"name":"ERC6372InconsistentClock","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"VotesExpiredSignature","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotes","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"pos","type":"uint32"}],"name":"checkpoints","outputs":[{"components":[{"internalType":"uint48","name":"_key","type":"uint48"},{"internalType":"uint208","name":"_value","type":"uint208"}],"internalType":"struct Checkpoints.Checkpoint208","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/contracts/erc/erc20votes/erc20Votes.go b/contracts/erc/erc20votes/erc20Votes.go new file mode 100644 index 00000000..928aaaf3 --- /dev/null +++ b/contracts/erc/erc20votes/erc20Votes.go @@ -0,0 +1,1576 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ERC20VotesContract + +import ( + "errors" + "math/big" + "strings" + + ethereum "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/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// CheckpointsCheckpoint208 is an auto generated low-level Go binding around an user-defined struct. +type CheckpointsCheckpoint208 struct { + Key *big.Int + Value *big.Int +} + +// ERC20VotesContractMetaData contains all meta data concerning the ERC20VotesContract contract. +var ERC20VotesContractMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"CheckpointUnorderedInsertion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"increasedSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cap\",\"type\":\"uint256\"}],\"name\":\"ERC20ExceededSafeSupply\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSpender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timepoint\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"clock\",\"type\":\"uint48\"}],\"name\":\"ERC5805FutureLookup\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC6372InconsistentClock\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"}],\"name\":\"InvalidAccountNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortString\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"bits\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SafeCastOverflowedUintDowncast\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"str\",\"type\":\"string\"}],\"name\":\"StringTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"VotesExpiredSignature\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousVotes\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVotes\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CLOCK_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"pos\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"components\":[{\"internalType\":\"uint48\",\"name\":\"_key\",\"type\":\"uint48\"},{\"internalType\":\"uint208\",\"name\":\"_value\",\"type\":\"uint208\"}],\"internalType\":\"structCheckpoints.Checkpoint208\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clock\",\"outputs\":[{\"internalType\":\"uint48\",\"name\":\"\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timepoint\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timepoint\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// ERC20VotesContractABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC20VotesContractMetaData.ABI instead. +var ERC20VotesContractABI = ERC20VotesContractMetaData.ABI + +// ERC20VotesContract is an auto generated Go binding around an Ethereum contract. +type ERC20VotesContract struct { + ERC20VotesContractCaller // Read-only binding to the contract + ERC20VotesContractTransactor // Write-only binding to the contract + ERC20VotesContractFilterer // Log filterer for contract events +} + +// ERC20VotesContractCaller is an auto generated read-only Go binding around an Ethereum contract. +type ERC20VotesContractCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20VotesContractTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC20VotesContractTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20VotesContractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC20VotesContractFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20VotesContractSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC20VotesContractSession struct { + Contract *ERC20VotesContract // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20VotesContractCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC20VotesContractCallerSession struct { + Contract *ERC20VotesContractCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ERC20VotesContractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC20VotesContractTransactorSession struct { + Contract *ERC20VotesContractTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20VotesContractRaw is an auto generated low-level Go binding around an Ethereum contract. +type ERC20VotesContractRaw struct { + Contract *ERC20VotesContract // Generic contract binding to access the raw methods on +} + +// ERC20VotesContractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC20VotesContractCallerRaw struct { + Contract *ERC20VotesContractCaller // Generic read-only contract binding to access the raw methods on +} + +// ERC20VotesContractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC20VotesContractTransactorRaw struct { + Contract *ERC20VotesContractTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewERC20VotesContract creates a new instance of ERC20VotesContract, bound to a specific deployed contract. +func NewERC20VotesContract(address common.Address, backend bind.ContractBackend) (*ERC20VotesContract, error) { + contract, err := bindERC20VotesContract(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ERC20VotesContract{ERC20VotesContractCaller: ERC20VotesContractCaller{contract: contract}, ERC20VotesContractTransactor: ERC20VotesContractTransactor{contract: contract}, ERC20VotesContractFilterer: ERC20VotesContractFilterer{contract: contract}}, nil +} + +// NewERC20VotesContractCaller creates a new read-only instance of ERC20VotesContract, bound to a specific deployed contract. +func NewERC20VotesContractCaller(address common.Address, caller bind.ContractCaller) (*ERC20VotesContractCaller, error) { + contract, err := bindERC20VotesContract(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC20VotesContractCaller{contract: contract}, nil +} + +// NewERC20VotesContractTransactor creates a new write-only instance of ERC20VotesContract, bound to a specific deployed contract. +func NewERC20VotesContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ERC20VotesContractTransactor, error) { + contract, err := bindERC20VotesContract(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC20VotesContractTransactor{contract: contract}, nil +} + +// NewERC20VotesContractFilterer creates a new log filterer instance of ERC20VotesContract, bound to a specific deployed contract. +func NewERC20VotesContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ERC20VotesContractFilterer, error) { + contract, err := bindERC20VotesContract(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC20VotesContractFilterer{contract: contract}, nil +} + +// bindERC20VotesContract binds a generic wrapper to an already deployed contract. +func bindERC20VotesContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC20VotesContractMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// 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 (_ERC20VotesContract *ERC20VotesContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20VotesContract.Contract.ERC20VotesContractCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20VotesContract *ERC20VotesContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.ERC20VotesContractTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20VotesContract *ERC20VotesContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.ERC20VotesContractTransactor.contract.Transact(opts, method, params...) +} + +// 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 (_ERC20VotesContract *ERC20VotesContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20VotesContract.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20VotesContract *ERC20VotesContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20VotesContract *ERC20VotesContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.contract.Transact(opts, method, params...) +} + +// CLOCKMODE is a free data retrieval call binding the contract method 0x4bf5d7e9. +// +// Solidity: function CLOCK_MODE() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractCaller) CLOCKMODE(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "CLOCK_MODE") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// CLOCKMODE is a free data retrieval call binding the contract method 0x4bf5d7e9. +// +// Solidity: function CLOCK_MODE() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractSession) CLOCKMODE() (string, error) { + return _ERC20VotesContract.Contract.CLOCKMODE(&_ERC20VotesContract.CallOpts) +} + +// CLOCKMODE is a free data retrieval call binding the contract method 0x4bf5d7e9. +// +// Solidity: function CLOCK_MODE() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) CLOCKMODE() (string, error) { + return _ERC20VotesContract.Contract.CLOCKMODE(&_ERC20VotesContract.CallOpts) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "allowance", owner, spender) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.Allowance(&_ERC20VotesContract.CallOpts, owner, spender) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.Allowance(&_ERC20VotesContract.CallOpts, owner, spender) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "balanceOf", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) BalanceOf(account common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.BalanceOf(&_ERC20VotesContract.CallOpts, account) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) BalanceOf(account common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.BalanceOf(&_ERC20VotesContract.CallOpts, account) +} + +// Checkpoints is a free data retrieval call binding the contract method 0xf1127ed8. +// +// Solidity: function checkpoints(address account, uint32 pos) view returns((uint48,uint208)) +func (_ERC20VotesContract *ERC20VotesContractCaller) Checkpoints(opts *bind.CallOpts, account common.Address, pos uint32) (CheckpointsCheckpoint208, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "checkpoints", account, pos) + + if err != nil { + return *new(CheckpointsCheckpoint208), err + } + + out0 := *abi.ConvertType(out[0], new(CheckpointsCheckpoint208)).(*CheckpointsCheckpoint208) + + return out0, err + +} + +// Checkpoints is a free data retrieval call binding the contract method 0xf1127ed8. +// +// Solidity: function checkpoints(address account, uint32 pos) view returns((uint48,uint208)) +func (_ERC20VotesContract *ERC20VotesContractSession) Checkpoints(account common.Address, pos uint32) (CheckpointsCheckpoint208, error) { + return _ERC20VotesContract.Contract.Checkpoints(&_ERC20VotesContract.CallOpts, account, pos) +} + +// Checkpoints is a free data retrieval call binding the contract method 0xf1127ed8. +// +// Solidity: function checkpoints(address account, uint32 pos) view returns((uint48,uint208)) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Checkpoints(account common.Address, pos uint32) (CheckpointsCheckpoint208, error) { + return _ERC20VotesContract.Contract.Checkpoints(&_ERC20VotesContract.CallOpts, account, pos) +} + +// Clock is a free data retrieval call binding the contract method 0x91ddadf4. +// +// Solidity: function clock() view returns(uint48) +func (_ERC20VotesContract *ERC20VotesContractCaller) Clock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "clock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Clock is a free data retrieval call binding the contract method 0x91ddadf4. +// +// Solidity: function clock() view returns(uint48) +func (_ERC20VotesContract *ERC20VotesContractSession) Clock() (*big.Int, error) { + return _ERC20VotesContract.Contract.Clock(&_ERC20VotesContract.CallOpts) +} + +// Clock is a free data retrieval call binding the contract method 0x91ddadf4. +// +// Solidity: function clock() view returns(uint48) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Clock() (*big.Int, error) { + return _ERC20VotesContract.Contract.Clock(&_ERC20VotesContract.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_ERC20VotesContract *ERC20VotesContractCaller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_ERC20VotesContract *ERC20VotesContractSession) Decimals() (uint8, error) { + return _ERC20VotesContract.Contract.Decimals(&_ERC20VotesContract.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Decimals() (uint8, error) { + return _ERC20VotesContract.Contract.Decimals(&_ERC20VotesContract.CallOpts) +} + +// Delegates is a free data retrieval call binding the contract method 0x587cde1e. +// +// Solidity: function delegates(address account) view returns(address) +func (_ERC20VotesContract *ERC20VotesContractCaller) Delegates(opts *bind.CallOpts, account common.Address) (common.Address, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "delegates", account) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Delegates is a free data retrieval call binding the contract method 0x587cde1e. +// +// Solidity: function delegates(address account) view returns(address) +func (_ERC20VotesContract *ERC20VotesContractSession) Delegates(account common.Address) (common.Address, error) { + return _ERC20VotesContract.Contract.Delegates(&_ERC20VotesContract.CallOpts, account) +} + +// Delegates is a free data retrieval call binding the contract method 0x587cde1e. +// +// Solidity: function delegates(address account) view returns(address) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Delegates(account common.Address) (common.Address, error) { + return _ERC20VotesContract.Contract.Delegates(&_ERC20VotesContract.CallOpts, account) +} + +// Eip712Domain is a free data retrieval call binding the contract method 0x84b0196e. +// +// Solidity: function eip712Domain() view returns(bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions) +func (_ERC20VotesContract *ERC20VotesContractCaller) Eip712Domain(opts *bind.CallOpts) (struct { + Fields [1]byte + Name string + Version string + ChainId *big.Int + VerifyingContract common.Address + Salt [32]byte + Extensions []*big.Int +}, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "eip712Domain") + + outstruct := new(struct { + Fields [1]byte + Name string + Version string + ChainId *big.Int + VerifyingContract common.Address + Salt [32]byte + Extensions []*big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Fields = *abi.ConvertType(out[0], new([1]byte)).(*[1]byte) + outstruct.Name = *abi.ConvertType(out[1], new(string)).(*string) + outstruct.Version = *abi.ConvertType(out[2], new(string)).(*string) + outstruct.ChainId = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.VerifyingContract = *abi.ConvertType(out[4], new(common.Address)).(*common.Address) + outstruct.Salt = *abi.ConvertType(out[5], new([32]byte)).(*[32]byte) + outstruct.Extensions = *abi.ConvertType(out[6], new([]*big.Int)).(*[]*big.Int) + + return *outstruct, err + +} + +// Eip712Domain is a free data retrieval call binding the contract method 0x84b0196e. +// +// Solidity: function eip712Domain() view returns(bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions) +func (_ERC20VotesContract *ERC20VotesContractSession) Eip712Domain() (struct { + Fields [1]byte + Name string + Version string + ChainId *big.Int + VerifyingContract common.Address + Salt [32]byte + Extensions []*big.Int +}, error) { + return _ERC20VotesContract.Contract.Eip712Domain(&_ERC20VotesContract.CallOpts) +} + +// Eip712Domain is a free data retrieval call binding the contract method 0x84b0196e. +// +// Solidity: function eip712Domain() view returns(bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Eip712Domain() (struct { + Fields [1]byte + Name string + Version string + ChainId *big.Int + VerifyingContract common.Address + Salt [32]byte + Extensions []*big.Int +}, error) { + return _ERC20VotesContract.Contract.Eip712Domain(&_ERC20VotesContract.CallOpts) +} + +// GetPastTotalSupply is a free data retrieval call binding the contract method 0x8e539e8c. +// +// Solidity: function getPastTotalSupply(uint256 timepoint) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) GetPastTotalSupply(opts *bind.CallOpts, timepoint *big.Int) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "getPastTotalSupply", timepoint) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetPastTotalSupply is a free data retrieval call binding the contract method 0x8e539e8c. +// +// Solidity: function getPastTotalSupply(uint256 timepoint) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) GetPastTotalSupply(timepoint *big.Int) (*big.Int, error) { + return _ERC20VotesContract.Contract.GetPastTotalSupply(&_ERC20VotesContract.CallOpts, timepoint) +} + +// GetPastTotalSupply is a free data retrieval call binding the contract method 0x8e539e8c. +// +// Solidity: function getPastTotalSupply(uint256 timepoint) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) GetPastTotalSupply(timepoint *big.Int) (*big.Int, error) { + return _ERC20VotesContract.Contract.GetPastTotalSupply(&_ERC20VotesContract.CallOpts, timepoint) +} + +// GetPastVotes is a free data retrieval call binding the contract method 0x3a46b1a8. +// +// Solidity: function getPastVotes(address account, uint256 timepoint) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) GetPastVotes(opts *bind.CallOpts, account common.Address, timepoint *big.Int) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "getPastVotes", account, timepoint) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetPastVotes is a free data retrieval call binding the contract method 0x3a46b1a8. +// +// Solidity: function getPastVotes(address account, uint256 timepoint) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) GetPastVotes(account common.Address, timepoint *big.Int) (*big.Int, error) { + return _ERC20VotesContract.Contract.GetPastVotes(&_ERC20VotesContract.CallOpts, account, timepoint) +} + +// GetPastVotes is a free data retrieval call binding the contract method 0x3a46b1a8. +// +// Solidity: function getPastVotes(address account, uint256 timepoint) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) GetPastVotes(account common.Address, timepoint *big.Int) (*big.Int, error) { + return _ERC20VotesContract.Contract.GetPastVotes(&_ERC20VotesContract.CallOpts, account, timepoint) +} + +// GetVotes is a free data retrieval call binding the contract method 0x9ab24eb0. +// +// Solidity: function getVotes(address account) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) GetVotes(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "getVotes", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetVotes is a free data retrieval call binding the contract method 0x9ab24eb0. +// +// Solidity: function getVotes(address account) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) GetVotes(account common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.GetVotes(&_ERC20VotesContract.CallOpts, account) +} + +// GetVotes is a free data retrieval call binding the contract method 0x9ab24eb0. +// +// Solidity: function getVotes(address account) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) GetVotes(account common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.GetVotes(&_ERC20VotesContract.CallOpts, account) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractCaller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractSession) Name() (string, error) { + return _ERC20VotesContract.Contract.Name(&_ERC20VotesContract.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Name() (string, error) { + return _ERC20VotesContract.Contract.Name(&_ERC20VotesContract.CallOpts) +} + +// Nonces is a free data retrieval call binding the contract method 0x7ecebe00. +// +// Solidity: function nonces(address owner) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) Nonces(opts *bind.CallOpts, owner common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "nonces", owner) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Nonces is a free data retrieval call binding the contract method 0x7ecebe00. +// +// Solidity: function nonces(address owner) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) Nonces(owner common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.Nonces(&_ERC20VotesContract.CallOpts, owner) +} + +// Nonces is a free data retrieval call binding the contract method 0x7ecebe00. +// +// Solidity: function nonces(address owner) view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Nonces(owner common.Address) (*big.Int, error) { + return _ERC20VotesContract.Contract.Nonces(&_ERC20VotesContract.CallOpts, owner) +} + +// NumCheckpoints is a free data retrieval call binding the contract method 0x6fcfff45. +// +// Solidity: function numCheckpoints(address account) view returns(uint32) +func (_ERC20VotesContract *ERC20VotesContractCaller) NumCheckpoints(opts *bind.CallOpts, account common.Address) (uint32, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "numCheckpoints", account) + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// NumCheckpoints is a free data retrieval call binding the contract method 0x6fcfff45. +// +// Solidity: function numCheckpoints(address account) view returns(uint32) +func (_ERC20VotesContract *ERC20VotesContractSession) NumCheckpoints(account common.Address) (uint32, error) { + return _ERC20VotesContract.Contract.NumCheckpoints(&_ERC20VotesContract.CallOpts, account) +} + +// NumCheckpoints is a free data retrieval call binding the contract method 0x6fcfff45. +// +// Solidity: function numCheckpoints(address account) view returns(uint32) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) NumCheckpoints(account common.Address) (uint32, error) { + return _ERC20VotesContract.Contract.NumCheckpoints(&_ERC20VotesContract.CallOpts, account) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractCaller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractSession) Symbol() (string, error) { + return _ERC20VotesContract.Contract.Symbol(&_ERC20VotesContract.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) Symbol() (string, error) { + return _ERC20VotesContract.Contract.Symbol(&_ERC20VotesContract.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _ERC20VotesContract.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractSession) TotalSupply() (*big.Int, error) { + return _ERC20VotesContract.Contract.TotalSupply(&_ERC20VotesContract.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_ERC20VotesContract *ERC20VotesContractCallerSession) TotalSupply() (*big.Int, error) { + return _ERC20VotesContract.Contract.TotalSupply(&_ERC20VotesContract.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractTransactor) Approve(opts *bind.TransactOpts, spender common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.contract.Transact(opts, "approve", spender, value) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractSession) Approve(spender common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.Approve(&_ERC20VotesContract.TransactOpts, spender, value) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractTransactorSession) Approve(spender common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.Approve(&_ERC20VotesContract.TransactOpts, spender, value) +} + +// Delegate is a paid mutator transaction binding the contract method 0x5c19a95c. +// +// Solidity: function delegate(address delegatee) returns() +func (_ERC20VotesContract *ERC20VotesContractTransactor) Delegate(opts *bind.TransactOpts, delegatee common.Address) (*types.Transaction, error) { + return _ERC20VotesContract.contract.Transact(opts, "delegate", delegatee) +} + +// Delegate is a paid mutator transaction binding the contract method 0x5c19a95c. +// +// Solidity: function delegate(address delegatee) returns() +func (_ERC20VotesContract *ERC20VotesContractSession) Delegate(delegatee common.Address) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.Delegate(&_ERC20VotesContract.TransactOpts, delegatee) +} + +// Delegate is a paid mutator transaction binding the contract method 0x5c19a95c. +// +// Solidity: function delegate(address delegatee) returns() +func (_ERC20VotesContract *ERC20VotesContractTransactorSession) Delegate(delegatee common.Address) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.Delegate(&_ERC20VotesContract.TransactOpts, delegatee) +} + +// DelegateBySig is a paid mutator transaction binding the contract method 0xc3cda520. +// +// Solidity: function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) returns() +func (_ERC20VotesContract *ERC20VotesContractTransactor) DelegateBySig(opts *bind.TransactOpts, delegatee common.Address, nonce *big.Int, expiry *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _ERC20VotesContract.contract.Transact(opts, "delegateBySig", delegatee, nonce, expiry, v, r, s) +} + +// DelegateBySig is a paid mutator transaction binding the contract method 0xc3cda520. +// +// Solidity: function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) returns() +func (_ERC20VotesContract *ERC20VotesContractSession) DelegateBySig(delegatee common.Address, nonce *big.Int, expiry *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.DelegateBySig(&_ERC20VotesContract.TransactOpts, delegatee, nonce, expiry, v, r, s) +} + +// DelegateBySig is a paid mutator transaction binding the contract method 0xc3cda520. +// +// Solidity: function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) returns() +func (_ERC20VotesContract *ERC20VotesContractTransactorSession) DelegateBySig(delegatee common.Address, nonce *big.Int, expiry *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.DelegateBySig(&_ERC20VotesContract.TransactOpts, delegatee, nonce, expiry, v, r, s) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractTransactor) Transfer(opts *bind.TransactOpts, to common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.contract.Transact(opts, "transfer", to, value) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractSession) Transfer(to common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.Transfer(&_ERC20VotesContract.TransactOpts, to, value) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractTransactorSession) Transfer(to common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.Transfer(&_ERC20VotesContract.TransactOpts, to, value) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.contract.Transact(opts, "transferFrom", from, to, value) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractSession) TransferFrom(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.TransferFrom(&_ERC20VotesContract.TransactOpts, from, to, value) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 value) returns(bool) +func (_ERC20VotesContract *ERC20VotesContractTransactorSession) TransferFrom(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _ERC20VotesContract.Contract.TransferFrom(&_ERC20VotesContract.TransactOpts, from, to, value) +} + +// ERC20VotesContractApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the ERC20VotesContract contract. +type ERC20VotesContractApprovalIterator struct { + Event *ERC20VotesContractApproval // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20VotesContractApprovalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20VotesContractApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20VotesContractApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20VotesContractApproval represents a Approval event raised by the ERC20VotesContract contract. +type ERC20VotesContractApproval struct { + Owner common.Address + Spender common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_ERC20VotesContract *ERC20VotesContractFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*ERC20VotesContractApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _ERC20VotesContract.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return &ERC20VotesContractApprovalIterator{contract: _ERC20VotesContract.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_ERC20VotesContract *ERC20VotesContractFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *ERC20VotesContractApproval, owner []common.Address, spender []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _ERC20VotesContract.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) + 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 + event := new(ERC20VotesContractApproval) + if err := _ERC20VotesContract.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_ERC20VotesContract *ERC20VotesContractFilterer) ParseApproval(log types.Log) (*ERC20VotesContractApproval, error) { + event := new(ERC20VotesContractApproval) + if err := _ERC20VotesContract.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20VotesContractDelegateChangedIterator is returned from FilterDelegateChanged and is used to iterate over the raw logs and unpacked data for DelegateChanged events raised by the ERC20VotesContract contract. +type ERC20VotesContractDelegateChangedIterator struct { + Event *ERC20VotesContractDelegateChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20VotesContractDelegateChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractDelegateChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractDelegateChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20VotesContractDelegateChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20VotesContractDelegateChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20VotesContractDelegateChanged represents a DelegateChanged event raised by the ERC20VotesContract contract. +type ERC20VotesContractDelegateChanged struct { + Delegator common.Address + FromDelegate common.Address + ToDelegate common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegateChanged is a free log retrieval operation binding the contract event 0x3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f. +// +// Solidity: event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate) +func (_ERC20VotesContract *ERC20VotesContractFilterer) FilterDelegateChanged(opts *bind.FilterOpts, delegator []common.Address, fromDelegate []common.Address, toDelegate []common.Address) (*ERC20VotesContractDelegateChangedIterator, error) { + + var delegatorRule []interface{} + for _, delegatorItem := range delegator { + delegatorRule = append(delegatorRule, delegatorItem) + } + var fromDelegateRule []interface{} + for _, fromDelegateItem := range fromDelegate { + fromDelegateRule = append(fromDelegateRule, fromDelegateItem) + } + var toDelegateRule []interface{} + for _, toDelegateItem := range toDelegate { + toDelegateRule = append(toDelegateRule, toDelegateItem) + } + + logs, sub, err := _ERC20VotesContract.contract.FilterLogs(opts, "DelegateChanged", delegatorRule, fromDelegateRule, toDelegateRule) + if err != nil { + return nil, err + } + return &ERC20VotesContractDelegateChangedIterator{contract: _ERC20VotesContract.contract, event: "DelegateChanged", logs: logs, sub: sub}, nil +} + +// WatchDelegateChanged is a free log subscription operation binding the contract event 0x3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f. +// +// Solidity: event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate) +func (_ERC20VotesContract *ERC20VotesContractFilterer) WatchDelegateChanged(opts *bind.WatchOpts, sink chan<- *ERC20VotesContractDelegateChanged, delegator []common.Address, fromDelegate []common.Address, toDelegate []common.Address) (event.Subscription, error) { + + var delegatorRule []interface{} + for _, delegatorItem := range delegator { + delegatorRule = append(delegatorRule, delegatorItem) + } + var fromDelegateRule []interface{} + for _, fromDelegateItem := range fromDelegate { + fromDelegateRule = append(fromDelegateRule, fromDelegateItem) + } + var toDelegateRule []interface{} + for _, toDelegateItem := range toDelegate { + toDelegateRule = append(toDelegateRule, toDelegateItem) + } + + logs, sub, err := _ERC20VotesContract.contract.WatchLogs(opts, "DelegateChanged", delegatorRule, fromDelegateRule, toDelegateRule) + 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 + event := new(ERC20VotesContractDelegateChanged) + if err := _ERC20VotesContract.contract.UnpackLog(event, "DelegateChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDelegateChanged is a log parse operation binding the contract event 0x3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f. +// +// Solidity: event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate) +func (_ERC20VotesContract *ERC20VotesContractFilterer) ParseDelegateChanged(log types.Log) (*ERC20VotesContractDelegateChanged, error) { + event := new(ERC20VotesContractDelegateChanged) + if err := _ERC20VotesContract.contract.UnpackLog(event, "DelegateChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20VotesContractDelegateVotesChangedIterator is returned from FilterDelegateVotesChanged and is used to iterate over the raw logs and unpacked data for DelegateVotesChanged events raised by the ERC20VotesContract contract. +type ERC20VotesContractDelegateVotesChangedIterator struct { + Event *ERC20VotesContractDelegateVotesChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20VotesContractDelegateVotesChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractDelegateVotesChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractDelegateVotesChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20VotesContractDelegateVotesChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20VotesContractDelegateVotesChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20VotesContractDelegateVotesChanged represents a DelegateVotesChanged event raised by the ERC20VotesContract contract. +type ERC20VotesContractDelegateVotesChanged struct { + Delegate common.Address + PreviousVotes *big.Int + NewVotes *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegateVotesChanged is a free log retrieval operation binding the contract event 0xdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724. +// +// Solidity: event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes) +func (_ERC20VotesContract *ERC20VotesContractFilterer) FilterDelegateVotesChanged(opts *bind.FilterOpts, delegate []common.Address) (*ERC20VotesContractDelegateVotesChangedIterator, error) { + + var delegateRule []interface{} + for _, delegateItem := range delegate { + delegateRule = append(delegateRule, delegateItem) + } + + logs, sub, err := _ERC20VotesContract.contract.FilterLogs(opts, "DelegateVotesChanged", delegateRule) + if err != nil { + return nil, err + } + return &ERC20VotesContractDelegateVotesChangedIterator{contract: _ERC20VotesContract.contract, event: "DelegateVotesChanged", logs: logs, sub: sub}, nil +} + +// WatchDelegateVotesChanged is a free log subscription operation binding the contract event 0xdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724. +// +// Solidity: event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes) +func (_ERC20VotesContract *ERC20VotesContractFilterer) WatchDelegateVotesChanged(opts *bind.WatchOpts, sink chan<- *ERC20VotesContractDelegateVotesChanged, delegate []common.Address) (event.Subscription, error) { + + var delegateRule []interface{} + for _, delegateItem := range delegate { + delegateRule = append(delegateRule, delegateItem) + } + + logs, sub, err := _ERC20VotesContract.contract.WatchLogs(opts, "DelegateVotesChanged", delegateRule) + 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 + event := new(ERC20VotesContractDelegateVotesChanged) + if err := _ERC20VotesContract.contract.UnpackLog(event, "DelegateVotesChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDelegateVotesChanged is a log parse operation binding the contract event 0xdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724. +// +// Solidity: event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes) +func (_ERC20VotesContract *ERC20VotesContractFilterer) ParseDelegateVotesChanged(log types.Log) (*ERC20VotesContractDelegateVotesChanged, error) { + event := new(ERC20VotesContractDelegateVotesChanged) + if err := _ERC20VotesContract.contract.UnpackLog(event, "DelegateVotesChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20VotesContractEIP712DomainChangedIterator is returned from FilterEIP712DomainChanged and is used to iterate over the raw logs and unpacked data for EIP712DomainChanged events raised by the ERC20VotesContract contract. +type ERC20VotesContractEIP712DomainChangedIterator struct { + Event *ERC20VotesContractEIP712DomainChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20VotesContractEIP712DomainChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractEIP712DomainChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractEIP712DomainChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20VotesContractEIP712DomainChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20VotesContractEIP712DomainChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20VotesContractEIP712DomainChanged represents a EIP712DomainChanged event raised by the ERC20VotesContract contract. +type ERC20VotesContractEIP712DomainChanged struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterEIP712DomainChanged is a free log retrieval operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. +// +// Solidity: event EIP712DomainChanged() +func (_ERC20VotesContract *ERC20VotesContractFilterer) FilterEIP712DomainChanged(opts *bind.FilterOpts) (*ERC20VotesContractEIP712DomainChangedIterator, error) { + + logs, sub, err := _ERC20VotesContract.contract.FilterLogs(opts, "EIP712DomainChanged") + if err != nil { + return nil, err + } + return &ERC20VotesContractEIP712DomainChangedIterator{contract: _ERC20VotesContract.contract, event: "EIP712DomainChanged", logs: logs, sub: sub}, nil +} + +// WatchEIP712DomainChanged is a free log subscription operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. +// +// Solidity: event EIP712DomainChanged() +func (_ERC20VotesContract *ERC20VotesContractFilterer) WatchEIP712DomainChanged(opts *bind.WatchOpts, sink chan<- *ERC20VotesContractEIP712DomainChanged) (event.Subscription, error) { + + logs, sub, err := _ERC20VotesContract.contract.WatchLogs(opts, "EIP712DomainChanged") + 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 + event := new(ERC20VotesContractEIP712DomainChanged) + if err := _ERC20VotesContract.contract.UnpackLog(event, "EIP712DomainChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseEIP712DomainChanged is a log parse operation binding the contract event 0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31. +// +// Solidity: event EIP712DomainChanged() +func (_ERC20VotesContract *ERC20VotesContractFilterer) ParseEIP712DomainChanged(log types.Log) (*ERC20VotesContractEIP712DomainChanged, error) { + event := new(ERC20VotesContractEIP712DomainChanged) + if err := _ERC20VotesContract.contract.UnpackLog(event, "EIP712DomainChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20VotesContractTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the ERC20VotesContract contract. +type ERC20VotesContractTransferIterator struct { + Event *ERC20VotesContractTransfer // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20VotesContractTransferIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20VotesContractTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20VotesContractTransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20VotesContractTransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20VotesContractTransfer represents a Transfer event raised by the ERC20VotesContract contract. +type ERC20VotesContractTransfer struct { + From common.Address + To common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_ERC20VotesContract *ERC20VotesContractFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ERC20VotesContractTransferIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _ERC20VotesContract.contract.FilterLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return &ERC20VotesContractTransferIterator{contract: _ERC20VotesContract.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_ERC20VotesContract *ERC20VotesContractFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ERC20VotesContractTransfer, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _ERC20VotesContract.contract.WatchLogs(opts, "Transfer", fromRule, toRule) + 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 + event := new(ERC20VotesContractTransfer) + if err := _ERC20VotesContract.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_ERC20VotesContract *ERC20VotesContractFilterer) ParseTransfer(log types.Log) (*ERC20VotesContractTransfer, error) { + event := new(ERC20VotesContractTransfer) + if err := _ERC20VotesContract.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/db/migrations/0001_census3.sql b/db/migrations/0001_census3.sql index 5e9b995b..e5d90c8b 100644 --- a/db/migrations/0001_census3.sql +++ b/db/migrations/0001_census3.sql @@ -15,6 +15,7 @@ INSERT INTO token_types (type_name) VALUES ('erc1155'); INSERT INTO token_types (type_name) VALUES ('erc777'); INSERT INTO token_types (type_name) VALUES ('nation3'); INSERT INTO token_types (type_name) VALUES ('want'); +INSERT INTO token_types (type_name) VALUES ('erc20votes'); CREATE TABLE tokens ( id BLOB PRIMARY KEY NOT NULL, diff --git a/state/const.go b/state/const.go index 5d479223..aa30a8db 100644 --- a/state/const.go +++ b/state/const.go @@ -20,6 +20,7 @@ const ( LOG_TOPIC_ERC1155_TRANSFER_BATCH = "4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb" LOG_TOPIC_WANT_DEPOSIT = "e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c" LOG_TOPIC_WANT_WITHDRAWAL = "7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65" + LOG_TOPIC_ERC20VOTES_DELEGATE = "dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724" // Add more topics here ) @@ -33,4 +34,5 @@ const ( CONTRACT_TYPE_CUSTOM_NATION3_VENATION CONTRACT_TYPE_CUSTOM_ARAGON_WANT CONTRACT_TYPE_ERC721_BURNED + CONTRACT_TYPE_ERC20_VOTES ) diff --git a/state/tokens.go b/state/tokens.go index 3d8a8ba0..901316d1 100644 --- a/state/tokens.go +++ b/state/tokens.go @@ -12,6 +12,7 @@ type TokenType uint64 var TokenTypeStringMap = map[TokenType]string{ CONTRACT_TYPE_UNKNOWN: "unknown", CONTRACT_TYPE_ERC20: "erc20", + CONTRACT_TYPE_ERC20_VOTES: "erc20votes", CONTRACT_TYPE_ERC721_BURNED: "erc721burned", CONTRACT_TYPE_ERC1155: "erc1155", CONTRACT_TYPE_ERC777: "erc777", @@ -29,6 +30,7 @@ var TokenTypeIntMap = map[string]TokenType{ "nation3": CONTRACT_TYPE_CUSTOM_NATION3_VENATION, "want": CONTRACT_TYPE_CUSTOM_ARAGON_WANT, "erc721burned": CONTRACT_TYPE_ERC721_BURNED, + "erc20votes": CONTRACT_TYPE_ERC20_VOTES, } func (c TokenType) String() string { diff --git a/state/web3.go b/state/web3.go index 4c7f13d7..25a552cc 100644 --- a/state/web3.go +++ b/state/web3.go @@ -13,6 +13,7 @@ import ( want "github.com/vocdoni/census3/contracts/aragon/want" erc1155 "github.com/vocdoni/census3/contracts/erc/erc1155" erc20 "github.com/vocdoni/census3/contracts/erc/erc20" + erc20Votes "github.com/vocdoni/census3/contracts/erc/erc20votes" erc721 "github.com/vocdoni/census3/contracts/erc/erc721" erc777 "github.com/vocdoni/census3/contracts/erc/erc777" venation "github.com/vocdoni/census3/contracts/nation3/vestedToken" @@ -59,7 +60,8 @@ func (w *Web3) Init(ctx context.Context, web3Endpoint string, CONTRACT_TYPE_ERC1155, CONTRACT_TYPE_ERC777, CONTRACT_TYPE_CUSTOM_NATION3_VENATION, - CONTRACT_TYPE_CUSTOM_ARAGON_WANT: + CONTRACT_TYPE_CUSTOM_ARAGON_WANT, + CONTRACT_TYPE_ERC20_VOTES: w.contractType = contractType default: return ErrUnknownTokenType @@ -89,6 +91,8 @@ func (w *Web3) NewContract() (interface{}, error) { return venation.NewNation3VestedTokenContract(w.contractAddress, w.client) case CONTRACT_TYPE_CUSTOM_ARAGON_WANT: return want.NewAragonWrappedANTTokenContract(w.contractAddress, w.client) + case CONTRACT_TYPE_ERC20_VOTES: + return erc20Votes.NewERC20VotesContract(w.contractAddress, w.client) default: return nil, ErrUnknownTokenType } @@ -114,6 +118,9 @@ func (w *Web3) TokenName() (string, error) { case CONTRACT_TYPE_CUSTOM_ARAGON_WANT: caller := w.contract.(*want.AragonWrappedANTTokenContract).AragonWrappedANTTokenContractCaller return caller.Name(nil) + case CONTRACT_TYPE_ERC20_VOTES: + caller := w.contract.(*erc20Votes.ERC20VotesContract).ERC20VotesContractCaller + return caller.Name(nil) } return "", ErrUnknownTokenType } @@ -138,6 +145,9 @@ func (w *Web3) TokenSymbol() (string, error) { case CONTRACT_TYPE_CUSTOM_ARAGON_WANT: caller := w.contract.(*want.AragonWrappedANTTokenContract).AragonWrappedANTTokenContractCaller return caller.Symbol(nil) + case CONTRACT_TYPE_ERC20_VOTES: + caller := w.contract.(*erc20Votes.ERC20VotesContract).ERC20VotesContractCaller + return caller.Symbol(nil) } return "", ErrUnknownTokenType } @@ -165,6 +175,9 @@ func (w *Web3) TokenDecimals() (uint8, error) { case CONTRACT_TYPE_CUSTOM_ARAGON_WANT: caller := w.contract.(*want.AragonWrappedANTTokenContract).AragonWrappedANTTokenContractCaller return caller.Decimals(nil) + case CONTRACT_TYPE_ERC20_VOTES: + caller := w.contract.(*erc20Votes.ERC20VotesContract).ERC20VotesContractCaller + return caller.Decimals(nil) } return 0, ErrUnknownTokenType } @@ -188,6 +201,9 @@ func (w *Web3) TokenTotalSupply() (*big.Int, error) { case CONTRACT_TYPE_CUSTOM_ARAGON_WANT: caller := w.contract.(*want.AragonWrappedANTTokenContract).AragonWrappedANTTokenContractCaller return caller.TotalSupply(nil) + case CONTRACT_TYPE_ERC20_VOTES: + caller := w.contract.(*erc20Votes.ERC20VotesContract).ERC20VotesContractCaller + return caller.TotalSupply(nil) } return nil, ErrUnknownTokenType } @@ -265,6 +281,9 @@ func (w *Web3) TokenBalanceOf(tokenHolderAddress common.Address, args ...interfa case 1: return caller.BalanceOfAt(nil, tokenHolderAddress, big.NewInt(int64(args[1].(uint64)))) } + case CONTRACT_TYPE_ERC20_VOTES: + caller := w.contract.(*erc20Votes.ERC20VotesContract).ERC20VotesContractCaller + return caller.GetVotes(nil, tokenHolderAddress) } return nil, ErrUnknownTokenType } @@ -455,6 +474,8 @@ func (w *Web3) transferLogs(fromBlock, nblocks uint64) ([]types.Log, error) { common.HexToHash(LOG_TOPIC_WANT_WITHDRAWAL), }, } + case CONTRACT_TYPE_ERC20_VOTES: + query.Topics = [][]common.Hash{{common.HexToHash(LOG_TOPIC_ERC20VOTES_DELEGATE)}} default: return nil, ErrUnknownTokenType } @@ -583,6 +604,13 @@ func (w *Web3) calcPartialBalances(hc HoldersCandidates, currentLog types.Log) ( hc[logData.Entity] = new(big.Int).Neg(logData.Amount) } } + case CONTRACT_TYPE_ERC20_VOTES: + filter := w.contract.(*erc20Votes.ERC20VotesContract).ERC20VotesContractFilterer + logData, err := filter.ParseDelegateVotesChanged(currentLog) + if err != nil { + return hc, err + } + hc[logData.Delegate] = logData.NewVotes } return hc, nil } From 72d089c09bacd65dfeb37564bc1ec4cbb940bcbd Mon Sep 17 00:00:00 2001 From: Lucas Menendez Date: Tue, 3 Oct 2023 22:04:44 +0200 Subject: [PATCH 2/4] new tests for multiple web3 providers stuff and other tests updated with the test holders balances changes of test token --- census/census_test.go | 7 ++++-- service/helper_test.go | 6 ++++-- state/helper_test.go | 16 +++++++++----- state/providers_test.go | 47 +++++++++++++++++++++++++++++++++++++++++ state/web3_test.go | 7 +++--- 5 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 state/providers_test.go diff --git a/census/census_test.go b/census/census_test.go index b0577e89..91edb579 100644 --- a/census/census_test.go +++ b/census/census_test.go @@ -38,12 +38,15 @@ var MonkeysAddresses = map[common.Address]*big.Int{ common.HexToAddress("0xe54d702f98E312aBA4318E3c6BDba98ab5e11012"): big.NewInt(16), common.HexToAddress("0x38d2BC91B89928f78cBaB3e4b1949e28787eC7a3"): big.NewInt(13), common.HexToAddress("0xF752B527E2ABA395D1Ba4C0dE9C147B763dDA1f4"): big.NewInt(12), - common.HexToAddress("0xdeb8699659bE5d41a0e57E179d6cB42E00B9200C"): big.NewInt(11), common.HexToAddress("0xe1308a8d0291849bfFb200Be582cB6347FBE90D9"): big.NewInt(9), - common.HexToAddress("0xB1F05B11Ba3d892EdD00f2e7689779E2B8841827"): big.NewInt(6), + common.HexToAddress("0xdeb8699659bE5d41a0e57E179d6cB42E00B9200C"): big.NewInt(7), + common.HexToAddress("0xB1F05B11Ba3d892EdD00f2e7689779E2B8841827"): big.NewInt(5), common.HexToAddress("0xF3C456FAAa70fea307A073C3DA9572413c77f58B"): big.NewInt(6), common.HexToAddress("0x45D3a03E8302de659e7Ea7400C4cfe9CAED8c723"): big.NewInt(6), common.HexToAddress("0x313c7f7126486fFefCaa9FEA92D968cbf891b80c"): big.NewInt(3), + common.HexToAddress("0x1893eD78480267D1854373A99Cee8dE2E08d430F"): big.NewInt(2), + common.HexToAddress("0xa2E4D94c5923A8dd99c5792A7B0436474c54e1E1"): big.NewInt(2), + common.HexToAddress("0x2a4636A5a1138e35F7f93e81FA56d3c970BC6777"): big.NewInt(1), } func TestNewCensusDB(t *testing.T) { diff --git a/service/helper_test.go b/service/helper_test.go index 9ac5aea8..bc01c299 100644 --- a/service/helper_test.go +++ b/service/helper_test.go @@ -32,13 +32,15 @@ var ( common.HexToAddress("0xe54d702f98E312aBA4318E3c6BDba98ab5e11012"): new(big.Int).SetUint64(16000000000000000000), common.HexToAddress("0x38d2BC91B89928f78cBaB3e4b1949e28787eC7a3"): new(big.Int).SetUint64(13000000000000000000), common.HexToAddress("0xF752B527E2ABA395D1Ba4C0dE9C147B763dDA1f4"): new(big.Int).SetUint64(12000000000000000000), - common.HexToAddress("0xdeb8699659bE5d41a0e57E179d6cB42E00B9200C"): new(big.Int).SetUint64(9000000000000000000), common.HexToAddress("0xe1308a8d0291849bfFb200Be582cB6347FBE90D9"): new(big.Int).SetUint64(9000000000000000000), - common.HexToAddress("0xB1F05B11Ba3d892EdD00f2e7689779E2B8841827"): new(big.Int).SetUint64(6000000000000000000), + common.HexToAddress("0xdeb8699659bE5d41a0e57E179d6cB42E00B9200C"): new(big.Int).SetUint64(7000000000000000000), + common.HexToAddress("0xB1F05B11Ba3d892EdD00f2e7689779E2B8841827"): new(big.Int).SetUint64(5000000000000000000), common.HexToAddress("0xF3C456FAAa70fea307A073C3DA9572413c77f58B"): new(big.Int).SetUint64(6000000000000000000), common.HexToAddress("0x45D3a03E8302de659e7Ea7400C4cfe9CAED8c723"): new(big.Int).SetUint64(6000000000000000000), common.HexToAddress("0x313c7f7126486fFefCaa9FEA92D968cbf891b80c"): new(big.Int).SetUint64(3000000000000000000), common.HexToAddress("0x1893eD78480267D1854373A99Cee8dE2E08d430F"): new(big.Int).SetUint64(2000000000000000000), + common.HexToAddress("0xa2E4D94c5923A8dd99c5792A7B0436474c54e1E1"): new(big.Int).SetUint64(2000000000000000000), + common.HexToAddress("0x2a4636A5a1138e35F7f93e81FA56d3c970BC6777"): new(big.Int).SetUint64(1000000000000000000), } ) diff --git a/state/helper_test.go b/state/helper_test.go index fd7780a8..d4433b85 100644 --- a/state/helper_test.go +++ b/state/helper_test.go @@ -18,21 +18,27 @@ var ( common.HexToAddress("0xe54d702f98E312aBA4318E3c6BDba98ab5e11012"): new(big.Int).SetUint64(16000000000000000000), common.HexToAddress("0x38d2BC91B89928f78cBaB3e4b1949e28787eC7a3"): new(big.Int).SetUint64(13000000000000000000), common.HexToAddress("0xF752B527E2ABA395D1Ba4C0dE9C147B763dDA1f4"): new(big.Int).SetUint64(12000000000000000000), - common.HexToAddress("0xdeb8699659bE5d41a0e57E179d6cB42E00B9200C"): new(big.Int).SetUint64(9000000000000000000), common.HexToAddress("0xe1308a8d0291849bfFb200Be582cB6347FBE90D9"): new(big.Int).SetUint64(9000000000000000000), - common.HexToAddress("0xB1F05B11Ba3d892EdD00f2e7689779E2B8841827"): new(big.Int).SetUint64(6000000000000000000), + common.HexToAddress("0xdeb8699659bE5d41a0e57E179d6cB42E00B9200C"): new(big.Int).SetUint64(7000000000000000000), + common.HexToAddress("0xB1F05B11Ba3d892EdD00f2e7689779E2B8841827"): new(big.Int).SetUint64(5000000000000000000), common.HexToAddress("0xF3C456FAAa70fea307A073C3DA9572413c77f58B"): new(big.Int).SetUint64(6000000000000000000), common.HexToAddress("0x45D3a03E8302de659e7Ea7400C4cfe9CAED8c723"): new(big.Int).SetUint64(6000000000000000000), common.HexToAddress("0x313c7f7126486fFefCaa9FEA92D968cbf891b80c"): new(big.Int).SetUint64(3000000000000000000), common.HexToAddress("0x1893eD78480267D1854373A99Cee8dE2E08d430F"): new(big.Int).SetUint64(2000000000000000000), + common.HexToAddress("0xa2E4D94c5923A8dd99c5792A7B0436474c54e1E1"): new(big.Int).SetUint64(2000000000000000000), + common.HexToAddress("0x2a4636A5a1138e35F7f93e81FA56d3c970BC6777"): new(big.Int).SetUint64(1000000000000000000), + } + DefaultWeb3Provider = Web3Provider{ + ChainID: 5, + Name: "Goerli", + ShortName: "gor", + URI: "https://eth-goerli.api.onfinality.io/public", } ) -const defaultWeb3testUri = "https://eth-goerli.api.onfinality.io/public" - func web3testUri() string { if uri := os.Getenv("WEB3_URI"); uri != "" { return uri } - return defaultWeb3testUri + return DefaultWeb3Provider.URI } diff --git a/state/providers_test.go b/state/providers_test.go new file mode 100644 index 00000000..b1bc9d7b --- /dev/null +++ b/state/providers_test.go @@ -0,0 +1,47 @@ +package state + +import ( + "testing" + + qt "github.com/frankban/quicktest" +) + +func TestCheckWeb3Providers(t *testing.T) { + c := qt.New(t) + + providers := []string{DefaultWeb3Provider.URI} + w3p, err := CheckWeb3Providers(providers) + c.Assert(err, qt.IsNil) + c.Assert(w3p[DefaultWeb3Provider.ChainID].URI, qt.Equals, DefaultWeb3Provider.URI) + c.Assert(w3p[DefaultWeb3Provider.ChainID].ShortName, qt.Equals, DefaultWeb3Provider.ShortName) + c.Assert(w3p[DefaultWeb3Provider.ChainID].Name, qt.Equals, DefaultWeb3Provider.Name) + + t.Run("URIByChainID", func(t *testing.T) { + _, ok := w3p.URIByChainID(DefaultWeb3Provider.ChainID + 1) + c.Assert(ok, qt.IsFalse) + uri, ok := w3p.URIByChainID(DefaultWeb3Provider.ChainID) + c.Assert(ok, qt.Equals, true) + c.Assert(uri, qt.Equals, DefaultWeb3Provider.URI) + }) + t.Run("ChainIDByShortName", func(t *testing.T) { + _, ok := w3p.ChainIDByShortName("UNKNOWN") + c.Assert(ok, qt.IsFalse) + chainID, ok := w3p.ChainIDByShortName(DefaultWeb3Provider.ShortName) + c.Assert(ok, qt.Equals, true) + c.Assert(chainID, qt.Equals, DefaultWeb3Provider.ChainID) + }) + t.Run("PrefixBlockNumber", func(t *testing.T) { + _, ok := w3p.PrefixBlockNumber(DefaultWeb3Provider.ChainID+1, 123456) + c.Assert(ok, qt.IsFalse) + prefix, ok := w3p.PrefixBlockNumber(DefaultWeb3Provider.ChainID, 123456) + c.Assert(ok, qt.Equals, true) + c.Assert(prefix, qt.Equals, "gor:123456") + }) + t.Run("PrefixSymbol", func(t *testing.T) { + _, ok := w3p.PrefixSymbol(DefaultWeb3Provider.ChainID+1, "UNKNOWN") + c.Assert(ok, qt.IsFalse) + prefix, ok := w3p.PrefixSymbol(DefaultWeb3Provider.ChainID, "MON") + c.Assert(ok, qt.Equals, true) + c.Assert(prefix, qt.Equals, "gor:MON") + }) +} diff --git a/state/web3_test.go b/state/web3_test.go index 2fd40625..ce9e9b36 100644 --- a/state/web3_test.go +++ b/state/web3_test.go @@ -253,7 +253,7 @@ func Test_transferLogs(t *testing.T) { logs, err := w.transferLogs(MonkeysCreationBlock, MonkeysCreationBlock+500) c.Assert(err, qt.IsNil) - c.Assert(logs, qt.HasLen, 10) + c.Assert(logs, qt.HasLen, 12) } func Test_calcPartialBalances(t *testing.T) { @@ -275,7 +275,7 @@ func Test_calcPartialBalances(t *testing.T) { for addr, balance := range MonkeysHolders { res, ok := hc[addr] c.Assert(ok, qt.IsTrue) - c.Assert(res.String(), qt.Equals, balance.String()) + c.Assert(res.String(), qt.Equals, balance.String(), qt.Commentf(addr.String())) } } @@ -289,12 +289,13 @@ func Test_commitTokenHolders(t *testing.T) { hc := HoldersCandidates(MonkeysHolders) th := new(TokenHolders).Init(MonkeysAddress, CONTRACT_TYPE_ERC20, MonkeysCreationBlock, 5) - c.Assert(w.commitTokenHolders(th, hc, MonkeysCreationBlock+1000), qt.IsNil) + c.Assert(w.commitTokenHolders(th, hc, MonkeysCreationBlock+500), qt.IsNil) c.Assert(th.LastBlock(), qt.Equals, MonkeysCreationBlock) for addr, balance := range hc { c.Assert(th.Exists(addr), qt.IsTrue) val, ok := th.holders.Load(addr) + c.Logf("addr: %s, balance: %d, val: %d", addr.String(), balance, val.(*big.Int)) c.Assert(ok, qt.IsTrue) c.Assert(val.(*big.Int).String(), qt.Equals, balance.String()) } From d122497ad53bc817e38b96f96e171ebd198a8e3f Mon Sep 17 00:00:00 2001 From: Lucas Menendez Date: Wed, 20 Sep 2023 15:31:42 +0200 Subject: [PATCH 3/4] web3 providers now contains the chain name and short name, this information is also included on /api/info endpoint --- api/README.md | 23 +++++++++- api/api.go | 19 +++++--- api/tokens.go | 8 ++-- api/types.go | 10 ++++ service/holders_scanner.go | 16 +++---- state/const.go | 7 +++ state/providers.go | 93 +++++++++++++++++++++++++++++++++++--- 7 files changed, 151 insertions(+), 25 deletions(-) diff --git a/api/README.md b/api/README.md index de1696a1..01c3a7df 100644 --- a/api/README.md +++ b/api/README.md @@ -16,7 +16,28 @@ Show information about the API service. ```json { - "chainIDs": [1, 5] + "supportedChains": [ + { + "chainID": 5, + "shortName": "gor", + "name": "Goerli" + }, + { + "chainID": 137, + "shortName": "matic", + "name": "Polygon Mainnet" + }, + { + "chainID": 80001, + "shortName": "maticmum", + "name": "Mumbai" + }, + { + "chainID": 1, + "shortName": "eth", + "name": "Ethereum Mainnet" + } + ] } ``` diff --git a/api/api.go b/api/api.go index 2e7b56d3..400df9b0 100644 --- a/api/api.go +++ b/api/api.go @@ -6,6 +6,7 @@ import ( "github.com/vocdoni/census3/census" "github.com/vocdoni/census3/db" "github.com/vocdoni/census3/queue" + "github.com/vocdoni/census3/state" "go.vocdoni.io/dvote/httprouter" api "go.vocdoni.io/dvote/httprouter/apirest" "go.vocdoni.io/dvote/log" @@ -16,7 +17,7 @@ type Census3APIConf struct { Port int DataDir string GroupKey string - Web3Providers map[uint64]string + Web3Providers state.Web3Providers } type census3API struct { @@ -25,7 +26,7 @@ type census3API struct { endpoint *api.API censusDB *census.CensusDB queue *queue.BackgroundQueue - w3p map[uint64]string + w3p state.Web3Providers } func Init(db *db.DB, conf Census3APIConf) error { @@ -74,11 +75,17 @@ func (capi *census3API) initAPIHandlers() error { } func (capi *census3API) getAPIInfo(msg *api.APIdata, ctx *httprouter.HTTPContext) error { - chainIDs := []uint64{} - for chainID := range capi.w3p { - chainIDs = append(chainIDs, chainID) + + info := &APIInfo{ + SupportedChains: []SupportedChain{}, + } + for _, provider := range capi.w3p { + info.SupportedChains = append(info.SupportedChains, SupportedChain{ + ChainID: provider.ChainID, + ShortName: provider.ShortName, + Name: provider.Name, + }) } - info := map[string]any{"chainIDs": chainIDs} res, err := json.Marshal(info) if err != nil { log.Errorw(err, "error encoding api info") diff --git a/api/tokens.go b/api/tokens.go index a0ecf724..ebf08fa5 100644 --- a/api/tokens.go +++ b/api/tokens.go @@ -91,11 +91,11 @@ func (capi *census3API) createToken(msg *api.APIdata, ctx *httprouter.HTTPContex internalCtx, cancel := context.WithTimeout(context.Background(), createTokenTimeout) defer cancel() // get correct web3 uri provider - w3uri, exists := capi.w3p[req.ChainID] + w3URI, exists := capi.w3p.URIByChainID(req.ChainID) if !exists { return ErrChainIDNotSupported.With("chain ID not supported") } - if err := w3.Init(internalCtx, w3uri, addr, tokenType); err != nil { + if err := w3.Init(internalCtx, w3URI, addr, tokenType); err != nil { log.Errorw(ErrInitializingWeb3, err.Error()) return ErrInitializingWeb3.WithErr(err) } @@ -186,13 +186,13 @@ func (capi *census3API) getToken(msg *api.APIdata, ctx *httprouter.HTTPContext) tokenProgress := 100 if !tokenData.Synced { // get correct web3 uri provider - w3uri, exists := capi.w3p[tokenData.ChainID] + w3URI, exists := capi.w3p.URIByChainID(tokenData.ChainID) if !exists { return ErrChainIDNotSupported.With("chain ID not supported") } // get last block of the network, if something fails return progress 0 w3 := state.Web3{} - if err := w3.Init(internalCtx, w3uri, address, state.TokenType(tokenData.TypeID)); err != nil { + if err := w3.Init(internalCtx, w3URI, address, state.TokenType(tokenData.TypeID)); err != nil { return ErrInitializingWeb3.WithErr(err) } // fetch the last block header and calculate progress diff --git a/api/types.go b/api/types.go index 9b625a99..6ac051c1 100644 --- a/api/types.go +++ b/api/types.go @@ -1,5 +1,15 @@ package api +type SupportedChain struct { + ChainID uint64 `json:"chainID"` + ShortName string `json:"shortName"` + Name string `json:"name"` +} + +type APIInfo struct { + SupportedChains []SupportedChain `json:"supportedChains"` +} + type CreateTokenRequest struct { ID string `json:"ID"` Type string `json:"type"` diff --git a/service/holders_scanner.go b/service/holders_scanner.go index 1654e92c..b1971d68 100644 --- a/service/holders_scanner.go +++ b/service/holders_scanner.go @@ -29,7 +29,7 @@ var ( // the tokens stored on the database (located on 'dataDir/dbFilename'). It // keeps the database updated scanning the network using the web3 endpoint. type HoldersScanner struct { - w3p map[uint64]string + w3p state.Web3Providers tokens map[common.Address]*state.TokenHolders mutex sync.RWMutex db *db.DB @@ -39,7 +39,7 @@ type HoldersScanner struct { // NewHoldersScanner function creates a new HolderScanner using the dataDir path // and the web3 endpoint URI provided. It sets up a sqlite3 database instance // and gets the number of last block scanned from it. -func NewHoldersScanner(db *db.DB, w3p map[uint64]string) (*HoldersScanner, error) { +func NewHoldersScanner(db *db.DB, w3p state.Web3Providers) (*HoldersScanner, error) { if db == nil { return nil, ErrNoDB } @@ -178,13 +178,13 @@ func (s *HoldersScanner) saveHolders(th *state.TokenHolders) error { return nil } // get correct web3 uri provider - w3uri, exists := s.w3p[th.ChainID] + w3URI, exists := s.w3p.URIByChainID(th.ChainID) if !exists { return fmt.Errorf("chain ID not supported") } // init web3 contract state w3 := state.Web3{} - if err := w3.Init(ctx, w3uri, th.Address(), th.Type()); err != nil { + if err := w3.Init(ctx, w3URI, th.Address(), th.Type()); err != nil { return err } // get current block number timestamp and root hash, required parameters to @@ -327,13 +327,13 @@ func (s *HoldersScanner) scanHolders(ctx context.Context, addr common.Address) ( s.lastBlock = th.LastBlock() } // get correct web3 uri provider - w3uri, exists := s.w3p[th.ChainID] + w3URI, exists := s.w3p.URIByChainID(th.ChainID) if !exists { return false, fmt.Errorf("chain ID not supported") } // init web3 contract state w3 := state.Web3{} - if err := w3.Init(ctx, w3uri, addr, th.Type()); err != nil { + if err := w3.Init(ctx, w3URI, addr, th.Type()); err != nil { return th.IsSynced(), err } // try to update the TokenHolders struct and the current scanner last block @@ -378,13 +378,13 @@ func (s *HoldersScanner) calcTokenCreationBlock(ctx context.Context, addr common } ttype := state.TokenType(tokenInfo.TypeID) // get correct web3 uri provider - w3uri, exists := s.w3p[tokenInfo.ChainID] + w3URI, exists := s.w3p.URIByChainID(tokenInfo.ChainID) if !exists { return fmt.Errorf("chain ID not supported") } // init web3 contract state w3 := state.Web3{} - if err := w3.Init(ctx, w3uri, addr, ttype); err != nil { + if err := w3.Init(ctx, w3URI, addr, ttype); err != nil { return fmt.Errorf("error intializing web3 client for this token: %w", err) } // get creation block of the current token contract diff --git a/state/const.go b/state/const.go index aa30a8db..792b3704 100644 --- a/state/const.go +++ b/state/const.go @@ -1,7 +1,14 @@ package state +import "time" + const timeLayout = "2006-01-02T15:04:05Z07:00" +const ( + shortNameSourceUri = "https://chainid.network/chains_mini.json" + checkWeb3ProvidersTimeout = time.Second * 10 +) + const ( // OTHER CONSTANTS MAX_SCAN_BLOCKS_PER_ITERATION = 1000000 diff --git a/state/providers.go b/state/providers.go index b51bf1c2..00105255 100644 --- a/state/providers.go +++ b/state/providers.go @@ -2,32 +2,113 @@ package state import ( "context" + "encoding/json" "fmt" - "time" + "net/http" "github.com/ethereum/go-ethereum/ethclient" ) -func CheckWeb3Providers(providersURIs []string) (map[uint64]string, error) { +// Web3Provider struct contains all the required information about a web3 +// provider based on its URI. It includes its chain ID, its name (and shortName) +// and the URI. +type Web3Provider struct { + ChainID uint64 `json:"chainId"` + Name string `json:"name"` + ShortName string `json:"shortName"` + URI string +} + +// Web3Providers type envolves a map of uint64-Web3Provider, used to index the +// configured web3 providers by the chainID. +type Web3Providers map[uint64]Web3Provider + +// URIByChainID method returns the URI configured for the chainID provided. +func (w3p Web3Providers) URIByChainID(chainID uint64) (string, bool) { + provider, ok := w3p[chainID] + if !ok { + return "", false + } + return provider.URI, true +} + +// ChainIDByShortName method returns the chainID configured for the network +// short name provided. +func (w3p Web3Providers) ChainIDByShortName(shortName string) (uint64, bool) { + for _, provider := range w3p { + if provider.ShortName == shortName { + return provider.ChainID, true + } + } + return 0, false +} + +// PrefixBlockNumber method returns a prefixed string of the block number +// provided, with the short name of the network identified by the chain id +// provided. +func (w3p Web3Providers) PrefixBlockNumber(chainID, blockNumber uint64) (string, bool) { + provider, ok := w3p[chainID] + if !ok { + return "", false + } + return fmt.Sprintf("%s:%d", provider.ShortName, blockNumber), true +} + +// PrefixSymbol method returns a prefixed string of the block number +// provided, with the short name of the network identified by the chain id +// provided. +func (w3p Web3Providers) PrefixSymbol(chainID uint64, symbol string) (string, bool) { + provider, ok := w3p[chainID] + if !ok { + return "", false + } + return fmt.Sprintf("%s:%s", provider.ShortName, symbol), true +} + +// CheckWeb3Providers function initializes a Web3Providers list checking the +// web3 enpoint URI's provided as argument. It checks if the URI's are valid, +// getting its chain ID's and then query to shortNameSourceURI endpoint to get +// the chain name and short name. +func CheckWeb3Providers(providersURIs []string) (Web3Providers, error) { if len(providersURIs) == 0 { return nil, fmt.Errorf("no URIs provided") } - - providers := make(map[uint64]string) + // get chains information from external source + res, err := http.Get(shortNameSourceUri) + if err != nil { + return nil, fmt.Errorf("error getting chains information from external source: %v", err) + } + chainsData := []Web3Provider{} + if err := json.NewDecoder(res.Body).Decode(&chainsData); err != nil { + return nil, fmt.Errorf("error decoding chains information from external source: %v", err) + } + providers := make(Web3Providers) for _, uri := range providersURIs { cli, err := ethclient.Dial(uri) if err != nil { return nil, fmt.Errorf("error dialing web3 provider uri '%s': %w", uri, err) } - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), checkWeb3ProvidersTimeout) defer cancel() // get the chainID from the web3 endpoint chainID, err := cli.ChainID(ctx) if err != nil { return nil, fmt.Errorf("error getting the chainID from the web3 provider '%s': %w", uri, err) } - providers[uint64(chainID.Int64())] = uri + // get chain shortName + ok := false + for _, info := range chainsData { + if info.ChainID == chainID.Uint64() { + ok = true + info.URI = uri + providers[info.ChainID] = info + break + } + } + if !ok { + return nil, fmt.Errorf("information about %d chain not found", chainID.Uint64()) + } } return providers, nil } From 01249ab70c61be3658194143b2b5bab5f03a6b9f Mon Sep 17 00:00:00 2001 From: Lucas Menendez Date: Wed, 4 Oct 2023 14:04:21 +0200 Subject: [PATCH 4/4] linter fixes --- api/api.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/api.go b/api/api.go index 400df9b0..44450ca2 100644 --- a/api/api.go +++ b/api/api.go @@ -75,7 +75,6 @@ func (capi *census3API) initAPIHandlers() error { } func (capi *census3API) getAPIInfo(msg *api.APIdata, ctx *httprouter.HTTPContext) error { - info := &APIInfo{ SupportedChains: []SupportedChain{}, }