From e76d3c98bbe473ba0c9bee772bbfcd43b72c4e0d Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Mon, 2 Sep 2024 09:54:22 +0300 Subject: [PATCH 1/3] - added migration batch creator components - added migration tool boiler plate code --- cmd/migration/config/config.toml | 50 + cmd/migration/config/migration.json | 19 + cmd/migration/disabled/statusHandler.go | 34 + cmd/migration/flags.go | 46 + cmd/migration/keys/ethereum.sk | 1 + cmd/migration/main.go | 176 ++ config/config.go | 13 + config/tomlConfigs_test.go | 116 ++ .../bridgeV2Wrappers/ERC20Safe.abi.json | 763 ++++++++ .../ethereum/bridgeV2Wrappers/ERC20Safe.go | 1654 +++++++++++++++++ executors/ethereum/common.go | 25 + executors/ethereum/errors.go | 9 + executors/ethereum/interface.go | 27 + executors/ethereum/migrationBatchCreator.go | 130 ++ 14 files changed, 3063 insertions(+) create mode 100644 cmd/migration/config/config.toml create mode 100644 cmd/migration/config/migration.json create mode 100644 cmd/migration/disabled/statusHandler.go create mode 100644 cmd/migration/flags.go create mode 100644 cmd/migration/keys/ethereum.sk create mode 100644 cmd/migration/main.go create mode 100644 executors/ethereum/bridgeV2Wrappers/ERC20Safe.abi.json create mode 100644 executors/ethereum/bridgeV2Wrappers/ERC20Safe.go create mode 100644 executors/ethereum/common.go create mode 100644 executors/ethereum/errors.go create mode 100644 executors/ethereum/interface.go create mode 100644 executors/ethereum/migrationBatchCreator.go diff --git a/cmd/migration/config/config.toml b/cmd/migration/config/config.toml new file mode 100644 index 00000000..77cfefc0 --- /dev/null +++ b/cmd/migration/config/config.toml @@ -0,0 +1,50 @@ +[Eth] + Chain = "Ethereum" + NetworkAddress = "http://127.0.0.1:8545" # a network address + PrivateKeyFile = "keys/ethereum.sk" # the path to the file containing the relayer eth private key + SafeContractAddress = "A6504Cc508889bbDBd4B748aFf6EA6b5D0d2684c" + GasLimitBase = 350000 + GasLimitForEach = 30000 + [Eth.GasStation] + Enabled = true + URL = "https://api.etherscan.io/api?module=gastracker&action=gasoracle" # gas station URL. Suggestion to provide the api-key here + GasPriceMultiplier = 1000000000 # the value to be multiplied with the fetched value. Useful in test chains. On production chain should be 1000000000 + PollingIntervalInSeconds = 60 # number of seconds between gas price polling + RequestRetryDelayInSeconds = 5 # number of seconds of delay after one failed request + MaxFetchRetries = 3 # number of fetch retries before printing an error + RequestTimeInSeconds = 2 # maximum timeout (in seconds) for the gas price request + MaximumAllowedGasPrice = 300 # maximum value allowed for the fetched gas price value + # GasPriceSelector available options: "SafeGasPrice", "ProposeGasPrice", "FastGasPrice" + GasPriceSelector = "SafeGasPrice" # selector used to provide the gas price + +[MultiversX] + NetworkAddress = "https://devnet-gateway.multiversx.com" # the network address + SafeContractAddress = "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus" # the multiversx address for the safe contract + [MultiversX.Proxy] + CacherExpirationSeconds = 600 # the caching time in seconds + + # valid options for ProxyRestAPIEntityType are "observer" and "proxy". Any other value will trigger an error. + # "observer" is useful when querying an observer, directly and "proxy" is useful when querying a squad's proxy (gateway) + RestAPIEntityType = "observer" + FinalityCheck = true + MaxNoncesDelta = 7 # the number of maximum blocks allowed to be "in front" of what the metachain has notarized + +[Logs] + LogFileLifeSpanInSec = 86400 # 24h + LogFileLifeSpanInMB = 1024 # 1GB + +[WhitelistedTokens] + List = [ + "ETHUSDC-220753", + "ETHUTK-8cdf7a", + "ETHUSDT-9c73c6", + "ETHBUSD-450923", + "ETHHMT-18538a", + "ETHCGG-ee4e0c", + "ETHINFRA-60a3bf", + "ETHWBTC-74e282", + "ETHWETH-e1c126", + "ETHWSDAI-572803", + "ETHWDAI-bd65f9", + "ETHUMB-291202", + ] diff --git a/cmd/migration/config/migration.json b/cmd/migration/config/migration.json new file mode 100644 index 00000000..4698c37e --- /dev/null +++ b/cmd/migration/config/migration.json @@ -0,0 +1,19 @@ +{ + "OldSafeContractAddress": "A6504Cc508889bbDBd4B748aFf6EA6b5D0d2684c", + "NewSafeContractAddress": "3009d97FfeD62E57d444e552A9eDF9Ee6Bc8644c", + "BatchID": 22222, + "DepositsInfo": [ + { + "DepositNonce": 1, + "Token": "USDC", + "ContractAddress": "ssss", + "Amount": "11111111111" + }, + { + "DepositNonce": 2, + "Token": "MEME", + "ContractAddress": "ssss", + "Amount": "2222222" + } + ] +} \ No newline at end of file diff --git a/cmd/migration/disabled/statusHandler.go b/cmd/migration/disabled/statusHandler.go new file mode 100644 index 00000000..7949c9cb --- /dev/null +++ b/cmd/migration/disabled/statusHandler.go @@ -0,0 +1,34 @@ +package disabled + +import "github.com/multiversx/mx-bridge-eth-go/core" + +// StatusHandler represents the disabled status handler implementation +type StatusHandler struct { +} + +// SetIntMetric does nothing +func (handler *StatusHandler) SetIntMetric(_ string, _ int) { +} + +// AddIntMetric does nothing +func (handler *StatusHandler) AddIntMetric(_ string, _ int) { +} + +// SetStringMetric does nothing +func (handler *StatusHandler) SetStringMetric(_ string, _ string) { +} + +// Name returns an empty string +func (handler *StatusHandler) Name() string { + return "" +} + +// GetAllMetrics returns an empty map +func (handler *StatusHandler) GetAllMetrics() core.GeneralMetrics { + return make(core.GeneralMetrics) +} + +// IsInterfaceNil returns true if there is no value under the interface +func (handler *StatusHandler) IsInterfaceNil() bool { + return handler == nil +} diff --git a/cmd/migration/flags.go b/cmd/migration/flags.go new file mode 100644 index 00000000..2afce5a0 --- /dev/null +++ b/cmd/migration/flags.go @@ -0,0 +1,46 @@ +package main + +import ( + "github.com/multiversx/mx-bridge-eth-go/config" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/urfave/cli" +) + +var ( + logLevel = cli.StringFlag{ + Name: "log-level", + Usage: "This flag specifies the logger `level(s)`. It can contain multiple comma-separated value. For example" + + ", if set to *:INFO the logs for all packages will have the INFO level. However, if set to *:INFO,api:DEBUG" + + " the logs for all packages will have the INFO level, excepting the api package which will receive a DEBUG" + + " log level.", + Value: "*:" + logger.LogDebug.String(), + } + // configurationFile defines a flag for the path to the main toml configuration file + configurationFile = cli.StringFlag{ + Name: "config", + Usage: "The `" + filePathPlaceholder + "` for the main configuration file. This TOML file contain the main " + + "configurations such as storage setups, epoch duration and so on.", + Value: "config/config.toml", + } + mode = cli.StringFlag{ + Name: "mode", + Usage: "This flag specifies the operation mode. Usage: generate, sign or execute", + Value: generateMode, + } +) + +func getFlags() []cli.Flag { + return []cli.Flag{ + logLevel, + configurationFile, + mode, + } +} +func getFlagsConfig(ctx *cli.Context) config.ContextFlagsConfig { + flagsConfig := config.ContextFlagsConfig{} + + flagsConfig.LogLevel = ctx.GlobalString(logLevel.Name) + flagsConfig.ConfigurationFile = ctx.GlobalString(configurationFile.Name) + + return flagsConfig +} diff --git a/cmd/migration/keys/ethereum.sk b/cmd/migration/keys/ethereum.sk new file mode 100644 index 00000000..5675c4b6 --- /dev/null +++ b/cmd/migration/keys/ethereum.sk @@ -0,0 +1 @@ +9bb971db41e3815a669a71c3f1bcb24e0b81f21e04bf11faa7a34b9b40e7cfb1 diff --git a/cmd/migration/main.go b/cmd/migration/main.go new file mode 100644 index 00000000..9efb7687 --- /dev/null +++ b/cmd/migration/main.go @@ -0,0 +1,176 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strings" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + ethereumClient "github.com/multiversx/mx-bridge-eth-go/clients/ethereum" + "github.com/multiversx/mx-bridge-eth-go/clients/multiversx" + "github.com/multiversx/mx-bridge-eth-go/clients/multiversx/mappers" + "github.com/multiversx/mx-bridge-eth-go/cmd/migration/disabled" + "github.com/multiversx/mx-bridge-eth-go/config" + "github.com/multiversx/mx-bridge-eth-go/executors/ethereum" + chainCore "github.com/multiversx/mx-chain-core-go/core" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-sdk-go/blockchain" + sdkCore "github.com/multiversx/mx-sdk-go/core" + "github.com/multiversx/mx-sdk-go/data" + "github.com/urfave/cli" +) + +const ( + filePathPlaceholder = "[path]" + generateMode = "generate" + signMode = "sign" + executeMode = "execute" +) + +var log = logger.GetOrCreate("main") + +func main() { + app := cli.NewApp() + app.Name = "Funds migration CLI tool" + app.Usage = "This is the entry point for the migration CLI tool" + app.Flags = getFlags() + app.Authors = []cli.Author{ + { + Name: "The MultiversX Team", + Email: "contact@multiversx.com", + }, + } + + app.Action = func(c *cli.Context) error { + return execute(c) + } + + err := app.Run(os.Args) + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } +} + +func execute(ctx *cli.Context) error { + flagsConfig := getFlagsConfig(ctx) + + err := logger.SetLogLevel(flagsConfig.LogLevel) + if err != nil { + return err + } + + cfg, err := loadConfig(flagsConfig.ConfigurationFile) + if err != nil { + return err + } + + log.Info("starting migration help tool", "pid", os.Getpid()) + + operationMode := strings.ToLower(ctx.GlobalString(mode.Name)) + switch operationMode { + case generateMode: + return generate(cfg) + case signMode: + //TODO: implement + case executeMode: + //TODO: implement + } + + return fmt.Errorf("unknown execution mode: %s", operationMode) +} + +func generate(cfg config.MigrationToolConfig) error { + argsProxy := blockchain.ArgsProxy{ + ProxyURL: cfg.MultiversX.NetworkAddress, + SameScState: false, + ShouldBeSynced: false, + FinalityCheck: cfg.MultiversX.Proxy.FinalityCheck, + AllowedDeltaToFinal: cfg.MultiversX.Proxy.MaxNoncesDelta, + CacheExpirationTime: time.Second * time.Duration(cfg.MultiversX.Proxy.CacherExpirationSeconds), + EntityType: sdkCore.RestAPIEntityType(cfg.MultiversX.Proxy.RestAPIEntityType), + } + proxy, err := blockchain.NewProxy(argsProxy) + if err != nil { + return err + } + + emptyAddress := data.NewAddressFromBytes(make([]byte, 0)) + safeAddress, err := data.NewAddressFromBech32String(cfg.MultiversX.SafeContractAddress) + if err != nil { + return err + } + + argsMXClientDataGetter := multiversx.ArgsMXClientDataGetter{ + MultisigContractAddress: emptyAddress, + SafeContractAddress: safeAddress, + RelayerAddress: emptyAddress, + Proxy: proxy, + Log: log, + } + mxDataGetter, err := multiversx.NewMXClientDataGetter(argsMXClientDataGetter) + if err != nil { + return err + } + + tokensWrapper, err := mappers.NewMultiversXToErc20Mapper(mxDataGetter) + if err != nil { + return err + } + + ethClient, err := ethclient.Dial(cfg.Eth.NetworkAddress) + if err != nil { + return err + } + + argsContractsHolder := ethereumClient.ArgsErc20SafeContractsHolder{ + EthClient: ethClient, + EthClientStatusHandler: &disabled.StatusHandler{}, + } + erc20ContractsHolder, err := ethereumClient.NewErc20SafeContractsHolder(argsContractsHolder) + if err != nil { + return err + } + + argsCreator := ethereum.ArgsMigrationBatchCreator{ + TokensList: cfg.WhitelistedTokens.List, + TokensMapper: tokensWrapper, + Erc20ContractsHolder: erc20ContractsHolder, + SafeContractAddress: common.Address{}, + SafeContractWrapper: nil, + } + + creator, err := ethereum.NewMigrationBatchCreator(argsCreator) + if err != nil { + return err + } + + batchInfo, err := creator.CreateBatchInfo(context.Background()) + if err != nil { + return err + } + + //TODO: save in a file + val, err := json.MarshalIndent(batchInfo, "", " ") + if err != nil { + return err + } + + log.Info(string(val)) + + return nil +} + +func loadConfig(filepath string) (config.MigrationToolConfig, error) { + cfg := config.MigrationToolConfig{} + err := chainCore.LoadTomlFile(&cfg, filepath) + if err != nil { + return config.MigrationToolConfig{}, err + } + + return cfg, nil +} diff --git a/config/config.go b/config/config.go index 1976d3d0..916126db 100644 --- a/config/config.go +++ b/config/config.go @@ -205,3 +205,16 @@ type ScCallsModuleConfig struct { FilterConfig PendingOperationsFilterConfig Logs LogsConfig } + +// WhitelistedTokensConfig will hold the whitelisted tokens config +type WhitelistedTokensConfig struct { + List []string +} + +// MigrationToolConfig is the migration tool config struct +type MigrationToolConfig struct { + Eth EthereumConfig + MultiversX MultiversXConfig + Logs LogsConfig + WhitelistedTokens WhitelistedTokensConfig +} diff --git a/config/tomlConfigs_test.go b/config/tomlConfigs_test.go index 7163fd9d..30f79d3b 100644 --- a/config/tomlConfigs_test.go +++ b/config/tomlConfigs_test.go @@ -456,3 +456,119 @@ PollingIntervalInMillis = 6000 require.Equal(t, expectedConfig, cfg) } + +func TestMigrationToolConfig(t *testing.T) { + t.Parallel() + + expectedConfig := MigrationToolConfig{ + Eth: EthereumConfig{ + Chain: "Ethereum", + NetworkAddress: "http://127.0.0.1:8545", + SafeContractAddress: "A6504Cc508889bbDBd4B748aFf6EA6b5D0d2684c", + PrivateKeyFile: "keys/ethereum.sk", + GasLimitBase: 350000, + GasLimitForEach: 30000, + GasStation: GasStationConfig{ + Enabled: true, + URL: "https://api.etherscan.io/api?module=gastracker&action=gasoracle", + PollingIntervalInSeconds: 60, + RequestRetryDelayInSeconds: 5, + MaxFetchRetries: 3, + RequestTimeInSeconds: 2, + MaximumAllowedGasPrice: 300, + GasPriceSelector: "SafeGasPrice", + GasPriceMultiplier: 1000000000, + }, + }, + MultiversX: MultiversXConfig{ + NetworkAddress: "https://devnet-gateway.multiversx.com", + SafeContractAddress: "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus", + Proxy: ProxyConfig{ + CacherExpirationSeconds: 600, + RestAPIEntityType: "observer", + MaxNoncesDelta: 7, + FinalityCheck: true, + }, + }, + Logs: LogsConfig{ + LogFileLifeSpanInSec: 86400, + LogFileLifeSpanInMB: 1024, + }, + WhitelistedTokens: WhitelistedTokensConfig{ + List: []string{ + "ETHUSDC-220753", + "ETHUTK-8cdf7a", + "ETHUSDT-9c73c6", + "ETHBUSD-450923", + "ETHHMT-18538a", + "ETHCGG-ee4e0c", + "ETHINFRA-60a3bf", + "ETHWBTC-74e282", + "ETHWETH-e1c126", + "ETHWSDAI-572803", + "ETHWDAI-bd65f9", + "ETHUMB-291202", + }, + }, + } + + testString := ` +[Eth] + Chain = "Ethereum" + NetworkAddress = "http://127.0.0.1:8545" # a network address + PrivateKeyFile = "keys/ethereum.sk" # the path to the file containing the relayer eth private key + SafeContractAddress = "A6504Cc508889bbDBd4B748aFf6EA6b5D0d2684c" + GasLimitBase = 350000 + GasLimitForEach = 30000 + [Eth.GasStation] + Enabled = true + URL = "https://api.etherscan.io/api?module=gastracker&action=gasoracle" # gas station URL. Suggestion to provide the api-key here + GasPriceMultiplier = 1000000000 # the value to be multiplied with the fetched value. Useful in test chains. On production chain should be 1000000000 + PollingIntervalInSeconds = 60 # number of seconds between gas price polling + RequestRetryDelayInSeconds = 5 # number of seconds of delay after one failed request + MaxFetchRetries = 3 # number of fetch retries before printing an error + RequestTimeInSeconds = 2 # maximum timeout (in seconds) for the gas price request + MaximumAllowedGasPrice = 300 # maximum value allowed for the fetched gas price value + # GasPriceSelector available options: "SafeGasPrice", "ProposeGasPrice", "FastGasPrice" + GasPriceSelector = "SafeGasPrice" # selector used to provide the gas price + +[MultiversX] + NetworkAddress = "https://devnet-gateway.multiversx.com" # the network address + SafeContractAddress = "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus" # the multiversx address for the safe contract + [MultiversX.Proxy] + CacherExpirationSeconds = 600 # the caching time in seconds + + # valid options for ProxyRestAPIEntityType are "observer" and "proxy". Any other value will trigger an error. + # "observer" is useful when querying an observer, directly and "proxy" is useful when querying a squad's proxy (gateway) + RestAPIEntityType = "observer" + FinalityCheck = true + MaxNoncesDelta = 7 # the number of maximum blocks allowed to be "in front" of what the metachain has notarized + +[Logs] + LogFileLifeSpanInSec = 86400 # 24h + LogFileLifeSpanInMB = 1024 # 1GB + +[WhitelistedTokens] + List = [ + "ETHUSDC-220753", + "ETHUTK-8cdf7a", + "ETHUSDT-9c73c6", + "ETHBUSD-450923", + "ETHHMT-18538a", + "ETHCGG-ee4e0c", + "ETHINFRA-60a3bf", + "ETHWBTC-74e282", + "ETHWETH-e1c126", + "ETHWSDAI-572803", + "ETHWDAI-bd65f9", + "ETHUMB-291202", + ] +` + + cfg := MigrationToolConfig{} + + err := toml.Unmarshal([]byte(testString), &cfg) + + require.Nil(t, err) + require.Equal(t, expectedConfig, cfg) +} diff --git a/executors/ethereum/bridgeV2Wrappers/ERC20Safe.abi.json b/executors/ethereum/bridgeV2Wrappers/ERC20Safe.abi.json new file mode 100644 index 00000000..81126a5e --- /dev/null +++ b/executors/ethereum/bridgeV2Wrappers/ERC20Safe.abi.json @@ -0,0 +1,763 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminRoleTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousBridge", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newBridge", + "type": "address" + } + ], + "name": "BridgeTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint112", + "name": "depositNonce", + "type": "uint112" + }, + { + "indexed": false, + "internalType": "uint112", + "name": "batchId", + "type": "uint112" + } + ], + "name": "ERC20Deposit", + "type": "event" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchBlockLimit", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "batchDeposits", + "outputs": [ + { + "internalType": "uint112", + "name": "nonce", + "type": "uint112" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "enum DepositStatus", + "name": "status", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchSettleLimit", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchSize", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "batches", + "outputs": [ + { + "internalType": "uint112", + "name": "nonce", + "type": "uint112" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastUpdatedBlockNumber", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "depositsCount", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchesCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "recipientAddress", + "type": "bytes32" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "depositsCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "batchNonce", + "type": "uint256" + } + ], + "name": "getBatch", + "outputs": [ + { + "components": [ + { + "internalType": "uint112", + "name": "nonce", + "type": "uint112" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastUpdatedBlockNumber", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "depositsCount", + "type": "uint16" + } + ], + "internalType": "struct Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "batchNonce", + "type": "uint256" + } + ], + "name": "getDeposits", + "outputs": [ + { + "components": [ + { + "internalType": "uint112", + "name": "nonce", + "type": "uint112" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "enum DepositStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct Deposit[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenMaxLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenMinLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "initSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAnyBatchInProgress", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenWhitelisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "recoverLostFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "removeTokenFromWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "newBatchBlockLimit", + "type": "uint8" + } + ], + "name": "setBatchBlockLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "newBatchSettleLimit", + "type": "uint8" + } + ], + "name": "setBatchSettleLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "newBatchSize", + "type": "uint16" + } + ], + "name": "setBatchSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newBridge", + "type": "address" + } + ], + "name": "setBridge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setTokenMaxLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setTokenMinLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenBalances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenMaxLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenMinLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipientAddress", + "type": "address" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "transferAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minimumAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumAmount", + "type": "uint256" + } + ], + "name": "whitelistToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "whitelistedTokens", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/executors/ethereum/bridgeV2Wrappers/ERC20Safe.go b/executors/ethereum/bridgeV2Wrappers/ERC20Safe.go new file mode 100644 index 00000000..548d35f1 --- /dev/null +++ b/executors/ethereum/bridgeV2Wrappers/ERC20Safe.go @@ -0,0 +1,1654 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contract + +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 +) + +// Batch is an auto generated low-level Go binding around an user-defined struct. +type Batch struct { + Nonce *big.Int + BlockNumber uint64 + LastUpdatedBlockNumber uint64 + DepositsCount uint16 +} + +// Deposit is an auto generated low-level Go binding around an user-defined struct. +type Deposit struct { + Nonce *big.Int + TokenAddress common.Address + Amount *big.Int + Depositor common.Address + Recipient [32]byte + Status uint8 +} + +// ERC20SafeMetaData contains all meta data concerning the ERC20Safe contract. +var ERC20SafeMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminRoleTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousBridge\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newBridge\",\"type\":\"address\"}],\"name\":\"BridgeTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint112\",\"name\":\"depositNonce\",\"type\":\"uint112\"},{\"indexed\":false,\"internalType\":\"uint112\",\"name\":\"batchId\",\"type\":\"uint112\"}],\"name\":\"ERC20Deposit\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchBlockLimit\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"batchDeposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"nonce\",\"type\":\"uint112\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"enumDepositStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchSettleLimit\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchSize\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"batches\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"nonce\",\"type\":\"uint112\"},{\"internalType\":\"uint64\",\"name\":\"blockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"lastUpdatedBlockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"depositsCount\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchesCount\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientAddress\",\"type\":\"bytes32\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositsCount\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchNonce\",\"type\":\"uint256\"}],\"name\":\"getBatch\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"nonce\",\"type\":\"uint112\"},{\"internalType\":\"uint64\",\"name\":\"blockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"lastUpdatedBlockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"depositsCount\",\"type\":\"uint16\"}],\"internalType\":\"structBatch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchNonce\",\"type\":\"uint256\"}],\"name\":\"getDeposits\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"nonce\",\"type\":\"uint112\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"enumDepositStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"internalType\":\"structDeposit[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenMaxLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenMinLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"initSupply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAnyBatchInProgress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenWhitelisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"recoverLostFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"removeTokenFromWhitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"newBatchBlockLimit\",\"type\":\"uint8\"}],\"name\":\"setBatchBlockLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"newBatchSettleLimit\",\"type\":\"uint8\"}],\"name\":\"setBatchSettleLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"newBatchSize\",\"type\":\"uint16\"}],\"name\":\"setBatchSize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newBridge\",\"type\":\"address\"}],\"name\":\"setBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setTokenMaxLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setTokenMinLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"tokenBalances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"tokenMaxLimits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"tokenMinLimits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipientAddress\",\"type\":\"address\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"transferAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minimumAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumAmount\",\"type\":\"uint256\"}],\"name\":\"whitelistToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"whitelistedTokens\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// ERC20SafeABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC20SafeMetaData.ABI instead. +var ERC20SafeABI = ERC20SafeMetaData.ABI + +// ERC20Safe is an auto generated Go binding around an Ethereum contract. +type ERC20Safe struct { + ERC20SafeCaller // Read-only binding to the contract + ERC20SafeTransactor // Write-only binding to the contract + ERC20SafeFilterer // Log filterer for contract events +} + +// ERC20SafeCaller is an auto generated read-only Go binding around an Ethereum contract. +type ERC20SafeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20SafeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC20SafeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20SafeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC20SafeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20SafeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC20SafeSession struct { + Contract *ERC20Safe // 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 +} + +// ERC20SafeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC20SafeCallerSession struct { + Contract *ERC20SafeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ERC20SafeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC20SafeTransactorSession struct { + Contract *ERC20SafeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20SafeRaw is an auto generated low-level Go binding around an Ethereum contract. +type ERC20SafeRaw struct { + Contract *ERC20Safe // Generic contract binding to access the raw methods on +} + +// ERC20SafeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC20SafeCallerRaw struct { + Contract *ERC20SafeCaller // Generic read-only contract binding to access the raw methods on +} + +// ERC20SafeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC20SafeTransactorRaw struct { + Contract *ERC20SafeTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewERC20Safe creates a new instance of ERC20Safe, bound to a specific deployed contract. +func NewERC20Safe(address common.Address, backend bind.ContractBackend) (*ERC20Safe, error) { + contract, err := bindERC20Safe(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ERC20Safe{ERC20SafeCaller: ERC20SafeCaller{contract: contract}, ERC20SafeTransactor: ERC20SafeTransactor{contract: contract}, ERC20SafeFilterer: ERC20SafeFilterer{contract: contract}}, nil +} + +// NewERC20SafeCaller creates a new read-only instance of ERC20Safe, bound to a specific deployed contract. +func NewERC20SafeCaller(address common.Address, caller bind.ContractCaller) (*ERC20SafeCaller, error) { + contract, err := bindERC20Safe(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC20SafeCaller{contract: contract}, nil +} + +// NewERC20SafeTransactor creates a new write-only instance of ERC20Safe, bound to a specific deployed contract. +func NewERC20SafeTransactor(address common.Address, transactor bind.ContractTransactor) (*ERC20SafeTransactor, error) { + contract, err := bindERC20Safe(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC20SafeTransactor{contract: contract}, nil +} + +// NewERC20SafeFilterer creates a new log filterer instance of ERC20Safe, bound to a specific deployed contract. +func NewERC20SafeFilterer(address common.Address, filterer bind.ContractFilterer) (*ERC20SafeFilterer, error) { + contract, err := bindERC20Safe(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC20SafeFilterer{contract: contract}, nil +} + +// bindERC20Safe binds a generic wrapper to an already deployed contract. +func bindERC20Safe(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC20SafeMetaData.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 (_ERC20Safe *ERC20SafeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20Safe.Contract.ERC20SafeCaller.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 (_ERC20Safe *ERC20SafeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Safe.Contract.ERC20SafeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20Safe *ERC20SafeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20Safe.Contract.ERC20SafeTransactor.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 (_ERC20Safe *ERC20SafeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20Safe.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 (_ERC20Safe *ERC20SafeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Safe.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20Safe *ERC20SafeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20Safe.Contract.contract.Transact(opts, method, params...) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_ERC20Safe *ERC20SafeCaller) Admin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "admin") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_ERC20Safe *ERC20SafeSession) Admin() (common.Address, error) { + return _ERC20Safe.Contract.Admin(&_ERC20Safe.CallOpts) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_ERC20Safe *ERC20SafeCallerSession) Admin() (common.Address, error) { + return _ERC20Safe.Contract.Admin(&_ERC20Safe.CallOpts) +} + +// BatchBlockLimit is a free data retrieval call binding the contract method 0x9ab7cfaa. +// +// Solidity: function batchBlockLimit() view returns(uint8) +func (_ERC20Safe *ERC20SafeCaller) BatchBlockLimit(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "batchBlockLimit") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// BatchBlockLimit is a free data retrieval call binding the contract method 0x9ab7cfaa. +// +// Solidity: function batchBlockLimit() view returns(uint8) +func (_ERC20Safe *ERC20SafeSession) BatchBlockLimit() (uint8, error) { + return _ERC20Safe.Contract.BatchBlockLimit(&_ERC20Safe.CallOpts) +} + +// BatchBlockLimit is a free data retrieval call binding the contract method 0x9ab7cfaa. +// +// Solidity: function batchBlockLimit() view returns(uint8) +func (_ERC20Safe *ERC20SafeCallerSession) BatchBlockLimit() (uint8, error) { + return _ERC20Safe.Contract.BatchBlockLimit(&_ERC20Safe.CallOpts) +} + +// BatchDeposits is a free data retrieval call binding the contract method 0x284c0c44. +// +// Solidity: function batchDeposits(uint256 , uint256 ) view returns(uint112 nonce, address tokenAddress, uint256 amount, address depositor, bytes32 recipient, uint8 status) +func (_ERC20Safe *ERC20SafeCaller) BatchDeposits(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (struct { + Nonce *big.Int + TokenAddress common.Address + Amount *big.Int + Depositor common.Address + Recipient [32]byte + Status uint8 +}, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "batchDeposits", arg0, arg1) + + outstruct := new(struct { + Nonce *big.Int + TokenAddress common.Address + Amount *big.Int + Depositor common.Address + Recipient [32]byte + Status uint8 + }) + if err != nil { + return *outstruct, err + } + + outstruct.Nonce = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.TokenAddress = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + outstruct.Amount = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.Depositor = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + outstruct.Recipient = *abi.ConvertType(out[4], new([32]byte)).(*[32]byte) + outstruct.Status = *abi.ConvertType(out[5], new(uint8)).(*uint8) + + return *outstruct, err + +} + +// BatchDeposits is a free data retrieval call binding the contract method 0x284c0c44. +// +// Solidity: function batchDeposits(uint256 , uint256 ) view returns(uint112 nonce, address tokenAddress, uint256 amount, address depositor, bytes32 recipient, uint8 status) +func (_ERC20Safe *ERC20SafeSession) BatchDeposits(arg0 *big.Int, arg1 *big.Int) (struct { + Nonce *big.Int + TokenAddress common.Address + Amount *big.Int + Depositor common.Address + Recipient [32]byte + Status uint8 +}, error) { + return _ERC20Safe.Contract.BatchDeposits(&_ERC20Safe.CallOpts, arg0, arg1) +} + +// BatchDeposits is a free data retrieval call binding the contract method 0x284c0c44. +// +// Solidity: function batchDeposits(uint256 , uint256 ) view returns(uint112 nonce, address tokenAddress, uint256 amount, address depositor, bytes32 recipient, uint8 status) +func (_ERC20Safe *ERC20SafeCallerSession) BatchDeposits(arg0 *big.Int, arg1 *big.Int) (struct { + Nonce *big.Int + TokenAddress common.Address + Amount *big.Int + Depositor common.Address + Recipient [32]byte + Status uint8 +}, error) { + return _ERC20Safe.Contract.BatchDeposits(&_ERC20Safe.CallOpts, arg0, arg1) +} + +// BatchSettleLimit is a free data retrieval call binding the contract method 0x2325b5f7. +// +// Solidity: function batchSettleLimit() view returns(uint8) +func (_ERC20Safe *ERC20SafeCaller) BatchSettleLimit(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "batchSettleLimit") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// BatchSettleLimit is a free data retrieval call binding the contract method 0x2325b5f7. +// +// Solidity: function batchSettleLimit() view returns(uint8) +func (_ERC20Safe *ERC20SafeSession) BatchSettleLimit() (uint8, error) { + return _ERC20Safe.Contract.BatchSettleLimit(&_ERC20Safe.CallOpts) +} + +// BatchSettleLimit is a free data retrieval call binding the contract method 0x2325b5f7. +// +// Solidity: function batchSettleLimit() view returns(uint8) +func (_ERC20Safe *ERC20SafeCallerSession) BatchSettleLimit() (uint8, error) { + return _ERC20Safe.Contract.BatchSettleLimit(&_ERC20Safe.CallOpts) +} + +// BatchSize is a free data retrieval call binding the contract method 0xf4daaba1. +// +// Solidity: function batchSize() view returns(uint16) +func (_ERC20Safe *ERC20SafeCaller) BatchSize(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "batchSize") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// BatchSize is a free data retrieval call binding the contract method 0xf4daaba1. +// +// Solidity: function batchSize() view returns(uint16) +func (_ERC20Safe *ERC20SafeSession) BatchSize() (uint16, error) { + return _ERC20Safe.Contract.BatchSize(&_ERC20Safe.CallOpts) +} + +// BatchSize is a free data retrieval call binding the contract method 0xf4daaba1. +// +// Solidity: function batchSize() view returns(uint16) +func (_ERC20Safe *ERC20SafeCallerSession) BatchSize() (uint16, error) { + return _ERC20Safe.Contract.BatchSize(&_ERC20Safe.CallOpts) +} + +// Batches is a free data retrieval call binding the contract method 0xb32c4d8d. +// +// Solidity: function batches(uint256 ) view returns(uint112 nonce, uint64 blockNumber, uint64 lastUpdatedBlockNumber, uint16 depositsCount) +func (_ERC20Safe *ERC20SafeCaller) Batches(opts *bind.CallOpts, arg0 *big.Int) (struct { + Nonce *big.Int + BlockNumber uint64 + LastUpdatedBlockNumber uint64 + DepositsCount uint16 +}, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "batches", arg0) + + outstruct := new(struct { + Nonce *big.Int + BlockNumber uint64 + LastUpdatedBlockNumber uint64 + DepositsCount uint16 + }) + if err != nil { + return *outstruct, err + } + + outstruct.Nonce = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.LastUpdatedBlockNumber = *abi.ConvertType(out[2], new(uint64)).(*uint64) + outstruct.DepositsCount = *abi.ConvertType(out[3], new(uint16)).(*uint16) + + return *outstruct, err + +} + +// Batches is a free data retrieval call binding the contract method 0xb32c4d8d. +// +// Solidity: function batches(uint256 ) view returns(uint112 nonce, uint64 blockNumber, uint64 lastUpdatedBlockNumber, uint16 depositsCount) +func (_ERC20Safe *ERC20SafeSession) Batches(arg0 *big.Int) (struct { + Nonce *big.Int + BlockNumber uint64 + LastUpdatedBlockNumber uint64 + DepositsCount uint16 +}, error) { + return _ERC20Safe.Contract.Batches(&_ERC20Safe.CallOpts, arg0) +} + +// Batches is a free data retrieval call binding the contract method 0xb32c4d8d. +// +// Solidity: function batches(uint256 ) view returns(uint112 nonce, uint64 blockNumber, uint64 lastUpdatedBlockNumber, uint16 depositsCount) +func (_ERC20Safe *ERC20SafeCallerSession) Batches(arg0 *big.Int) (struct { + Nonce *big.Int + BlockNumber uint64 + LastUpdatedBlockNumber uint64 + DepositsCount uint16 +}, error) { + return _ERC20Safe.Contract.Batches(&_ERC20Safe.CallOpts, arg0) +} + +// BatchesCount is a free data retrieval call binding the contract method 0x87ea0961. +// +// Solidity: function batchesCount() view returns(uint64) +func (_ERC20Safe *ERC20SafeCaller) BatchesCount(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "batchesCount") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// BatchesCount is a free data retrieval call binding the contract method 0x87ea0961. +// +// Solidity: function batchesCount() view returns(uint64) +func (_ERC20Safe *ERC20SafeSession) BatchesCount() (uint64, error) { + return _ERC20Safe.Contract.BatchesCount(&_ERC20Safe.CallOpts) +} + +// BatchesCount is a free data retrieval call binding the contract method 0x87ea0961. +// +// Solidity: function batchesCount() view returns(uint64) +func (_ERC20Safe *ERC20SafeCallerSession) BatchesCount() (uint64, error) { + return _ERC20Safe.Contract.BatchesCount(&_ERC20Safe.CallOpts) +} + +// Bridge is a free data retrieval call binding the contract method 0xe78cea92. +// +// Solidity: function bridge() view returns(address) +func (_ERC20Safe *ERC20SafeCaller) Bridge(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "bridge") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Bridge is a free data retrieval call binding the contract method 0xe78cea92. +// +// Solidity: function bridge() view returns(address) +func (_ERC20Safe *ERC20SafeSession) Bridge() (common.Address, error) { + return _ERC20Safe.Contract.Bridge(&_ERC20Safe.CallOpts) +} + +// Bridge is a free data retrieval call binding the contract method 0xe78cea92. +// +// Solidity: function bridge() view returns(address) +func (_ERC20Safe *ERC20SafeCallerSession) Bridge() (common.Address, error) { + return _ERC20Safe.Contract.Bridge(&_ERC20Safe.CallOpts) +} + +// DepositsCount is a free data retrieval call binding the contract method 0x4506e935. +// +// Solidity: function depositsCount() view returns(uint64) +func (_ERC20Safe *ERC20SafeCaller) DepositsCount(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "depositsCount") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// DepositsCount is a free data retrieval call binding the contract method 0x4506e935. +// +// Solidity: function depositsCount() view returns(uint64) +func (_ERC20Safe *ERC20SafeSession) DepositsCount() (uint64, error) { + return _ERC20Safe.Contract.DepositsCount(&_ERC20Safe.CallOpts) +} + +// DepositsCount is a free data retrieval call binding the contract method 0x4506e935. +// +// Solidity: function depositsCount() view returns(uint64) +func (_ERC20Safe *ERC20SafeCallerSession) DepositsCount() (uint64, error) { + return _ERC20Safe.Contract.DepositsCount(&_ERC20Safe.CallOpts) +} + +// GetBatch is a free data retrieval call binding the contract method 0x5ac44282. +// +// Solidity: function getBatch(uint256 batchNonce) view returns((uint112,uint64,uint64,uint16)) +func (_ERC20Safe *ERC20SafeCaller) GetBatch(opts *bind.CallOpts, batchNonce *big.Int) (Batch, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "getBatch", batchNonce) + + if err != nil { + return *new(Batch), err + } + + out0 := *abi.ConvertType(out[0], new(Batch)).(*Batch) + + return out0, err + +} + +// GetBatch is a free data retrieval call binding the contract method 0x5ac44282. +// +// Solidity: function getBatch(uint256 batchNonce) view returns((uint112,uint64,uint64,uint16)) +func (_ERC20Safe *ERC20SafeSession) GetBatch(batchNonce *big.Int) (Batch, error) { + return _ERC20Safe.Contract.GetBatch(&_ERC20Safe.CallOpts, batchNonce) +} + +// GetBatch is a free data retrieval call binding the contract method 0x5ac44282. +// +// Solidity: function getBatch(uint256 batchNonce) view returns((uint112,uint64,uint64,uint16)) +func (_ERC20Safe *ERC20SafeCallerSession) GetBatch(batchNonce *big.Int) (Batch, error) { + return _ERC20Safe.Contract.GetBatch(&_ERC20Safe.CallOpts, batchNonce) +} + +// GetDeposits is a free data retrieval call binding the contract method 0x085c967f. +// +// Solidity: function getDeposits(uint256 batchNonce) view returns((uint112,address,uint256,address,bytes32,uint8)[]) +func (_ERC20Safe *ERC20SafeCaller) GetDeposits(opts *bind.CallOpts, batchNonce *big.Int) ([]Deposit, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "getDeposits", batchNonce) + + if err != nil { + return *new([]Deposit), err + } + + out0 := *abi.ConvertType(out[0], new([]Deposit)).(*[]Deposit) + + return out0, err + +} + +// GetDeposits is a free data retrieval call binding the contract method 0x085c967f. +// +// Solidity: function getDeposits(uint256 batchNonce) view returns((uint112,address,uint256,address,bytes32,uint8)[]) +func (_ERC20Safe *ERC20SafeSession) GetDeposits(batchNonce *big.Int) ([]Deposit, error) { + return _ERC20Safe.Contract.GetDeposits(&_ERC20Safe.CallOpts, batchNonce) +} + +// GetDeposits is a free data retrieval call binding the contract method 0x085c967f. +// +// Solidity: function getDeposits(uint256 batchNonce) view returns((uint112,address,uint256,address,bytes32,uint8)[]) +func (_ERC20Safe *ERC20SafeCallerSession) GetDeposits(batchNonce *big.Int) ([]Deposit, error) { + return _ERC20Safe.Contract.GetDeposits(&_ERC20Safe.CallOpts, batchNonce) +} + +// GetTokenMaxLimit is a free data retrieval call binding the contract method 0xc652a0b5. +// +// Solidity: function getTokenMaxLimit(address token) view returns(uint256) +func (_ERC20Safe *ERC20SafeCaller) GetTokenMaxLimit(opts *bind.CallOpts, token common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "getTokenMaxLimit", token) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetTokenMaxLimit is a free data retrieval call binding the contract method 0xc652a0b5. +// +// Solidity: function getTokenMaxLimit(address token) view returns(uint256) +func (_ERC20Safe *ERC20SafeSession) GetTokenMaxLimit(token common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.GetTokenMaxLimit(&_ERC20Safe.CallOpts, token) +} + +// GetTokenMaxLimit is a free data retrieval call binding the contract method 0xc652a0b5. +// +// Solidity: function getTokenMaxLimit(address token) view returns(uint256) +func (_ERC20Safe *ERC20SafeCallerSession) GetTokenMaxLimit(token common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.GetTokenMaxLimit(&_ERC20Safe.CallOpts, token) +} + +// GetTokenMinLimit is a free data retrieval call binding the contract method 0x9f0ebb93. +// +// Solidity: function getTokenMinLimit(address token) view returns(uint256) +func (_ERC20Safe *ERC20SafeCaller) GetTokenMinLimit(opts *bind.CallOpts, token common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "getTokenMinLimit", token) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetTokenMinLimit is a free data retrieval call binding the contract method 0x9f0ebb93. +// +// Solidity: function getTokenMinLimit(address token) view returns(uint256) +func (_ERC20Safe *ERC20SafeSession) GetTokenMinLimit(token common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.GetTokenMinLimit(&_ERC20Safe.CallOpts, token) +} + +// GetTokenMinLimit is a free data retrieval call binding the contract method 0x9f0ebb93. +// +// Solidity: function getTokenMinLimit(address token) view returns(uint256) +func (_ERC20Safe *ERC20SafeCallerSession) GetTokenMinLimit(token common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.GetTokenMinLimit(&_ERC20Safe.CallOpts, token) +} + +// IsAnyBatchInProgress is a free data retrieval call binding the contract method 0x82146138. +// +// Solidity: function isAnyBatchInProgress() view returns(bool) +func (_ERC20Safe *ERC20SafeCaller) IsAnyBatchInProgress(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "isAnyBatchInProgress") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsAnyBatchInProgress is a free data retrieval call binding the contract method 0x82146138. +// +// Solidity: function isAnyBatchInProgress() view returns(bool) +func (_ERC20Safe *ERC20SafeSession) IsAnyBatchInProgress() (bool, error) { + return _ERC20Safe.Contract.IsAnyBatchInProgress(&_ERC20Safe.CallOpts) +} + +// IsAnyBatchInProgress is a free data retrieval call binding the contract method 0x82146138. +// +// Solidity: function isAnyBatchInProgress() view returns(bool) +func (_ERC20Safe *ERC20SafeCallerSession) IsAnyBatchInProgress() (bool, error) { + return _ERC20Safe.Contract.IsAnyBatchInProgress(&_ERC20Safe.CallOpts) +} + +// IsTokenWhitelisted is a free data retrieval call binding the contract method 0xb5af090f. +// +// Solidity: function isTokenWhitelisted(address token) view returns(bool) +func (_ERC20Safe *ERC20SafeCaller) IsTokenWhitelisted(opts *bind.CallOpts, token common.Address) (bool, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "isTokenWhitelisted", token) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsTokenWhitelisted is a free data retrieval call binding the contract method 0xb5af090f. +// +// Solidity: function isTokenWhitelisted(address token) view returns(bool) +func (_ERC20Safe *ERC20SafeSession) IsTokenWhitelisted(token common.Address) (bool, error) { + return _ERC20Safe.Contract.IsTokenWhitelisted(&_ERC20Safe.CallOpts, token) +} + +// IsTokenWhitelisted is a free data retrieval call binding the contract method 0xb5af090f. +// +// Solidity: function isTokenWhitelisted(address token) view returns(bool) +func (_ERC20Safe *ERC20SafeCallerSession) IsTokenWhitelisted(token common.Address) (bool, error) { + return _ERC20Safe.Contract.IsTokenWhitelisted(&_ERC20Safe.CallOpts, token) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_ERC20Safe *ERC20SafeCaller) Paused(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "paused") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_ERC20Safe *ERC20SafeSession) Paused() (bool, error) { + return _ERC20Safe.Contract.Paused(&_ERC20Safe.CallOpts) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_ERC20Safe *ERC20SafeCallerSession) Paused() (bool, error) { + return _ERC20Safe.Contract.Paused(&_ERC20Safe.CallOpts) +} + +// TokenBalances is a free data retrieval call binding the contract method 0x523fba7f. +// +// Solidity: function tokenBalances(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeCaller) TokenBalances(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "tokenBalances", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TokenBalances is a free data retrieval call binding the contract method 0x523fba7f. +// +// Solidity: function tokenBalances(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeSession) TokenBalances(arg0 common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.TokenBalances(&_ERC20Safe.CallOpts, arg0) +} + +// TokenBalances is a free data retrieval call binding the contract method 0x523fba7f. +// +// Solidity: function tokenBalances(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeCallerSession) TokenBalances(arg0 common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.TokenBalances(&_ERC20Safe.CallOpts, arg0) +} + +// TokenMaxLimits is a free data retrieval call binding the contract method 0xc639651d. +// +// Solidity: function tokenMaxLimits(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeCaller) TokenMaxLimits(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "tokenMaxLimits", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TokenMaxLimits is a free data retrieval call binding the contract method 0xc639651d. +// +// Solidity: function tokenMaxLimits(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeSession) TokenMaxLimits(arg0 common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.TokenMaxLimits(&_ERC20Safe.CallOpts, arg0) +} + +// TokenMaxLimits is a free data retrieval call binding the contract method 0xc639651d. +// +// Solidity: function tokenMaxLimits(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeCallerSession) TokenMaxLimits(arg0 common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.TokenMaxLimits(&_ERC20Safe.CallOpts, arg0) +} + +// TokenMinLimits is a free data retrieval call binding the contract method 0xf6246ea1. +// +// Solidity: function tokenMinLimits(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeCaller) TokenMinLimits(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "tokenMinLimits", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TokenMinLimits is a free data retrieval call binding the contract method 0xf6246ea1. +// +// Solidity: function tokenMinLimits(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeSession) TokenMinLimits(arg0 common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.TokenMinLimits(&_ERC20Safe.CallOpts, arg0) +} + +// TokenMinLimits is a free data retrieval call binding the contract method 0xf6246ea1. +// +// Solidity: function tokenMinLimits(address ) view returns(uint256) +func (_ERC20Safe *ERC20SafeCallerSession) TokenMinLimits(arg0 common.Address) (*big.Int, error) { + return _ERC20Safe.Contract.TokenMinLimits(&_ERC20Safe.CallOpts, arg0) +} + +// WhitelistedTokens is a free data retrieval call binding the contract method 0xdaf9c210. +// +// Solidity: function whitelistedTokens(address ) view returns(bool) +func (_ERC20Safe *ERC20SafeCaller) WhitelistedTokens(opts *bind.CallOpts, arg0 common.Address) (bool, error) { + var out []interface{} + err := _ERC20Safe.contract.Call(opts, &out, "whitelistedTokens", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// WhitelistedTokens is a free data retrieval call binding the contract method 0xdaf9c210. +// +// Solidity: function whitelistedTokens(address ) view returns(bool) +func (_ERC20Safe *ERC20SafeSession) WhitelistedTokens(arg0 common.Address) (bool, error) { + return _ERC20Safe.Contract.WhitelistedTokens(&_ERC20Safe.CallOpts, arg0) +} + +// WhitelistedTokens is a free data retrieval call binding the contract method 0xdaf9c210. +// +// Solidity: function whitelistedTokens(address ) view returns(bool) +func (_ERC20Safe *ERC20SafeCallerSession) WhitelistedTokens(arg0 common.Address) (bool, error) { + return _ERC20Safe.Contract.WhitelistedTokens(&_ERC20Safe.CallOpts, arg0) +} + +// Deposit is a paid mutator transaction binding the contract method 0x26b3293f. +// +// Solidity: function deposit(address tokenAddress, uint256 amount, bytes32 recipientAddress) returns() +func (_ERC20Safe *ERC20SafeTransactor) Deposit(opts *bind.TransactOpts, tokenAddress common.Address, amount *big.Int, recipientAddress [32]byte) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "deposit", tokenAddress, amount, recipientAddress) +} + +// Deposit is a paid mutator transaction binding the contract method 0x26b3293f. +// +// Solidity: function deposit(address tokenAddress, uint256 amount, bytes32 recipientAddress) returns() +func (_ERC20Safe *ERC20SafeSession) Deposit(tokenAddress common.Address, amount *big.Int, recipientAddress [32]byte) (*types.Transaction, error) { + return _ERC20Safe.Contract.Deposit(&_ERC20Safe.TransactOpts, tokenAddress, amount, recipientAddress) +} + +// Deposit is a paid mutator transaction binding the contract method 0x26b3293f. +// +// Solidity: function deposit(address tokenAddress, uint256 amount, bytes32 recipientAddress) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) Deposit(tokenAddress common.Address, amount *big.Int, recipientAddress [32]byte) (*types.Transaction, error) { + return _ERC20Safe.Contract.Deposit(&_ERC20Safe.TransactOpts, tokenAddress, amount, recipientAddress) +} + +// InitSupply is a paid mutator transaction binding the contract method 0x4013c89c. +// +// Solidity: function initSupply(address tokenAddress, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeTransactor) InitSupply(opts *bind.TransactOpts, tokenAddress common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "initSupply", tokenAddress, amount) +} + +// InitSupply is a paid mutator transaction binding the contract method 0x4013c89c. +// +// Solidity: function initSupply(address tokenAddress, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeSession) InitSupply(tokenAddress common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.InitSupply(&_ERC20Safe.TransactOpts, tokenAddress, amount) +} + +// InitSupply is a paid mutator transaction binding the contract method 0x4013c89c. +// +// Solidity: function initSupply(address tokenAddress, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) InitSupply(tokenAddress common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.InitSupply(&_ERC20Safe.TransactOpts, tokenAddress, amount) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_ERC20Safe *ERC20SafeTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "pause") +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_ERC20Safe *ERC20SafeSession) Pause() (*types.Transaction, error) { + return _ERC20Safe.Contract.Pause(&_ERC20Safe.TransactOpts) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_ERC20Safe *ERC20SafeTransactorSession) Pause() (*types.Transaction, error) { + return _ERC20Safe.Contract.Pause(&_ERC20Safe.TransactOpts) +} + +// RecoverLostFunds is a paid mutator transaction binding the contract method 0x770be784. +// +// Solidity: function recoverLostFunds(address tokenAddress) returns() +func (_ERC20Safe *ERC20SafeTransactor) RecoverLostFunds(opts *bind.TransactOpts, tokenAddress common.Address) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "recoverLostFunds", tokenAddress) +} + +// RecoverLostFunds is a paid mutator transaction binding the contract method 0x770be784. +// +// Solidity: function recoverLostFunds(address tokenAddress) returns() +func (_ERC20Safe *ERC20SafeSession) RecoverLostFunds(tokenAddress common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.RecoverLostFunds(&_ERC20Safe.TransactOpts, tokenAddress) +} + +// RecoverLostFunds is a paid mutator transaction binding the contract method 0x770be784. +// +// Solidity: function recoverLostFunds(address tokenAddress) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) RecoverLostFunds(tokenAddress common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.RecoverLostFunds(&_ERC20Safe.TransactOpts, tokenAddress) +} + +// RemoveTokenFromWhitelist is a paid mutator transaction binding the contract method 0x306275be. +// +// Solidity: function removeTokenFromWhitelist(address token) returns() +func (_ERC20Safe *ERC20SafeTransactor) RemoveTokenFromWhitelist(opts *bind.TransactOpts, token common.Address) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "removeTokenFromWhitelist", token) +} + +// RemoveTokenFromWhitelist is a paid mutator transaction binding the contract method 0x306275be. +// +// Solidity: function removeTokenFromWhitelist(address token) returns() +func (_ERC20Safe *ERC20SafeSession) RemoveTokenFromWhitelist(token common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.RemoveTokenFromWhitelist(&_ERC20Safe.TransactOpts, token) +} + +// RemoveTokenFromWhitelist is a paid mutator transaction binding the contract method 0x306275be. +// +// Solidity: function removeTokenFromWhitelist(address token) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) RemoveTokenFromWhitelist(token common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.RemoveTokenFromWhitelist(&_ERC20Safe.TransactOpts, token) +} + +// RenounceAdmin is a paid mutator transaction binding the contract method 0x8bad0c0a. +// +// Solidity: function renounceAdmin() returns() +func (_ERC20Safe *ERC20SafeTransactor) RenounceAdmin(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "renounceAdmin") +} + +// RenounceAdmin is a paid mutator transaction binding the contract method 0x8bad0c0a. +// +// Solidity: function renounceAdmin() returns() +func (_ERC20Safe *ERC20SafeSession) RenounceAdmin() (*types.Transaction, error) { + return _ERC20Safe.Contract.RenounceAdmin(&_ERC20Safe.TransactOpts) +} + +// RenounceAdmin is a paid mutator transaction binding the contract method 0x8bad0c0a. +// +// Solidity: function renounceAdmin() returns() +func (_ERC20Safe *ERC20SafeTransactorSession) RenounceAdmin() (*types.Transaction, error) { + return _ERC20Safe.Contract.RenounceAdmin(&_ERC20Safe.TransactOpts) +} + +// SetBatchBlockLimit is a paid mutator transaction binding the contract method 0xe8a70ee2. +// +// Solidity: function setBatchBlockLimit(uint8 newBatchBlockLimit) returns() +func (_ERC20Safe *ERC20SafeTransactor) SetBatchBlockLimit(opts *bind.TransactOpts, newBatchBlockLimit uint8) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "setBatchBlockLimit", newBatchBlockLimit) +} + +// SetBatchBlockLimit is a paid mutator transaction binding the contract method 0xe8a70ee2. +// +// Solidity: function setBatchBlockLimit(uint8 newBatchBlockLimit) returns() +func (_ERC20Safe *ERC20SafeSession) SetBatchBlockLimit(newBatchBlockLimit uint8) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBatchBlockLimit(&_ERC20Safe.TransactOpts, newBatchBlockLimit) +} + +// SetBatchBlockLimit is a paid mutator transaction binding the contract method 0xe8a70ee2. +// +// Solidity: function setBatchBlockLimit(uint8 newBatchBlockLimit) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) SetBatchBlockLimit(newBatchBlockLimit uint8) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBatchBlockLimit(&_ERC20Safe.TransactOpts, newBatchBlockLimit) +} + +// SetBatchSettleLimit is a paid mutator transaction binding the contract method 0xf2e0ec48. +// +// Solidity: function setBatchSettleLimit(uint8 newBatchSettleLimit) returns() +func (_ERC20Safe *ERC20SafeTransactor) SetBatchSettleLimit(opts *bind.TransactOpts, newBatchSettleLimit uint8) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "setBatchSettleLimit", newBatchSettleLimit) +} + +// SetBatchSettleLimit is a paid mutator transaction binding the contract method 0xf2e0ec48. +// +// Solidity: function setBatchSettleLimit(uint8 newBatchSettleLimit) returns() +func (_ERC20Safe *ERC20SafeSession) SetBatchSettleLimit(newBatchSettleLimit uint8) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBatchSettleLimit(&_ERC20Safe.TransactOpts, newBatchSettleLimit) +} + +// SetBatchSettleLimit is a paid mutator transaction binding the contract method 0xf2e0ec48. +// +// Solidity: function setBatchSettleLimit(uint8 newBatchSettleLimit) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) SetBatchSettleLimit(newBatchSettleLimit uint8) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBatchSettleLimit(&_ERC20Safe.TransactOpts, newBatchSettleLimit) +} + +// SetBatchSize is a paid mutator transaction binding the contract method 0xd4673de9. +// +// Solidity: function setBatchSize(uint16 newBatchSize) returns() +func (_ERC20Safe *ERC20SafeTransactor) SetBatchSize(opts *bind.TransactOpts, newBatchSize uint16) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "setBatchSize", newBatchSize) +} + +// SetBatchSize is a paid mutator transaction binding the contract method 0xd4673de9. +// +// Solidity: function setBatchSize(uint16 newBatchSize) returns() +func (_ERC20Safe *ERC20SafeSession) SetBatchSize(newBatchSize uint16) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBatchSize(&_ERC20Safe.TransactOpts, newBatchSize) +} + +// SetBatchSize is a paid mutator transaction binding the contract method 0xd4673de9. +// +// Solidity: function setBatchSize(uint16 newBatchSize) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) SetBatchSize(newBatchSize uint16) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBatchSize(&_ERC20Safe.TransactOpts, newBatchSize) +} + +// SetBridge is a paid mutator transaction binding the contract method 0x8dd14802. +// +// Solidity: function setBridge(address newBridge) returns() +func (_ERC20Safe *ERC20SafeTransactor) SetBridge(opts *bind.TransactOpts, newBridge common.Address) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "setBridge", newBridge) +} + +// SetBridge is a paid mutator transaction binding the contract method 0x8dd14802. +// +// Solidity: function setBridge(address newBridge) returns() +func (_ERC20Safe *ERC20SafeSession) SetBridge(newBridge common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBridge(&_ERC20Safe.TransactOpts, newBridge) +} + +// SetBridge is a paid mutator transaction binding the contract method 0x8dd14802. +// +// Solidity: function setBridge(address newBridge) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) SetBridge(newBridge common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetBridge(&_ERC20Safe.TransactOpts, newBridge) +} + +// SetTokenMaxLimit is a paid mutator transaction binding the contract method 0x7d7763ce. +// +// Solidity: function setTokenMaxLimit(address token, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeTransactor) SetTokenMaxLimit(opts *bind.TransactOpts, token common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "setTokenMaxLimit", token, amount) +} + +// SetTokenMaxLimit is a paid mutator transaction binding the contract method 0x7d7763ce. +// +// Solidity: function setTokenMaxLimit(address token, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeSession) SetTokenMaxLimit(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetTokenMaxLimit(&_ERC20Safe.TransactOpts, token, amount) +} + +// SetTokenMaxLimit is a paid mutator transaction binding the contract method 0x7d7763ce. +// +// Solidity: function setTokenMaxLimit(address token, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) SetTokenMaxLimit(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetTokenMaxLimit(&_ERC20Safe.TransactOpts, token, amount) +} + +// SetTokenMinLimit is a paid mutator transaction binding the contract method 0x920b0308. +// +// Solidity: function setTokenMinLimit(address token, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeTransactor) SetTokenMinLimit(opts *bind.TransactOpts, token common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "setTokenMinLimit", token, amount) +} + +// SetTokenMinLimit is a paid mutator transaction binding the contract method 0x920b0308. +// +// Solidity: function setTokenMinLimit(address token, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeSession) SetTokenMinLimit(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetTokenMinLimit(&_ERC20Safe.TransactOpts, token, amount) +} + +// SetTokenMinLimit is a paid mutator transaction binding the contract method 0x920b0308. +// +// Solidity: function setTokenMinLimit(address token, uint256 amount) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) SetTokenMinLimit(token common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.SetTokenMinLimit(&_ERC20Safe.TransactOpts, token, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xdbba0f01. +// +// Solidity: function transfer(address tokenAddress, uint256 amount, address recipientAddress) returns(bool) +func (_ERC20Safe *ERC20SafeTransactor) Transfer(opts *bind.TransactOpts, tokenAddress common.Address, amount *big.Int, recipientAddress common.Address) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "transfer", tokenAddress, amount, recipientAddress) +} + +// Transfer is a paid mutator transaction binding the contract method 0xdbba0f01. +// +// Solidity: function transfer(address tokenAddress, uint256 amount, address recipientAddress) returns(bool) +func (_ERC20Safe *ERC20SafeSession) Transfer(tokenAddress common.Address, amount *big.Int, recipientAddress common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.Transfer(&_ERC20Safe.TransactOpts, tokenAddress, amount, recipientAddress) +} + +// Transfer is a paid mutator transaction binding the contract method 0xdbba0f01. +// +// Solidity: function transfer(address tokenAddress, uint256 amount, address recipientAddress) returns(bool) +func (_ERC20Safe *ERC20SafeTransactorSession) Transfer(tokenAddress common.Address, amount *big.Int, recipientAddress common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.Transfer(&_ERC20Safe.TransactOpts, tokenAddress, amount, recipientAddress) +} + +// TransferAdmin is a paid mutator transaction binding the contract method 0x75829def. +// +// Solidity: function transferAdmin(address newAdmin) returns() +func (_ERC20Safe *ERC20SafeTransactor) TransferAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "transferAdmin", newAdmin) +} + +// TransferAdmin is a paid mutator transaction binding the contract method 0x75829def. +// +// Solidity: function transferAdmin(address newAdmin) returns() +func (_ERC20Safe *ERC20SafeSession) TransferAdmin(newAdmin common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.TransferAdmin(&_ERC20Safe.TransactOpts, newAdmin) +} + +// TransferAdmin is a paid mutator transaction binding the contract method 0x75829def. +// +// Solidity: function transferAdmin(address newAdmin) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) TransferAdmin(newAdmin common.Address) (*types.Transaction, error) { + return _ERC20Safe.Contract.TransferAdmin(&_ERC20Safe.TransactOpts, newAdmin) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_ERC20Safe *ERC20SafeTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "unpause") +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_ERC20Safe *ERC20SafeSession) Unpause() (*types.Transaction, error) { + return _ERC20Safe.Contract.Unpause(&_ERC20Safe.TransactOpts) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_ERC20Safe *ERC20SafeTransactorSession) Unpause() (*types.Transaction, error) { + return _ERC20Safe.Contract.Unpause(&_ERC20Safe.TransactOpts) +} + +// WhitelistToken is a paid mutator transaction binding the contract method 0x1ce330ec. +// +// Solidity: function whitelistToken(address token, uint256 minimumAmount, uint256 maximumAmount) returns() +func (_ERC20Safe *ERC20SafeTransactor) WhitelistToken(opts *bind.TransactOpts, token common.Address, minimumAmount *big.Int, maximumAmount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.contract.Transact(opts, "whitelistToken", token, minimumAmount, maximumAmount) +} + +// WhitelistToken is a paid mutator transaction binding the contract method 0x1ce330ec. +// +// Solidity: function whitelistToken(address token, uint256 minimumAmount, uint256 maximumAmount) returns() +func (_ERC20Safe *ERC20SafeSession) WhitelistToken(token common.Address, minimumAmount *big.Int, maximumAmount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.WhitelistToken(&_ERC20Safe.TransactOpts, token, minimumAmount, maximumAmount) +} + +// WhitelistToken is a paid mutator transaction binding the contract method 0x1ce330ec. +// +// Solidity: function whitelistToken(address token, uint256 minimumAmount, uint256 maximumAmount) returns() +func (_ERC20Safe *ERC20SafeTransactorSession) WhitelistToken(token common.Address, minimumAmount *big.Int, maximumAmount *big.Int) (*types.Transaction, error) { + return _ERC20Safe.Contract.WhitelistToken(&_ERC20Safe.TransactOpts, token, minimumAmount, maximumAmount) +} + +// ERC20SafeAdminRoleTransferredIterator is returned from FilterAdminRoleTransferred and is used to iterate over the raw logs and unpacked data for AdminRoleTransferred events raised by the ERC20Safe contract. +type ERC20SafeAdminRoleTransferredIterator struct { + Event *ERC20SafeAdminRoleTransferred // 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 *ERC20SafeAdminRoleTransferredIterator) 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(ERC20SafeAdminRoleTransferred) + 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(ERC20SafeAdminRoleTransferred) + 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 *ERC20SafeAdminRoleTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20SafeAdminRoleTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20SafeAdminRoleTransferred represents a AdminRoleTransferred event raised by the ERC20Safe contract. +type ERC20SafeAdminRoleTransferred struct { + PreviousAdmin common.Address + NewAdmin common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAdminRoleTransferred is a free log retrieval operation binding the contract event 0xe379ac64de02d8184ca1a871ac486cb8137de77e485ede140e97057b9c765ffd. +// +// Solidity: event AdminRoleTransferred(address indexed previousAdmin, address indexed newAdmin) +func (_ERC20Safe *ERC20SafeFilterer) FilterAdminRoleTransferred(opts *bind.FilterOpts, previousAdmin []common.Address, newAdmin []common.Address) (*ERC20SafeAdminRoleTransferredIterator, error) { + + var previousAdminRule []interface{} + for _, previousAdminItem := range previousAdmin { + previousAdminRule = append(previousAdminRule, previousAdminItem) + } + var newAdminRule []interface{} + for _, newAdminItem := range newAdmin { + newAdminRule = append(newAdminRule, newAdminItem) + } + + logs, sub, err := _ERC20Safe.contract.FilterLogs(opts, "AdminRoleTransferred", previousAdminRule, newAdminRule) + if err != nil { + return nil, err + } + return &ERC20SafeAdminRoleTransferredIterator{contract: _ERC20Safe.contract, event: "AdminRoleTransferred", logs: logs, sub: sub}, nil +} + +// WatchAdminRoleTransferred is a free log subscription operation binding the contract event 0xe379ac64de02d8184ca1a871ac486cb8137de77e485ede140e97057b9c765ffd. +// +// Solidity: event AdminRoleTransferred(address indexed previousAdmin, address indexed newAdmin) +func (_ERC20Safe *ERC20SafeFilterer) WatchAdminRoleTransferred(opts *bind.WatchOpts, sink chan<- *ERC20SafeAdminRoleTransferred, previousAdmin []common.Address, newAdmin []common.Address) (event.Subscription, error) { + + var previousAdminRule []interface{} + for _, previousAdminItem := range previousAdmin { + previousAdminRule = append(previousAdminRule, previousAdminItem) + } + var newAdminRule []interface{} + for _, newAdminItem := range newAdmin { + newAdminRule = append(newAdminRule, newAdminItem) + } + + logs, sub, err := _ERC20Safe.contract.WatchLogs(opts, "AdminRoleTransferred", previousAdminRule, newAdminRule) + 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(ERC20SafeAdminRoleTransferred) + if err := _ERC20Safe.contract.UnpackLog(event, "AdminRoleTransferred", 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 +} + +// ParseAdminRoleTransferred is a log parse operation binding the contract event 0xe379ac64de02d8184ca1a871ac486cb8137de77e485ede140e97057b9c765ffd. +// +// Solidity: event AdminRoleTransferred(address indexed previousAdmin, address indexed newAdmin) +func (_ERC20Safe *ERC20SafeFilterer) ParseAdminRoleTransferred(log types.Log) (*ERC20SafeAdminRoleTransferred, error) { + event := new(ERC20SafeAdminRoleTransferred) + if err := _ERC20Safe.contract.UnpackLog(event, "AdminRoleTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20SafeBridgeTransferredIterator is returned from FilterBridgeTransferred and is used to iterate over the raw logs and unpacked data for BridgeTransferred events raised by the ERC20Safe contract. +type ERC20SafeBridgeTransferredIterator struct { + Event *ERC20SafeBridgeTransferred // 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 *ERC20SafeBridgeTransferredIterator) 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(ERC20SafeBridgeTransferred) + 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(ERC20SafeBridgeTransferred) + 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 *ERC20SafeBridgeTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20SafeBridgeTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20SafeBridgeTransferred represents a BridgeTransferred event raised by the ERC20Safe contract. +type ERC20SafeBridgeTransferred struct { + PreviousBridge common.Address + NewBridge common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBridgeTransferred is a free log retrieval operation binding the contract event 0xcca5fddab921a878ddbd4edb737a2cf3ac6df70864f108606647d1b37a5e07a0. +// +// Solidity: event BridgeTransferred(address indexed previousBridge, address indexed newBridge) +func (_ERC20Safe *ERC20SafeFilterer) FilterBridgeTransferred(opts *bind.FilterOpts, previousBridge []common.Address, newBridge []common.Address) (*ERC20SafeBridgeTransferredIterator, error) { + + var previousBridgeRule []interface{} + for _, previousBridgeItem := range previousBridge { + previousBridgeRule = append(previousBridgeRule, previousBridgeItem) + } + var newBridgeRule []interface{} + for _, newBridgeItem := range newBridge { + newBridgeRule = append(newBridgeRule, newBridgeItem) + } + + logs, sub, err := _ERC20Safe.contract.FilterLogs(opts, "BridgeTransferred", previousBridgeRule, newBridgeRule) + if err != nil { + return nil, err + } + return &ERC20SafeBridgeTransferredIterator{contract: _ERC20Safe.contract, event: "BridgeTransferred", logs: logs, sub: sub}, nil +} + +// WatchBridgeTransferred is a free log subscription operation binding the contract event 0xcca5fddab921a878ddbd4edb737a2cf3ac6df70864f108606647d1b37a5e07a0. +// +// Solidity: event BridgeTransferred(address indexed previousBridge, address indexed newBridge) +func (_ERC20Safe *ERC20SafeFilterer) WatchBridgeTransferred(opts *bind.WatchOpts, sink chan<- *ERC20SafeBridgeTransferred, previousBridge []common.Address, newBridge []common.Address) (event.Subscription, error) { + + var previousBridgeRule []interface{} + for _, previousBridgeItem := range previousBridge { + previousBridgeRule = append(previousBridgeRule, previousBridgeItem) + } + var newBridgeRule []interface{} + for _, newBridgeItem := range newBridge { + newBridgeRule = append(newBridgeRule, newBridgeItem) + } + + logs, sub, err := _ERC20Safe.contract.WatchLogs(opts, "BridgeTransferred", previousBridgeRule, newBridgeRule) + 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(ERC20SafeBridgeTransferred) + if err := _ERC20Safe.contract.UnpackLog(event, "BridgeTransferred", 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 +} + +// ParseBridgeTransferred is a log parse operation binding the contract event 0xcca5fddab921a878ddbd4edb737a2cf3ac6df70864f108606647d1b37a5e07a0. +// +// Solidity: event BridgeTransferred(address indexed previousBridge, address indexed newBridge) +func (_ERC20Safe *ERC20SafeFilterer) ParseBridgeTransferred(log types.Log) (*ERC20SafeBridgeTransferred, error) { + event := new(ERC20SafeBridgeTransferred) + if err := _ERC20Safe.contract.UnpackLog(event, "BridgeTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20SafeERC20DepositIterator is returned from FilterERC20Deposit and is used to iterate over the raw logs and unpacked data for ERC20Deposit events raised by the ERC20Safe contract. +type ERC20SafeERC20DepositIterator struct { + Event *ERC20SafeERC20Deposit // 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 *ERC20SafeERC20DepositIterator) 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(ERC20SafeERC20Deposit) + 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(ERC20SafeERC20Deposit) + 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 *ERC20SafeERC20DepositIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20SafeERC20DepositIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20SafeERC20Deposit represents a ERC20Deposit event raised by the ERC20Safe contract. +type ERC20SafeERC20Deposit struct { + DepositNonce *big.Int + BatchId *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterERC20Deposit is a free log retrieval operation binding the contract event 0x6c15ce44793c685a79cde26a0bd5419ef4f3a337991f156be7b365962001b4a7. +// +// Solidity: event ERC20Deposit(uint112 depositNonce, uint112 batchId) +func (_ERC20Safe *ERC20SafeFilterer) FilterERC20Deposit(opts *bind.FilterOpts) (*ERC20SafeERC20DepositIterator, error) { + + logs, sub, err := _ERC20Safe.contract.FilterLogs(opts, "ERC20Deposit") + if err != nil { + return nil, err + } + return &ERC20SafeERC20DepositIterator{contract: _ERC20Safe.contract, event: "ERC20Deposit", logs: logs, sub: sub}, nil +} + +// WatchERC20Deposit is a free log subscription operation binding the contract event 0x6c15ce44793c685a79cde26a0bd5419ef4f3a337991f156be7b365962001b4a7. +// +// Solidity: event ERC20Deposit(uint112 depositNonce, uint112 batchId) +func (_ERC20Safe *ERC20SafeFilterer) WatchERC20Deposit(opts *bind.WatchOpts, sink chan<- *ERC20SafeERC20Deposit) (event.Subscription, error) { + + logs, sub, err := _ERC20Safe.contract.WatchLogs(opts, "ERC20Deposit") + 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(ERC20SafeERC20Deposit) + if err := _ERC20Safe.contract.UnpackLog(event, "ERC20Deposit", 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 +} + +// ParseERC20Deposit is a log parse operation binding the contract event 0x6c15ce44793c685a79cde26a0bd5419ef4f3a337991f156be7b365962001b4a7. +// +// Solidity: event ERC20Deposit(uint112 depositNonce, uint112 batchId) +func (_ERC20Safe *ERC20SafeFilterer) ParseERC20Deposit(log types.Log) (*ERC20SafeERC20Deposit, error) { + event := new(ERC20SafeERC20Deposit) + if err := _ERC20Safe.contract.UnpackLog(event, "ERC20Deposit", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/executors/ethereum/common.go b/executors/ethereum/common.go new file mode 100644 index 00000000..71f5e146 --- /dev/null +++ b/executors/ethereum/common.go @@ -0,0 +1,25 @@ +package ethereum + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// DepositInfo is the deposit info list +type DepositInfo struct { + DepositNonce uint64 `json:"DepositNonce"` + Token string `json:"Token"` + ContractAddress string `json:"ContractAddress"` + contractAddress common.Address + amount *big.Int + Amount string `json:"Amount"` +} + +// BatchInfo is the batch info list +type BatchInfo struct { + OldSafeContractAddress string `json:"OldSafeContractAddress"` + NewSafeContractAddress string `json:"NewSafeContractAddress"` + BatchID uint64 `json:"BatchID"` + DepositsInfo []*DepositInfo `json:"DepositsInfo"` +} diff --git a/executors/ethereum/errors.go b/executors/ethereum/errors.go new file mode 100644 index 00000000..3bb07bac --- /dev/null +++ b/executors/ethereum/errors.go @@ -0,0 +1,9 @@ +package ethereum + +import "errors" + +var ( + errEmptyTokensList = errors.New("empty tokens list") + errNilTokensMapper = errors.New("nil MultiversX to Ethereum tokens mapper") + errNilErc20ContractsHolder = errors.New("nil ERC20 contracts holder") +) diff --git a/executors/ethereum/interface.go b/executors/ethereum/interface.go new file mode 100644 index 00000000..5ddaf025 --- /dev/null +++ b/executors/ethereum/interface.go @@ -0,0 +1,27 @@ +package ethereum + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +// TokensMapper can convert a token bytes from one chain to another +type TokensMapper interface { + ConvertToken(ctx context.Context, sourceBytes []byte) ([]byte, error) + IsInterfaceNil() bool +} + +// Erc20ContractsHolder defines the Ethereum ERC20 contract operations +type Erc20ContractsHolder interface { + BalanceOf(ctx context.Context, erc20Address common.Address, address common.Address) (*big.Int, error) + IsInterfaceNil() bool +} + +// SafeContractWrapper defines the operations for the safe contract +type SafeContractWrapper interface { + DepositsCount(opts *bind.CallOpts) (uint64, error) + BatchesCount(opts *bind.CallOpts) (uint64, error) +} diff --git a/executors/ethereum/migrationBatchCreator.go b/executors/ethereum/migrationBatchCreator.go new file mode 100644 index 00000000..c208c799 --- /dev/null +++ b/executors/ethereum/migrationBatchCreator.go @@ -0,0 +1,130 @@ +package ethereum + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/multiversx/mx-chain-core-go/core/check" +) + +var zero = big.NewInt(0) + +// ArgsMigrationBatchCreator is the argument for the NewMigrationBatchCreator constructor +type ArgsMigrationBatchCreator struct { + TokensList []string + TokensMapper TokensMapper + Erc20ContractsHolder Erc20ContractsHolder + SafeContractAddress common.Address + SafeContractWrapper SafeContractWrapper +} + +type migrationBatchCreator struct { + tokensList []string + tokensMapper TokensMapper + erc20ContractsHolder Erc20ContractsHolder + safeContractAddress common.Address + safeContractWrapper SafeContractWrapper +} + +// NewMigrationBatchCreator creates a new instance of type migrationBatchCreator that is able to generate the migration batch output file +func NewMigrationBatchCreator(args ArgsMigrationBatchCreator) (*migrationBatchCreator, error) { + if len(args.TokensList) == 0 { + return nil, errEmptyTokensList + } + if check.IfNil(args.TokensMapper) { + return nil, errNilTokensMapper + } + if check.IfNil(args.Erc20ContractsHolder) { + return nil, errNilErc20ContractsHolder + } + + return &migrationBatchCreator{ + tokensList: args.TokensList, + tokensMapper: args.TokensMapper, + erc20ContractsHolder: args.Erc20ContractsHolder, + safeContractAddress: args.SafeContractAddress, + }, nil +} + +// CreateBatchInfo creates an instance of type BatchInfo +func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context) (*BatchInfo, error) { + batchesCount, err := creator.safeContractWrapper.BatchesCount(&bind.CallOpts{Context: ctx}) + if err != nil { + return nil, err + } + + depositsCount, err := creator.safeContractWrapper.DepositsCount(&bind.CallOpts{Context: ctx}) + if err != nil { + return nil, err + } + + deposits, err := creator.fetchERC20ContractsAddresses(ctx, depositsCount) + if err != nil { + return nil, err + } + + err = creator.fetchBalances(ctx, deposits) + if err != nil { + return nil, err + } + + return creator.assembleBatchInfo(batchesCount, deposits) +} + +func (creator *migrationBatchCreator) fetchERC20ContractsAddresses(ctx context.Context, lastDepositNonce uint64) ([]*DepositInfo, error) { + deposits := make([]*DepositInfo, 0, len(creator.tokensList)) + for idx, token := range creator.tokensList { + addressBytes, err := creator.tokensMapper.ConvertToken(ctx, []byte(token)) + if err != nil { + return nil, err + } + + deposit := &DepositInfo{ + DepositNonce: lastDepositNonce + uint64(1+idx), + Token: token, + ContractAddress: common.BytesToAddress(addressBytes).String(), + contractAddress: common.BytesToAddress(addressBytes), + Amount: "", + } + + deposits = append(deposits, deposit) + } + + return deposits, nil +} + +func (creator *migrationBatchCreator) fetchBalances(ctx context.Context, deposits []*DepositInfo) error { + for _, deposit := range deposits { + balance, err := creator.erc20ContractsHolder.BalanceOf(ctx, deposit.contractAddress, creator.safeContractAddress) + if err != nil { + return fmt.Errorf("%w for address %s in ERC20 contract %s", err, creator.safeContractAddress.String(), deposit.contractAddress.String()) + } + + deposit.amount = balance + deposit.Amount = balance.String() + } + + return nil +} + +func (creator *migrationBatchCreator) assembleBatchInfo(batchesCount uint64, deposits []*DepositInfo) (*BatchInfo, error) { + batchInfo := &BatchInfo{ + OldSafeContractAddress: creator.safeContractAddress.String(), + NewSafeContractAddress: "", + BatchID: batchesCount + 1, + DepositsInfo: make([]*DepositInfo, 0, len(deposits)), + } + + for _, deposit := range deposits { + if deposit.amount.Cmp(zero) <= 0 { + continue + } + + batchInfo.DepositsInfo = append(batchInfo.DepositsInfo, deposit) + } + + return batchInfo, nil +} From 09c9833422bf4f7496d0006e7db82cbfbe0bf34a Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Mon, 2 Sep 2024 16:12:45 +0300 Subject: [PATCH 2/3] - fixes - added unit tests --- cmd/migration/config/config.toml | 2 +- cmd/migration/config/migration.json | 82 +++++- cmd/migration/flags.go | 13 +- cmd/migration/main.go | 38 ++- config/tomlConfigs_test.go | 6 +- executors/ethereum/errors.go | 1 + executors/ethereum/migrationBatchCreator.go | 12 +- .../ethereum/migrationBatchCreator_test.go | 236 ++++++++++++++++++ testsCommon/bridge/safeContractWrapperStub.go | 27 ++ 9 files changed, 385 insertions(+), 32 deletions(-) create mode 100644 executors/ethereum/migrationBatchCreator_test.go create mode 100644 testsCommon/bridge/safeContractWrapperStub.go diff --git a/cmd/migration/config/config.toml b/cmd/migration/config/config.toml index 77cfefc0..e6a8e24f 100644 --- a/cmd/migration/config/config.toml +++ b/cmd/migration/config/config.toml @@ -19,7 +19,7 @@ [MultiversX] NetworkAddress = "https://devnet-gateway.multiversx.com" # the network address - SafeContractAddress = "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus" # the multiversx address for the safe contract + MultisigContractAddress = "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus" [MultiversX.Proxy] CacherExpirationSeconds = 600 # the caching time in seconds diff --git a/cmd/migration/config/migration.json b/cmd/migration/config/migration.json index 4698c37e..3f03dc36 100644 --- a/cmd/migration/config/migration.json +++ b/cmd/migration/config/migration.json @@ -1,19 +1,79 @@ { - "OldSafeContractAddress": "A6504Cc508889bbDBd4B748aFf6EA6b5D0d2684c", - "NewSafeContractAddress": "3009d97FfeD62E57d444e552A9eDF9Ee6Bc8644c", - "BatchID": 22222, + "OldSafeContractAddress": "0x92A26975433A61CF1134802586aa669bAB8B69f3", + "NewSafeContractAddress": "0x37aaaf95887624a363effB7762D489E3C05c2a02", + "BatchID": 3547, "DepositsInfo": [ { - "DepositNonce": 1, - "Token": "USDC", - "ContractAddress": "ssss", - "Amount": "11111111111" + "DepositNonce": 4651, + "Token": "ETHUSDC-220753", + "ContractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "Amount": "7245293620507" }, { - "DepositNonce": 2, - "Token": "MEME", - "ContractAddress": "ssss", - "Amount": "2222222" + "DepositNonce": 4652, + "Token": "ETHUTK-8cdf7a", + "ContractAddress": "0xdc9Ac3C20D1ed0B540dF9b1feDC10039Df13F99c", + "Amount": "224564169411881824066539333" + }, + { + "DepositNonce": 4653, + "Token": "ETHUSDT-9c73c6", + "ContractAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7", + "Amount": "305146464594" + }, + { + "DepositNonce": 4654, + "Token": "ETHBUSD-450923", + "ContractAddress": "0x4Fabb145d64652a948d72533023f6E7A623C7C53", + "Amount": "22294352736330153151984" + }, + { + "DepositNonce": 4655, + "Token": "ETHHMT-18538a", + "ContractAddress": "0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867", + "Amount": "435000000000000000000" + }, + { + "DepositNonce": 4656, + "Token": "ETHCGG-ee4e0c", + "ContractAddress": "0x1fE24F25b1Cf609B9c4e7E12D802e3640dFA5e43", + "Amount": "1500138370967581082219795" + }, + { + "DepositNonce": 4657, + "Token": "ETHINFRA-60a3bf", + "ContractAddress": "0x013062189dc3dcc99e9Cee714c513033b8d99e3c", + "Amount": "141172595980399500424091" + }, + { + "DepositNonce": 4658, + "Token": "ETHWBTC-74e282", + "ContractAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "Amount": "3898848955" + }, + { + "DepositNonce": 4659, + "Token": "ETHWETH-e1c126", + "ContractAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "Amount": "725921417141355037005" + }, + { + "DepositNonce": 4660, + "Token": "ETHWSDAI-572803", + "ContractAddress": "0x83F20F44975D03b1b09e64809B757c47f942BEeA", + "Amount": "5431516086574385345409" + }, + { + "DepositNonce": 4661, + "Token": "ETHWDAI-bd65f9", + "ContractAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "Amount": "127608014625114134146189" + }, + { + "DepositNonce": 4662, + "Token": "ETHUMB-291202", + "ContractAddress": "0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2", + "Amount": "4669367702477323508554075" } ] } \ No newline at end of file diff --git a/cmd/migration/flags.go b/cmd/migration/flags.go index 2afce5a0..ee96b554 100644 --- a/cmd/migration/flags.go +++ b/cmd/migration/flags.go @@ -15,7 +15,6 @@ var ( " log level.", Value: "*:" + logger.LogDebug.String(), } - // configurationFile defines a flag for the path to the main toml configuration file configurationFile = cli.StringFlag{ Name: "config", Usage: "The `" + filePathPlaceholder + "` for the main configuration file. This TOML file contain the main " + @@ -27,6 +26,16 @@ var ( Usage: "This flag specifies the operation mode. Usage: generate, sign or execute", Value: generateMode, } + migrationJsonFile = cli.StringFlag{ + Name: "migration-file", + Usage: "The input or output .json file containing the migration data", + Value: "config/migration.json", + } + newSafeAddress = cli.StringFlag{ + Name: "new-safe-address", + Usage: "The new safe address on Ethereum", + Value: "", + } ) func getFlags() []cli.Flag { @@ -34,6 +43,8 @@ func getFlags() []cli.Flag { logLevel, configurationFile, mode, + migrationJsonFile, + newSafeAddress, } } func getFlagsConfig(ctx *cli.Context) config.ContextFlagsConfig { diff --git a/cmd/migration/main.go b/cmd/migration/main.go index 9efb7687..273452e0 100644 --- a/cmd/migration/main.go +++ b/cmd/migration/main.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "encoding/json" "fmt" @@ -11,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ethereumClient "github.com/multiversx/mx-bridge-eth-go/clients/ethereum" + "github.com/multiversx/mx-bridge-eth-go/clients/ethereum/contract" "github.com/multiversx/mx-bridge-eth-go/clients/multiversx" "github.com/multiversx/mx-bridge-eth-go/clients/multiversx/mappers" "github.com/multiversx/mx-bridge-eth-go/cmd/migration/disabled" @@ -74,7 +76,7 @@ func execute(ctx *cli.Context) error { operationMode := strings.ToLower(ctx.GlobalString(mode.Name)) switch operationMode { case generateMode: - return generate(cfg) + return generate(ctx, cfg) case signMode: //TODO: implement case executeMode: @@ -84,7 +86,7 @@ func execute(ctx *cli.Context) error { return fmt.Errorf("unknown execution mode: %s", operationMode) } -func generate(cfg config.MigrationToolConfig) error { +func generate(ctx *cli.Context, cfg config.MigrationToolConfig) error { argsProxy := blockchain.ArgsProxy{ ProxyURL: cfg.MultiversX.NetworkAddress, SameScState: false, @@ -99,16 +101,16 @@ func generate(cfg config.MigrationToolConfig) error { return err } - emptyAddress := data.NewAddressFromBytes(make([]byte, 0)) - safeAddress, err := data.NewAddressFromBech32String(cfg.MultiversX.SafeContractAddress) + dummyAddress := data.NewAddressFromBytes(bytes.Repeat([]byte{0x1}, 32)) + multisigAddress, err := data.NewAddressFromBech32String(cfg.MultiversX.MultisigContractAddress) if err != nil { return err } argsMXClientDataGetter := multiversx.ArgsMXClientDataGetter{ - MultisigContractAddress: emptyAddress, - SafeContractAddress: safeAddress, - RelayerAddress: emptyAddress, + MultisigContractAddress: multisigAddress, + SafeContractAddress: dummyAddress, + RelayerAddress: dummyAddress, Proxy: proxy, Log: log, } @@ -136,12 +138,18 @@ func generate(cfg config.MigrationToolConfig) error { return err } + safeEthAddress := common.HexToAddress(cfg.Eth.SafeContractAddress) + safeInstance, err := contract.NewERC20Safe(safeEthAddress, ethClient) + if err != nil { + return err + } + argsCreator := ethereum.ArgsMigrationBatchCreator{ TokensList: cfg.WhitelistedTokens.List, TokensMapper: tokensWrapper, Erc20ContractsHolder: erc20ContractsHolder, - SafeContractAddress: common.Address{}, - SafeContractWrapper: nil, + SafeContractAddress: safeEthAddress, + SafeContractWrapper: safeInstance, } creator, err := ethereum.NewMigrationBatchCreator(argsCreator) @@ -149,12 +157,17 @@ func generate(cfg config.MigrationToolConfig) error { return err } - batchInfo, err := creator.CreateBatchInfo(context.Background()) + newSafeAddressString := ctx.GlobalString(newSafeAddress.Name) + if len(newSafeAddressString) == 0 { + return fmt.Errorf("invalid new safe address for Ethereum") + } + newSafeAddressValue := common.HexToAddress(ctx.GlobalString(newSafeAddress.Name)) + + batchInfo, err := creator.CreateBatchInfo(context.Background(), newSafeAddressValue) if err != nil { return err } - //TODO: save in a file val, err := json.MarshalIndent(batchInfo, "", " ") if err != nil { return err @@ -162,7 +175,8 @@ func generate(cfg config.MigrationToolConfig) error { log.Info(string(val)) - return nil + jsonFilename := ctx.GlobalString(migrationJsonFile.Name) + return os.WriteFile(jsonFilename, val, os.ModePerm) } func loadConfig(filepath string) (config.MigrationToolConfig, error) { diff --git a/config/tomlConfigs_test.go b/config/tomlConfigs_test.go index 30f79d3b..4e0b3498 100644 --- a/config/tomlConfigs_test.go +++ b/config/tomlConfigs_test.go @@ -481,8 +481,8 @@ func TestMigrationToolConfig(t *testing.T) { }, }, MultiversX: MultiversXConfig{ - NetworkAddress: "https://devnet-gateway.multiversx.com", - SafeContractAddress: "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus", + NetworkAddress: "https://devnet-gateway.multiversx.com", + MultisigContractAddress: "erd1qqqqqqqqqqqqqpgqzyuaqg3dl7rqlkudrsnm5ek0j3a97qevd8sszj0glf", Proxy: ProxyConfig{ CacherExpirationSeconds: 600, RestAPIEntityType: "observer", @@ -534,7 +534,7 @@ func TestMigrationToolConfig(t *testing.T) { [MultiversX] NetworkAddress = "https://devnet-gateway.multiversx.com" # the network address - SafeContractAddress = "erd1qqqqqqqqqqqqqpgqtvnswnzxxz8susupesys0hvg7q2z5nawrcjq06qdus" # the multiversx address for the safe contract + MultisigContractAddress = "erd1qqqqqqqqqqqqqpgqzyuaqg3dl7rqlkudrsnm5ek0j3a97qevd8sszj0glf" [MultiversX.Proxy] CacherExpirationSeconds = 600 # the caching time in seconds diff --git a/executors/ethereum/errors.go b/executors/ethereum/errors.go index 3bb07bac..25687f62 100644 --- a/executors/ethereum/errors.go +++ b/executors/ethereum/errors.go @@ -6,4 +6,5 @@ var ( errEmptyTokensList = errors.New("empty tokens list") errNilTokensMapper = errors.New("nil MultiversX to Ethereum tokens mapper") errNilErc20ContractsHolder = errors.New("nil ERC20 contracts holder") + errNilSafeContractWrapper = errors.New("nil safe contract wrapper") ) diff --git a/executors/ethereum/migrationBatchCreator.go b/executors/ethereum/migrationBatchCreator.go index c208c799..bf2be86f 100644 --- a/executors/ethereum/migrationBatchCreator.go +++ b/executors/ethereum/migrationBatchCreator.go @@ -40,17 +40,21 @@ func NewMigrationBatchCreator(args ArgsMigrationBatchCreator) (*migrationBatchCr if check.IfNil(args.Erc20ContractsHolder) { return nil, errNilErc20ContractsHolder } + if check.IfNilReflect(args.SafeContractWrapper) { + return nil, errNilSafeContractWrapper + } return &migrationBatchCreator{ tokensList: args.TokensList, tokensMapper: args.TokensMapper, erc20ContractsHolder: args.Erc20ContractsHolder, safeContractAddress: args.SafeContractAddress, + safeContractWrapper: args.SafeContractWrapper, }, nil } // CreateBatchInfo creates an instance of type BatchInfo -func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context) (*BatchInfo, error) { +func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context, newSafeAddress common.Address) (*BatchInfo, error) { batchesCount, err := creator.safeContractWrapper.BatchesCount(&bind.CallOpts{Context: ctx}) if err != nil { return nil, err @@ -71,7 +75,7 @@ func (creator *migrationBatchCreator) CreateBatchInfo(ctx context.Context) (*Bat return nil, err } - return creator.assembleBatchInfo(batchesCount, deposits) + return creator.assembleBatchInfo(batchesCount, deposits, newSafeAddress) } func (creator *migrationBatchCreator) fetchERC20ContractsAddresses(ctx context.Context, lastDepositNonce uint64) ([]*DepositInfo, error) { @@ -110,10 +114,10 @@ func (creator *migrationBatchCreator) fetchBalances(ctx context.Context, deposit return nil } -func (creator *migrationBatchCreator) assembleBatchInfo(batchesCount uint64, deposits []*DepositInfo) (*BatchInfo, error) { +func (creator *migrationBatchCreator) assembleBatchInfo(batchesCount uint64, deposits []*DepositInfo, newSafeAddress common.Address) (*BatchInfo, error) { batchInfo := &BatchInfo{ OldSafeContractAddress: creator.safeContractAddress.String(), - NewSafeContractAddress: "", + NewSafeContractAddress: newSafeAddress.String(), BatchID: batchesCount + 1, DepositsInfo: make([]*DepositInfo, 0, len(deposits)), } diff --git a/executors/ethereum/migrationBatchCreator_test.go b/executors/ethereum/migrationBatchCreator_test.go new file mode 100644 index 00000000..b5edcba4 --- /dev/null +++ b/executors/ethereum/migrationBatchCreator_test.go @@ -0,0 +1,236 @@ +package ethereum + +import ( + "bytes" + "context" + "errors" + "fmt" + "math/big" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/multiversx/mx-bridge-eth-go/testsCommon/bridge" + "github.com/stretchr/testify/assert" +) + +var safeContractAddress = common.HexToAddress(strings.Repeat("9", 40)) +var tkn1Erc20Address = bytes.Repeat([]byte("2"), 20) +var tkn2Erc20Address = bytes.Repeat([]byte("3"), 20) +var balanceOfTkn1 = big.NewInt(37) +var balanceOfTkn2 = big.NewInt(38) + +func createMockArgsForMigrationBatchCreator() ArgsMigrationBatchCreator { + return ArgsMigrationBatchCreator{ + TokensList: []string{"tkn1", "tkn2"}, + TokensMapper: &bridge.TokensMapperStub{}, + Erc20ContractsHolder: &bridge.ERC20ContractsHolderStub{}, + SafeContractAddress: safeContractAddress, + SafeContractWrapper: &bridge.SafeContractWrapperStub{}, + } +} + +func TestNewMigrationBatchCreator(t *testing.T) { + t.Parallel() + + t.Run("nil or empty tokens list should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.TokensList = nil + + creator, err := NewMigrationBatchCreator(args) + assert.Nil(t, creator) + assert.Equal(t, errEmptyTokensList, err) + + args = createMockArgsForMigrationBatchCreator() + args.TokensList = make([]string, 0) + + creator, err = NewMigrationBatchCreator(args) + assert.Nil(t, creator) + assert.Equal(t, errEmptyTokensList, err) + }) + t.Run("nil tokens mapper should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.TokensMapper = nil + + creator, err := NewMigrationBatchCreator(args) + assert.Nil(t, creator) + assert.Equal(t, errNilTokensMapper, err) + }) + t.Run("nil erc20 contracts holder should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.Erc20ContractsHolder = nil + + creator, err := NewMigrationBatchCreator(args) + assert.Nil(t, creator) + assert.Equal(t, errNilErc20ContractsHolder, err) + }) + t.Run("nil safe contract wrapper should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.SafeContractWrapper = nil + + creator, err := NewMigrationBatchCreator(args) + assert.Nil(t, creator) + assert.Equal(t, errNilSafeContractWrapper, err) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + + creator, err := NewMigrationBatchCreator(args) + assert.NotNil(t, creator) + assert.Nil(t, err) + }) +} + +func TestMigrationBatchCreator_CreateBatchInfo(t *testing.T) { + t.Parallel() + + expectedErr := errors.New("expected error") + newSafeContractAddress := common.HexToAddress(strings.Repeat("8", 40)) + t.Run("BatchesCount errors should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.SafeContractWrapper = &bridge.SafeContractWrapperStub{ + BatchesCountCalled: func(opts *bind.CallOpts) (uint64, error) { + return 0, expectedErr + }, + } + + creator, _ := NewMigrationBatchCreator(args) + batch, err := creator.CreateBatchInfo(context.Background(), newSafeContractAddress) + assert.Equal(t, expectedErr, err) + assert.Nil(t, batch) + }) + t.Run("DepositsCount errors should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.SafeContractWrapper = &bridge.SafeContractWrapperStub{ + DepositsCountCalled: func(opts *bind.CallOpts) (uint64, error) { + return 0, expectedErr + }, + } + + creator, _ := NewMigrationBatchCreator(args) + batch, err := creator.CreateBatchInfo(context.Background(), newSafeContractAddress) + assert.Equal(t, expectedErr, err) + assert.Nil(t, batch) + }) + t.Run("ConvertToken errors should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.TokensMapper = &bridge.TokensMapperStub{ + ConvertTokenCalled: func(ctx context.Context, sourceBytes []byte) ([]byte, error) { + return nil, expectedErr + }, + } + + creator, _ := NewMigrationBatchCreator(args) + batch, err := creator.CreateBatchInfo(context.Background(), newSafeContractAddress) + assert.Equal(t, expectedErr, err) + assert.Nil(t, batch) + }) + t.Run("BalanceOf errors should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgsForMigrationBatchCreator() + args.Erc20ContractsHolder = &bridge.ERC20ContractsHolderStub{ + BalanceOfCalled: func(ctx context.Context, erc20Address common.Address, address common.Address) (*big.Int, error) { + return nil, expectedErr + }, + } + + creator, _ := NewMigrationBatchCreator(args) + batch, err := creator.CreateBatchInfo(context.Background(), newSafeContractAddress) + assert.ErrorIs(t, err, expectedErr) + assert.Nil(t, batch) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + + depositCountStart := uint64(39) + depositCount := depositCountStart + batchesCount := uint64(2244) + args := createMockArgsForMigrationBatchCreator() + args.TokensMapper = &bridge.TokensMapperStub{ + ConvertTokenCalled: func(ctx context.Context, sourceBytes []byte) ([]byte, error) { + if string(sourceBytes) == "tkn1" { + return tkn1Erc20Address, nil + } + if string(sourceBytes) == "tkn2" { + return tkn2Erc20Address, nil + } + + return nil, fmt.Errorf("unexpected source bytes") + }, + } + args.Erc20ContractsHolder = &bridge.ERC20ContractsHolderStub{ + BalanceOfCalled: func(ctx context.Context, erc20Address common.Address, address common.Address) (*big.Int, error) { + assert.Equal(t, address.String(), safeContractAddress.String()) + + if string(erc20Address.Bytes()) == string(tkn1Erc20Address) { + return balanceOfTkn1, nil + } + if string(erc20Address.Bytes()) == string(tkn2Erc20Address) { + return balanceOfTkn2, nil + } + + return nil, fmt.Errorf("unexpected ERC20 contract address") + }, + } + args.SafeContractWrapper = &bridge.SafeContractWrapperStub{ + DepositsCountCalled: func(opts *bind.CallOpts) (uint64, error) { + depositCountValue := depositCount + depositCount++ + + return depositCountValue, nil + + }, + BatchesCountCalled: func(opts *bind.CallOpts) (uint64, error) { + return batchesCount, nil + }, + } + creator, _ := NewMigrationBatchCreator(args) + + expectedBatch := &BatchInfo{ + OldSafeContractAddress: safeContractAddress.String(), + NewSafeContractAddress: newSafeContractAddress.String(), + BatchID: 2245, + DepositsInfo: []*DepositInfo{ + { + DepositNonce: 40, + Token: "tkn1", + ContractAddress: common.BytesToAddress(tkn1Erc20Address).String(), + contractAddress: common.BytesToAddress(tkn1Erc20Address), + amount: big.NewInt(37), + Amount: "37", + }, + { + DepositNonce: 41, + Token: "tkn2", + ContractAddress: common.BytesToAddress(tkn2Erc20Address).String(), + contractAddress: common.BytesToAddress(tkn2Erc20Address), + amount: big.NewInt(38), + Amount: "38", + }, + }, + } + + batch, err := creator.CreateBatchInfo(context.Background(), newSafeContractAddress) + assert.Nil(t, err) + assert.Equal(t, expectedBatch, batch) + }) + +} diff --git a/testsCommon/bridge/safeContractWrapperStub.go b/testsCommon/bridge/safeContractWrapperStub.go new file mode 100644 index 00000000..9da42c08 --- /dev/null +++ b/testsCommon/bridge/safeContractWrapperStub.go @@ -0,0 +1,27 @@ +package bridge + +import "github.com/ethereum/go-ethereum/accounts/abi/bind" + +// SafeContractWrapperStub - +type SafeContractWrapperStub struct { + DepositsCountCalled func(opts *bind.CallOpts) (uint64, error) + BatchesCountCalled func(opts *bind.CallOpts) (uint64, error) +} + +// DepositsCount - +func (stub *SafeContractWrapperStub) DepositsCount(opts *bind.CallOpts) (uint64, error) { + if stub.DepositsCountCalled != nil { + return stub.DepositsCountCalled(opts) + } + + return 0, nil +} + +// BatchesCount - +func (stub *SafeContractWrapperStub) BatchesCount(opts *bind.CallOpts) (uint64, error) { + if stub.BatchesCountCalled != nil { + return stub.BatchesCountCalled(opts) + } + + return 0, nil +} From 1a5f57d6f028c8655bb8362150444d1ed9a88995 Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Wed, 4 Sep 2024 19:07:32 +0300 Subject: [PATCH 3/3] - fixes after review: renaming --- executors/ethereum/common.go | 12 +++++----- executors/ethereum/migrationBatchCreator.go | 20 ++++++++-------- .../ethereum/migrationBatchCreator_test.go | 24 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/executors/ethereum/common.go b/executors/ethereum/common.go index 71f5e146..7732975d 100644 --- a/executors/ethereum/common.go +++ b/executors/ethereum/common.go @@ -8,12 +8,12 @@ import ( // DepositInfo is the deposit info list type DepositInfo struct { - DepositNonce uint64 `json:"DepositNonce"` - Token string `json:"Token"` - ContractAddress string `json:"ContractAddress"` - contractAddress common.Address - amount *big.Int - Amount string `json:"Amount"` + DepositNonce uint64 `json:"DepositNonce"` + Token string `json:"Token"` + ContractAddressString string `json:"ContractAddress"` + ContractAddress common.Address `json:"-"` + Amount *big.Int `json:"-"` + AmountString string `json:"Amount"` } // BatchInfo is the batch info list diff --git a/executors/ethereum/migrationBatchCreator.go b/executors/ethereum/migrationBatchCreator.go index bf2be86f..d5bae823 100644 --- a/executors/ethereum/migrationBatchCreator.go +++ b/executors/ethereum/migrationBatchCreator.go @@ -87,11 +87,11 @@ func (creator *migrationBatchCreator) fetchERC20ContractsAddresses(ctx context.C } deposit := &DepositInfo{ - DepositNonce: lastDepositNonce + uint64(1+idx), - Token: token, - ContractAddress: common.BytesToAddress(addressBytes).String(), - contractAddress: common.BytesToAddress(addressBytes), - Amount: "", + DepositNonce: lastDepositNonce + uint64(1+idx), + Token: token, + ContractAddressString: common.BytesToAddress(addressBytes).String(), + ContractAddress: common.BytesToAddress(addressBytes), + AmountString: "", } deposits = append(deposits, deposit) @@ -102,13 +102,13 @@ func (creator *migrationBatchCreator) fetchERC20ContractsAddresses(ctx context.C func (creator *migrationBatchCreator) fetchBalances(ctx context.Context, deposits []*DepositInfo) error { for _, deposit := range deposits { - balance, err := creator.erc20ContractsHolder.BalanceOf(ctx, deposit.contractAddress, creator.safeContractAddress) + balance, err := creator.erc20ContractsHolder.BalanceOf(ctx, deposit.ContractAddress, creator.safeContractAddress) if err != nil { - return fmt.Errorf("%w for address %s in ERC20 contract %s", err, creator.safeContractAddress.String(), deposit.contractAddress.String()) + return fmt.Errorf("%w for address %s in ERC20 contract %s", err, creator.safeContractAddress.String(), deposit.ContractAddress.String()) } - deposit.amount = balance - deposit.Amount = balance.String() + deposit.Amount = balance + deposit.AmountString = balance.String() } return nil @@ -123,7 +123,7 @@ func (creator *migrationBatchCreator) assembleBatchInfo(batchesCount uint64, dep } for _, deposit := range deposits { - if deposit.amount.Cmp(zero) <= 0 { + if deposit.Amount.Cmp(zero) <= 0 { continue } diff --git a/executors/ethereum/migrationBatchCreator_test.go b/executors/ethereum/migrationBatchCreator_test.go index b5edcba4..348a5235 100644 --- a/executors/ethereum/migrationBatchCreator_test.go +++ b/executors/ethereum/migrationBatchCreator_test.go @@ -210,20 +210,20 @@ func TestMigrationBatchCreator_CreateBatchInfo(t *testing.T) { BatchID: 2245, DepositsInfo: []*DepositInfo{ { - DepositNonce: 40, - Token: "tkn1", - ContractAddress: common.BytesToAddress(tkn1Erc20Address).String(), - contractAddress: common.BytesToAddress(tkn1Erc20Address), - amount: big.NewInt(37), - Amount: "37", + DepositNonce: 40, + Token: "tkn1", + ContractAddressString: common.BytesToAddress(tkn1Erc20Address).String(), + ContractAddress: common.BytesToAddress(tkn1Erc20Address), + Amount: big.NewInt(37), + AmountString: "37", }, { - DepositNonce: 41, - Token: "tkn2", - ContractAddress: common.BytesToAddress(tkn2Erc20Address).String(), - contractAddress: common.BytesToAddress(tkn2Erc20Address), - amount: big.NewInt(38), - Amount: "38", + DepositNonce: 41, + Token: "tkn2", + ContractAddressString: common.BytesToAddress(tkn2Erc20Address).String(), + ContractAddress: common.BytesToAddress(tkn2Erc20Address), + Amount: big.NewInt(38), + AmountString: "38", }, }, }