-
-
Save bonedaddy/2cb00701c84fdda3fa467a96a10ab6eb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package multicall | |
import ( | |
"context" | |
"math/big" | |
bindings "github.com/bonedaddy/<redacted>/bindings/multicall" | |
"github.com/ethereum/go-ethereum/accounts/abi/bind" | |
"github.com/ethereum/go-ethereum/common" | |
) | |
// Multicall exposes utility functions around the multicall contract | |
type Multicall struct { | |
backend bind.ContractBackend | |
binding *bindings.Multicall | |
ctx context.Context | |
cancel context.CancelFunc | |
} | |
// New initializes the multicall contract wrapper package | |
func New(ctx context.Context, addr string, backend bind.ContractBackend) (*Multicall, error) { | |
ctx, cancel := context.WithCancel(ctx) | |
binding, err := bindings.NewMulticall(common.HexToAddress(addr), backend) | |
if err != nil { | |
cancel() | |
return nil, err | |
} | |
return &Multicall{ | |
backend: backend, | |
binding: binding, | |
ctx: ctx, | |
cancel: cancel, | |
}, nil | |
} | |
// GetDenormalizedWeights returns the denormalized weights of all given tokens | |
func (m *Multicall) GetDenormalizedWeights( | |
block uint64, | |
pool string, | |
tokens []string, | |
) ([]common.Address, []*big.Int, error) { | |
poolAddr := common.HexToAddress(pool) | |
var tokenAddrs = make([]common.Address, len(tokens)) | |
for i, tok := range tokens { | |
tokenAddrs[i] = common.HexToAddress(tok) | |
} | |
return m.binding.GetDenormalizedWeights( | |
&bind.CallOpts{ | |
Context: m.ctx, | |
BlockNumber: new(big.Int).SetUint64(block), | |
}, | |
poolAddr, | |
tokenAddrs, | |
) | |
} | |
// GetBalances returns the balances of various tokens | |
func (m *Multicall) GetBalances( | |
block uint64, | |
pool string, | |
tokens []string, | |
) ([]common.Address, []*big.Int, error) { | |
poolAddr := common.HexToAddress(pool) | |
var tokenAddrs = make([]common.Address, len(tokens)) | |
for i, tok := range tokens { | |
tokenAddrs[i] = common.HexToAddress(tok) | |
} | |
return m.binding.GetBalances( | |
&bind.CallOpts{ | |
Context: m.ctx, | |
BlockNumber: new(big.Int).SetUint64(block), | |
}, | |
poolAddr, | |
tokenAddrs, | |
) | |
} | |
// GetUsedBalances returns the used balances of various tokens | |
func (m *Multicall) GetUsedBalances( | |
block uint64, | |
pool string, | |
tokens []string, | |
) ([]common.Address, []*big.Int, error) { | |
poolAddr := common.HexToAddress(pool) | |
var tokenAddrs = make([]common.Address, len(tokens)) | |
for i, tok := range tokens { | |
tokenAddrs[i] = common.HexToAddress(tok) | |
} | |
return m.binding.GetUsedBalances( | |
&bind.CallOpts{ | |
Context: m.ctx, | |
BlockNumber: new(big.Int).SetUint64(block), | |
}, | |
poolAddr, | |
tokenAddrs, | |
) | |
} | |
// GetSpotPrices returns the spot prices of various in/out pairs | |
func (m *Multicall) GetSpotPrices( | |
block uint64, | |
pool string, | |
tokensIn []string, | |
tokensOut []string, | |
) ([]common.Address, []common.Address, []*big.Int, error) { | |
poolAddr := common.HexToAddress(pool) | |
var ( | |
tokenInAddrs = make([]common.Address, len(tokensIn)) | |
tokenOutAddrs = make([]common.Address, len(tokensOut)) | |
) | |
for i, tok := range tokensIn { | |
tokenInAddrs[i] = common.HexToAddress(tok) | |
} | |
for i, tok := range tokensOut { | |
tokenOutAddrs[i] = common.HexToAddress(tok) | |
} | |
return m.binding.GetSpotPrices( | |
&bind.CallOpts{ | |
Context: m.ctx, | |
BlockNumber: new(big.Int).SetUint64(block), | |
}, | |
poolAddr, | |
tokenInAddrs, | |
tokenOutAddrs, | |
) | |
} | |
// GetTotalSupplies returns the total supplies of various tokens | |
func (m *Multicall) GetTotalSupplies( | |
block uint64, | |
tokens []string, | |
) ([]common.Address, []*big.Int, error) { | |
var tokenAddrs = make([]common.Address, len(tokens)) | |
for i, tok := range tokens { | |
tokenAddrs[i] = common.HexToAddress(tok) | |
} | |
return m.binding.GetTotalSupplies( | |
&bind.CallOpts{ | |
Context: m.ctx, | |
BlockNumber: new(big.Int).SetUint64(block), | |
}, | |
tokenAddrs, | |
) | |
} | |
// Close terminates the context | |
func (m *Multicall) Close() { | |
m.cancel() | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code generated - DO NOT EDIT. | |
// This file is a generated binding and any manual changes will be lost. | |
package multicall | |
import ( | |
"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 ( | |
_ = big.NewInt | |
_ = strings.NewReader | |
_ = ethereum.NotFound | |
_ = bind.Bind | |
_ = common.Big1 | |
_ = types.BloomLookup | |
_ = event.NewSubscription | |
) | |
// MulticallABI is the input ABI used to generate the binding from. | |
const MulticallABI = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getBalances\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getDenormalizedWeights\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"inTokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"outTokens\",\"type\":\"address[]\"}],\"name\":\"getSpotPrices\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTotalSupplies\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getUsedBalances\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" | |
// MulticallBin is the compiled bytecode used for deploying new contracts. | |
var MulticallBin = "0x608060405234801561001057600080fd5b50610b3c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632dd43d891461005c5780636a385ae91461019657806395d7710e14610247578063db16d8ac146102f8578063f7a6b6b6146103a9575b600080fd5b6100fd6004803603602081101561007257600080fd5b810190602081018135600160201b81111561008c57600080fd5b82018360208201111561009e57600080fd5b803590602001918460208302840111600160201b831117156100bf57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506105ba945050505050565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610141578181015183820152602001610129565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610180578181015183820152602001610168565b5050505090500194505050505060405180910390f35b6100fd600480360360408110156101ac57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156101d657600080fd5b8201836020820111156101e857600080fd5b803590602001918460208302840111600160201b8311171561020957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506106b1945050505050565b6100fd6004803603604081101561025d57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561028757600080fd5b82018360208201111561029957600080fd5b803590602001918460208302840111600160201b831117156102ba57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506107be945050505050565b6100fd6004803603604081101561030e57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561033857600080fd5b82018360208201111561034a57600080fd5b803590602001918460208302840111600160201b8311171561036b57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506108c1945050505050565b6104dc600480360360608110156103bf57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156103e957600080fd5b8201836020820111156103fb57600080fd5b803590602001918460208302840111600160201b8311171561041c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561046b57600080fd5b82018360208201111561047d57600080fd5b803590602001918460208302840111600160201b8311171561049e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506109c4945050505050565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561052457818101518382015260200161050c565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561056357818101518382015260200161054b565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156105a257818101518382015260200161058a565b50505050905001965050505050505060405180910390f35b6060806060835167ffffffffffffffff811180156105d757600080fd5b50604051908082528060200260200182016040528015610601578160200160208202803683370190505b50905060005b84518110156106a95784818151811061061c57fe5b60200260200101516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561065c57600080fd5b505afa158015610670573d6000803e3d6000fd5b505050506040513d602081101561068657600080fd5b5051825183908390811061069657fe5b6020908102919091010152600101610607565b509293915050565b6060806060835167ffffffffffffffff811180156106ce57600080fd5b506040519080825280602002602001820160405280156106f8578160200160208202803683370190505b50905060005b84518110156107b457856001600160a01b031663f8b2cb4f86838151811061072257fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561076757600080fd5b505afa15801561077b573d6000803e3d6000fd5b505050506040513d602081101561079157600080fd5b505182518390839081106107a157fe5b60209081029190910101526001016106fe565b5092949293505050565b6060806060835167ffffffffffffffff811180156107db57600080fd5b50604051908082528060200260200182016040528015610805578160200160208202803683370190505b50905060005b84518110156107b457856001600160a01b0316634aa4e0b586838151811061082f57fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561087457600080fd5b505afa158015610888573d6000803e3d6000fd5b505050506040513d602081101561089e57600080fd5b505182518390839081106108ae57fe5b602090810291909101015260010161080b565b6060806060835167ffffffffffffffff811180156108de57600080fd5b50604051908082528060200260200182016040528015610908578160200160208202803683370190505b50905060005b84518110156107b457856001600160a01b031663948d8ce686838151811061093257fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d60208110156109a157600080fd5b505182518390839081106109b157fe5b602090810291909101015260010161090e565b606080606083518551146109d757600080fd5b6060855167ffffffffffffffff811180156109f157600080fd5b50604051908082528060200260200182016040528015610a1b578160200160208202803683370190505b50905060005b8651811015610afb57876001600160a01b03166315e84af9888381518110610a4557fe5b6020026020010151888481518110610a5957fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015610aae57600080fd5b505afa158015610ac2573d6000803e3d6000fd5b505050506040513d6020811015610ad857600080fd5b50518251839083908110610ae857fe5b6020908102919091010152600101610a21565b50949693955050505056fea264697066735822122044470bd2564b5e5b98cf0a195bf1b5960c678d1fb0cc4d8bd8cd0424a29be5a064736f6c63430007040033" | |
// DeployMulticall deploys a new Ethereum contract, binding an instance of Multicall to it. | |
func DeployMulticall(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Multicall, error) { | |
parsed, err := abi.JSON(strings.NewReader(MulticallABI)) | |
if err != nil { | |
return common.Address{}, nil, nil, err | |
} | |
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(MulticallBin), backend) | |
if err != nil { | |
return common.Address{}, nil, nil, err | |
} | |
return address, tx, &Multicall{MulticallCaller: MulticallCaller{contract: contract}, MulticallTransactor: MulticallTransactor{contract: contract}, MulticallFilterer: MulticallFilterer{contract: contract}}, nil | |
} | |
// Multicall is an auto generated Go binding around an Ethereum contract. | |
type Multicall struct { | |
MulticallCaller // Read-only binding to the contract | |
MulticallTransactor // Write-only binding to the contract | |
MulticallFilterer // Log filterer for contract events | |
} | |
// MulticallCaller is an auto generated read-only Go binding around an Ethereum contract. | |
type MulticallCaller struct { | |
contract *bind.BoundContract // Generic contract wrapper for the low level calls | |
} | |
// MulticallTransactor is an auto generated write-only Go binding around an Ethereum contract. | |
type MulticallTransactor struct { | |
contract *bind.BoundContract // Generic contract wrapper for the low level calls | |
} | |
// MulticallFilterer is an auto generated log filtering Go binding around an Ethereum contract events. | |
type MulticallFilterer struct { | |
contract *bind.BoundContract // Generic contract wrapper for the low level calls | |
} | |
// MulticallSession is an auto generated Go binding around an Ethereum contract, | |
// with pre-set call and transact options. | |
type MulticallSession struct { | |
Contract *Multicall // 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 | |
} | |
// MulticallCallerSession is an auto generated read-only Go binding around an Ethereum contract, | |
// with pre-set call options. | |
type MulticallCallerSession struct { | |
Contract *MulticallCaller // Generic contract caller binding to set the session for | |
CallOpts bind.CallOpts // Call options to use throughout this session | |
} | |
// MulticallTransactorSession is an auto generated write-only Go binding around an Ethereum contract, | |
// with pre-set transact options. | |
type MulticallTransactorSession struct { | |
Contract *MulticallTransactor // Generic contract transactor binding to set the session for | |
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session | |
} | |
// MulticallRaw is an auto generated low-level Go binding around an Ethereum contract. | |
type MulticallRaw struct { | |
Contract *Multicall // Generic contract binding to access the raw methods on | |
} | |
// MulticallCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. | |
type MulticallCallerRaw struct { | |
Contract *MulticallCaller // Generic read-only contract binding to access the raw methods on | |
} | |
// MulticallTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. | |
type MulticallTransactorRaw struct { | |
Contract *MulticallTransactor // Generic write-only contract binding to access the raw methods on | |
} | |
// NewMulticall creates a new instance of Multicall, bound to a specific deployed contract. | |
func NewMulticall(address common.Address, backend bind.ContractBackend) (*Multicall, error) { | |
contract, err := bindMulticall(address, backend, backend, backend) | |
if err != nil { | |
return nil, err | |
} | |
return &Multicall{MulticallCaller: MulticallCaller{contract: contract}, MulticallTransactor: MulticallTransactor{contract: contract}, MulticallFilterer: MulticallFilterer{contract: contract}}, nil | |
} | |
// NewMulticallCaller creates a new read-only instance of Multicall, bound to a specific deployed contract. | |
func NewMulticallCaller(address common.Address, caller bind.ContractCaller) (*MulticallCaller, error) { | |
contract, err := bindMulticall(address, caller, nil, nil) | |
if err != nil { | |
return nil, err | |
} | |
return &MulticallCaller{contract: contract}, nil | |
} | |
// NewMulticallTransactor creates a new write-only instance of Multicall, bound to a specific deployed contract. | |
func NewMulticallTransactor(address common.Address, transactor bind.ContractTransactor) (*MulticallTransactor, error) { | |
contract, err := bindMulticall(address, nil, transactor, nil) | |
if err != nil { | |
return nil, err | |
} | |
return &MulticallTransactor{contract: contract}, nil | |
} | |
// NewMulticallFilterer creates a new log filterer instance of Multicall, bound to a specific deployed contract. | |
func NewMulticallFilterer(address common.Address, filterer bind.ContractFilterer) (*MulticallFilterer, error) { | |
contract, err := bindMulticall(address, nil, nil, filterer) | |
if err != nil { | |
return nil, err | |
} | |
return &MulticallFilterer{contract: contract}, nil | |
} | |
// bindMulticall binds a generic wrapper to an already deployed contract. | |
func bindMulticall(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { | |
parsed, err := abi.JSON(strings.NewReader(MulticallABI)) | |
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 (_Multicall *MulticallRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { | |
return _Multicall.Contract.MulticallCaller.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 (_Multicall *MulticallRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { | |
return _Multicall.Contract.MulticallTransactor.contract.Transfer(opts) | |
} | |
// Transact invokes the (paid) contract method with params as input values. | |
func (_Multicall *MulticallRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { | |
return _Multicall.Contract.MulticallTransactor.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 (_Multicall *MulticallCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { | |
return _Multicall.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 (_Multicall *MulticallTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { | |
return _Multicall.Contract.contract.Transfer(opts) | |
} | |
// Transact invokes the (paid) contract method with params as input values. | |
func (_Multicall *MulticallTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { | |
return _Multicall.Contract.contract.Transact(opts, method, params...) | |
} | |
// GetBalances is a free data retrieval call binding the contract method 0x6a385ae9. | |
// | |
// Solidity: function getBalances(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCaller) GetBalances(opts *bind.CallOpts, poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
var out []interface{} | |
err := _Multicall.contract.Call(opts, &out, "getBalances", poolAddress, tokens) | |
if err != nil { | |
return *new([]common.Address), *new([]*big.Int), err | |
} | |
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) | |
out1 := *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) | |
return out0, out1, err | |
} | |
// GetBalances is a free data retrieval call binding the contract method 0x6a385ae9. | |
// | |
// Solidity: function getBalances(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallSession) GetBalances(poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetBalances(&_Multicall.CallOpts, poolAddress, tokens) | |
} | |
// GetBalances is a free data retrieval call binding the contract method 0x6a385ae9. | |
// | |
// Solidity: function getBalances(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCallerSession) GetBalances(poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetBalances(&_Multicall.CallOpts, poolAddress, tokens) | |
} | |
// GetDenormalizedWeights is a free data retrieval call binding the contract method 0xdb16d8ac. | |
// | |
// Solidity: function getDenormalizedWeights(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCaller) GetDenormalizedWeights(opts *bind.CallOpts, poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
var out []interface{} | |
err := _Multicall.contract.Call(opts, &out, "getDenormalizedWeights", poolAddress, tokens) | |
if err != nil { | |
return *new([]common.Address), *new([]*big.Int), err | |
} | |
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) | |
out1 := *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) | |
return out0, out1, err | |
} | |
// GetDenormalizedWeights is a free data retrieval call binding the contract method 0xdb16d8ac. | |
// | |
// Solidity: function getDenormalizedWeights(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallSession) GetDenormalizedWeights(poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetDenormalizedWeights(&_Multicall.CallOpts, poolAddress, tokens) | |
} | |
// GetDenormalizedWeights is a free data retrieval call binding the contract method 0xdb16d8ac. | |
// | |
// Solidity: function getDenormalizedWeights(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCallerSession) GetDenormalizedWeights(poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetDenormalizedWeights(&_Multicall.CallOpts, poolAddress, tokens) | |
} | |
// GetSpotPrices is a free data retrieval call binding the contract method 0xf7a6b6b6. | |
// | |
// Solidity: function getSpotPrices(address poolAddress, address[] inTokens, address[] outTokens) view returns(address[], address[], uint256[]) | |
func (_Multicall *MulticallCaller) GetSpotPrices(opts *bind.CallOpts, poolAddress common.Address, inTokens []common.Address, outTokens []common.Address) ([]common.Address, []common.Address, []*big.Int, error) { | |
var out []interface{} | |
err := _Multicall.contract.Call(opts, &out, "getSpotPrices", poolAddress, inTokens, outTokens) | |
if err != nil { | |
return *new([]common.Address), *new([]common.Address), *new([]*big.Int), err | |
} | |
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) | |
out1 := *abi.ConvertType(out[1], new([]common.Address)).(*[]common.Address) | |
out2 := *abi.ConvertType(out[2], new([]*big.Int)).(*[]*big.Int) | |
return out0, out1, out2, err | |
} | |
// GetSpotPrices is a free data retrieval call binding the contract method 0xf7a6b6b6. | |
// | |
// Solidity: function getSpotPrices(address poolAddress, address[] inTokens, address[] outTokens) view returns(address[], address[], uint256[]) | |
func (_Multicall *MulticallSession) GetSpotPrices(poolAddress common.Address, inTokens []common.Address, outTokens []common.Address) ([]common.Address, []common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetSpotPrices(&_Multicall.CallOpts, poolAddress, inTokens, outTokens) | |
} | |
// GetSpotPrices is a free data retrieval call binding the contract method 0xf7a6b6b6. | |
// | |
// Solidity: function getSpotPrices(address poolAddress, address[] inTokens, address[] outTokens) view returns(address[], address[], uint256[]) | |
func (_Multicall *MulticallCallerSession) GetSpotPrices(poolAddress common.Address, inTokens []common.Address, outTokens []common.Address) ([]common.Address, []common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetSpotPrices(&_Multicall.CallOpts, poolAddress, inTokens, outTokens) | |
} | |
// GetTotalSupplies is a free data retrieval call binding the contract method 0x2dd43d89. | |
// | |
// Solidity: function getTotalSupplies(address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCaller) GetTotalSupplies(opts *bind.CallOpts, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
var out []interface{} | |
err := _Multicall.contract.Call(opts, &out, "getTotalSupplies", tokens) | |
if err != nil { | |
return *new([]common.Address), *new([]*big.Int), err | |
} | |
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) | |
out1 := *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) | |
return out0, out1, err | |
} | |
// GetTotalSupplies is a free data retrieval call binding the contract method 0x2dd43d89. | |
// | |
// Solidity: function getTotalSupplies(address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallSession) GetTotalSupplies(tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetTotalSupplies(&_Multicall.CallOpts, tokens) | |
} | |
// GetTotalSupplies is a free data retrieval call binding the contract method 0x2dd43d89. | |
// | |
// Solidity: function getTotalSupplies(address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCallerSession) GetTotalSupplies(tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetTotalSupplies(&_Multicall.CallOpts, tokens) | |
} | |
// GetUsedBalances is a free data retrieval call binding the contract method 0x95d7710e. | |
// | |
// Solidity: function getUsedBalances(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCaller) GetUsedBalances(opts *bind.CallOpts, poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
var out []interface{} | |
err := _Multicall.contract.Call(opts, &out, "getUsedBalances", poolAddress, tokens) | |
if err != nil { | |
return *new([]common.Address), *new([]*big.Int), err | |
} | |
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) | |
out1 := *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) | |
return out0, out1, err | |
} | |
// GetUsedBalances is a free data retrieval call binding the contract method 0x95d7710e. | |
// | |
// Solidity: function getUsedBalances(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallSession) GetUsedBalances(poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetUsedBalances(&_Multicall.CallOpts, poolAddress, tokens) | |
} | |
// GetUsedBalances is a free data retrieval call binding the contract method 0x95d7710e. | |
// | |
// Solidity: function getUsedBalances(address poolAddress, address[] tokens) view returns(address[], uint256[]) | |
func (_Multicall *MulticallCallerSession) GetUsedBalances(poolAddress common.Address, tokens []common.Address) ([]common.Address, []*big.Int, error) { | |
return _Multicall.Contract.GetUsedBalances(&_Multicall.CallOpts, poolAddress, tokens) | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package multicall | |
import ( | |
"context" | |
"os" | |
"testing" | |
"github.com/bonedaddy/bdsm/testenv" | |
"github.com/bonedaddy/<redacted>/bindings/logswap" | |
"github.com/bonedaddy/<redacted>/bindings/multicall" | |
"github.com/bonedaddy/go-indexed/bclient" | |
"github.com/stretchr/testify/require" | |
) | |
var ( | |
infuraAPIKey = os.Getenv("INFURA_API_KEY") | |
defi5ContractAddress = "0xfa6de2697d59e88ed7fc4dfe5a33dac43565ea41" | |
multicallContractAddress = "0x3067b1b7bf344027c7439509fbdf344eb25f5991" | |
defi5Tokens = []string{ | |
"0xc00e94Cb662C3520282E6f5717214004A7f26888", | |
"0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F", | |
"0xD533a949740bb3306d119CC777fa900bA034cd52", | |
"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", | |
"0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9", | |
} | |
) | |
func TestMulticallReal(t *testing.T) { | |
ctx, cancel := context.WithCancel(context.Background()) | |
defer cancel() | |
bc, err := bclient.NewInfuraClient(infuraAPIKey, true) | |
require.NoError(t, err) | |
caller, err := New(ctx, multicallContractAddress, bc.EthClient()) | |
require.NoError(t, err) | |
var defi5TokensReversed []string | |
for i := len(defi5Tokens) - 1; i >= 0; i-- { | |
defi5TokensReversed = append(defi5TokensReversed, defi5Tokens[i]) | |
} | |
// make sure reversal worked | |
require.NotEqual(t, defi5Tokens, defi5TokensReversed) | |
t.Run("GetDenormalizedWeights", func(t *testing.T) { | |
type args struct { | |
pool string | |
addrs []string | |
} | |
tests := []struct { | |
name string | |
args args | |
wantCount int | |
}{ | |
{"DEFI5", args{ | |
defi5ContractAddress, | |
defi5Tokens, | |
}, 5}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
// get the current block number | |
block, err := bc.CurrentBlock() | |
require.NoError(t, err) | |
addrs, values, err := caller.GetDenormalizedWeights( | |
block, | |
tt.args.pool, | |
tt.args.addrs, | |
) | |
require.NoError(t, err) | |
require.Len(t, values, tt.wantCount) | |
require.Len(t, addrs, tt.wantCount) | |
}) | |
} | |
}) | |
t.Run("GetBalances", func(t *testing.T) { | |
type args struct { | |
pool string | |
addrs []string | |
} | |
tests := []struct { | |
name string | |
args args | |
wantCount int | |
}{ | |
{"DEFI5", args{ | |
defi5ContractAddress, | |
defi5Tokens, | |
}, 5}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
// get the current block number | |
block, err := bc.CurrentBlock() | |
require.NoError(t, err) | |
addrs, values, err := caller.GetBalances( | |
block, | |
tt.args.pool, | |
tt.args.addrs, | |
) | |
require.NoError(t, err) | |
require.Len(t, values, tt.wantCount) | |
require.Len(t, addrs, tt.wantCount) | |
}) | |
} | |
}) | |
t.Run("GetUsedBalances", func(t *testing.T) { | |
type args struct { | |
pool string | |
addrs []string | |
} | |
tests := []struct { | |
name string | |
args args | |
wantCount int | |
}{ | |
{"DEFI5", args{ | |
defi5ContractAddress, | |
defi5Tokens, | |
}, 5}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
// get the current block number | |
block, err := bc.CurrentBlock() | |
require.NoError(t, err) | |
addrs, values, err := caller.GetUsedBalances( | |
block, | |
tt.args.pool, | |
tt.args.addrs, | |
) | |
require.NoError(t, err) | |
require.Len(t, values, tt.wantCount) | |
require.Len(t, addrs, tt.wantCount) | |
}) | |
} | |
}) | |
t.Run("GetSpotPrices", func(t *testing.T) { | |
type args struct { | |
pool string | |
addrs []string | |
} | |
tests := []struct { | |
name string | |
args args | |
wantCount int | |
}{ | |
{"DEFI5", args{ | |
defi5ContractAddress, | |
defi5Tokens, | |
}, 5}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
// get the current block number | |
block, err := bc.CurrentBlock() | |
require.NoError(t, err) | |
addrsIn, addrsOut, values, err := caller.GetSpotPrices( | |
block, | |
tt.args.pool, | |
tt.args.addrs, // in | |
defi5TokensReversed, // out | |
) | |
require.NoError(t, err) | |
require.Len(t, values, tt.wantCount) | |
require.Len(t, addrsIn, tt.wantCount) | |
require.Len(t, addrsOut, tt.wantCount) | |
}) | |
} | |
}) | |
t.Run("GetTotalSupplies", func(t *testing.T) { | |
type args struct { | |
addrs []string | |
} | |
tests := []struct { | |
name string | |
args args | |
wantCount int | |
}{ | |
{"DEFI5", args{ | |
defi5Tokens, | |
}, 5}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
// get the current block number | |
block, err := bc.CurrentBlock() | |
require.NoError(t, err) | |
addrs, values, err := caller.GetTotalSupplies( | |
block, | |
tt.args.addrs, | |
) | |
require.NoError(t, err) | |
require.Len(t, values, tt.wantCount) | |
require.Len(t, addrs, tt.wantCount) | |
}) | |
} | |
}) | |
caller.Close() | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.7.0 <0.8.0; | |
/** | |
* @notice this interface is taken from indexed-core commit hash dae7f231d0f58bfc0993f6c01199cd6b74b01895 | |
*/ | |
interface IndexPoolI { | |
function getDenormalizedWeight(address token) external view returns (uint256); | |
function getBalance(address token) external view returns (uint256); | |
function getUsedBalance(address token) external view returns (uint256); | |
function getSpotPrice(address tokenIn, address tokenOut) external view returns (uint256); | |
} | |
interface ERC20I { | |
function totalSupply() external view returns (uint256); | |
} | |
/** | |
* @notice SimpleMultiCall is a multicall-like contract for reading IndexPool information | |
* @notice it is intended to minimize the need for manual abi encoding/decoding | |
* @notice and leverage Golang's abigen to do the heavy lifting | |
*/ | |
contract SimpleMultiCall { | |
// index pool methods | |
function getDenormalizedWeights( | |
address poolAddress, | |
address[] memory tokens | |
) | |
public | |
view | |
returns (address[] memory, uint256[] memory) | |
{ | |
uint256[] memory weights = new uint256[](tokens.length); | |
for (uint256 i = 0; i < tokens.length; i++) { | |
weights[i] = IndexPoolI(poolAddress).getDenormalizedWeight(tokens[i]); | |
} | |
return (tokens, weights); | |
} | |
function getBalances( | |
address poolAddress, | |
address[] memory tokens | |
) | |
public | |
view | |
returns (address[] memory, uint256[] memory) | |
{ | |
uint256[] memory balances = new uint256[](tokens.length); | |
for (uint256 i = 0; i < tokens.length; i++) { | |
balances[i] = IndexPoolI(poolAddress).getBalance(tokens[i]); | |
} | |
return (tokens, balances); | |
} | |
function getUsedBalances( | |
address poolAddress, | |
address[] memory tokens | |
) | |
public | |
view | |
returns (address[] memory, uint256[] memory) | |
{ | |
uint256[] memory balances = new uint256[](tokens.length); | |
for (uint256 i = 0; i < tokens.length; i++) { | |
balances[i] = IndexPoolI(poolAddress).getUsedBalance(tokens[i]); | |
} | |
return (tokens, balances); | |
} | |
function getSpotPrices( | |
address poolAddress, | |
address[] memory inTokens, | |
address[] memory outTokens | |
) | |
public | |
view | |
returns (address[] memory, address[] memory, uint256[] memory) | |
{ | |
require(inTokens.length == outTokens.length); | |
uint256[] memory prices = new uint256[](inTokens.length); | |
for (uint256 i = 0; i < inTokens.length; i++) { | |
prices[i] = IndexPoolI(poolAddress).getSpotPrice(inTokens[i], outTokens[i]); | |
} | |
return (inTokens, outTokens, prices); | |
} | |
// erc20 methods | |
function getTotalSupplies( | |
address[] memory tokens | |
) | |
public | |
view | |
returns (address[] memory, uint256[] memory) | |
{ | |
uint256[] memory supplies = new uint256[](tokens.length); | |
for (uint256 i = 0; i < tokens.length; i++) { | |
supplies[i] = ERC20I(tokens[i]).totalSupply(); | |
} | |
return (tokens, supplies); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment