From 64fb56a1a9bfca0e069b7f3aaf394b20837e3014 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Wed, 31 Mar 2021 14:08:57 +0300 Subject: [PATCH 01/14] Matic bindings added --- bindings/ChannelImplementation.go | 24 +- bindings/HermesImplementation.go | 71 +++++- bindings/MystToken.go | 4 +- bindings/Registry.go | 395 +++++++++++++++++++++++++----- client/client.go | 2 +- gen.go | 2 +- 6 files changed, 415 insertions(+), 83 deletions(-) diff --git a/bindings/ChannelImplementation.go b/bindings/ChannelImplementation.go index 448df74..0b4a9df 100644 --- a/bindings/ChannelImplementation.go +++ b/bindings/ChannelImplementation.go @@ -1,6 +1,6 @@ /* Mysterium network payment library. * - * Copyright (C) 2020 BlockDev AG + * Copyright (C) 2021 BlockDev AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -43,10 +43,10 @@ var ( ) // ChannelImplementationABI is the input ABI used to generate the binding from. -const ChannelImplementationABI = "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"DestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timelock\",\"type\":\"uint256\"}],\"name\":\"ExitRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSettled\",\"type\":\"uint256\"}],\"name\":\"PromiseSettled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"claimEthers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exitRequest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timelock\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hermes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"settled\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIERC20Token\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dexAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_identityHash\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_lock\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settlePromise\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_validUntil\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"requestExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalizeExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_validUntil\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_operatorSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_hermesSignature\",\"type\":\"bytes\"}],\"name\":\"fastExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"setFundsDestinationByCheque\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" +const ChannelImplementationABI = "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"DestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timelock\",\"type\":\"uint256\"}],\"name\":\"ExitRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSettled\",\"type\":\"uint256\"}],\"name\":\"PromiseSettled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"claimEthers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exitRequest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timelock\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hermes\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"settled\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIERC20Token\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dexAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_lock\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settlePromise\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_validUntil\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"requestExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalizeExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_validUntil\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_operatorSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_hermesSignature\",\"type\":\"bytes\"}],\"name\":\"fastExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"setFundsDestinationByCheque\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" // ChannelImplementationBin is the compiled bytecode used for deploying new contracts. -var ChannelImplementationBin = "0x608060405234801561001057600080fd5b50612331806100206000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063f2fde38b11610064578063f2fde38b1461083b578063f4b3a1971461086e578063f58c5b6e146108a4578063f7013ef6146108b9578063fc0c546a1461090c57610354565b80638da5cb5b1461065d578063d8092c9214610672578063df8de3e7146106b1578063e9e8ad8b146106e457610354565b8063570ca735116100d1578063570ca735146104925780636931b550146104c35780636a2b76ad146104d85780636f1746301461059957610354565b806307e8ec1f14610359578063182f348814610370578063238e130a14610436578063392e53cd1461046957610354565b366103545760408051600280825260608083018452926020830190803683375050600b54604080516315ab88c960e31b815290519394506001600160a01b039091169263ad5c464892506004808301926020929190829003018186803b15801561016b57600080fd5b505afa15801561017f573d6000803e3d6000fd5b505050506040513d602081101561019557600080fd5b5051815182906000906101a457fe5b6001600160a01b0392831660209182029290920101526002548251911690829060019081106101cf57fe5b6001600160a01b03928316602091820292909201810191909152600b54604051637ff36ab560e01b8152600060048201818152306044840181905242606485018190526080602486019081528951608487015289519690981697637ff36ab597349795968b969495939460a49091019187810191028083838b5b83811015610261578181015183820152602001610249565b50505050905001955050505050506000604051808303818588803b15801561028857600080fd5b505af115801561029c573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156102c657600080fd5b8101908080516040519392919084600160201b8211156102e557600080fd5b9083019060208201858111156102fa57600080fd5b82518660208202830111600160201b8211171561031657600080fd5b82525081516020918201928201910280838360005b8381101561034357818101518382015260200161032b565b505050509050016040525050505050005b600080fd5b34801561036557600080fd5b5061036e610921565b005b34801561037c57600080fd5b5061036e6004803603606081101561039357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156103c257600080fd5b8201836020820111156103d457600080fd5b803590602001918460018302840111600160201b831117156103f557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610ae1945050505050565b34801561044257600080fd5b5061036e6004803603602081101561045957600080fd5b50356001600160a01b0316610d9b565b34801561047557600080fd5b5061047e610e7d565b604080519115158252519081900360200190f35b34801561049e57600080fd5b506104a7610e8e565b604080516001600160a01b039092168252519081900360200190f35b3480156104cf57600080fd5b5061036e610e9d565b3480156104e457600080fd5b5061036e600480360360408110156104fb57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561052557600080fd5b82018360208201111561053757600080fd5b803590602001918460018302840111600160201b8311171561055857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610eee945050505050565b3480156105a557600080fd5b5061036e600480360360808110156105bc57600080fd5b81359160208101359160408201359190810190608081016060820135600160201b8111156105e957600080fd5b8201836020820111156105fb57600080fd5b803590602001918460018302840111600160201b8311171561061c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061100d945050505050565b34801561066957600080fd5b506104a761133d565b34801561067e57600080fd5b5061068761134c565b604080516001600160a01b0394851681529290931660208301528183015290519081900360600190f35b3480156106bd57600080fd5b5061036e600480360360208110156106d457600080fd5b50356001600160a01b0316611368565b3480156106f057600080fd5b5061036e600480360360c081101561070757600080fd5b8135916020810135916001600160a01b036040830135169160608101359181019060a081016080820135600160201b81111561074257600080fd5b82018360208201111561075457600080fd5b803590602001918460018302840111600160201b8311171561077557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156107c757600080fd5b8201836020820111156107d957600080fd5b803590602001918460018302840111600160201b831117156107fa57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506114ce945050505050565b34801561084757600080fd5b5061036e6004803603602081101561085e57600080fd5b50356001600160a01b031661185e565b34801561087a57600080fd5b50610883611971565b604080519283526001600160a01b0390911660208301528051918290030190f35b3480156108b057600080fd5b506104a7611983565b3480156108c557600080fd5b5061036e600480360360a08110156108dc57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611992565b34801561091857600080fd5b506104a7611c7c565b6004541580159061093457506004544310155b61096f5760405162461bcd60e51b8152600401808060200182810382526042815260200180611fbd6042913960600191505060405180910390fd5b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156109ba57600080fd5b505afa1580156109ce573d6000803e3d6000fd5b505050506040513d60208110156109e457600080fd5b50516002546005546040805163a9059cbb60e01b81526001600160a01b03928316600482015260248101859052905193945091169163a9059cbb916044808201926020929091908290030181600087803b158015610a4157600080fd5b505af1158015610a55573d6000803e3d6000fd5b505050506040513d6020811015610a6b57600080fd5b5050600554604080516001600160a01b0390921682526020820183905280517f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649281900390910190a1506040805180820190915260008082526020909101819052600455600580546001600160a01b0319169055565b6000610aeb611c8b565b60045490915015610b2d5760405162461bcd60e51b815260040180806020018281038252604281526020018061204c6042913960600191505060405180910390fd5b438311610b6b5760405162461bcd60e51b815260040180806020018281038252604181526020018061208e6041913960600191505060405180910390fd5b828111610ba95760405162461bcd60e51b815260040180806020018281038252603b81526020018061213c603b913960400191505060405180910390fd5b6001600160a01b038416610bee5760405162461bcd60e51b815260040180806020018281038252602a815260200180612225602a913960400191505060405180910390fd5b600a546001600160a01b03163314610d2e5760003090506000610cdc846040518060400160405280600d81526020016c22bc34ba103932b8bab2b9ba1d60991b8152508489896040516020018085805190602001908083835b60208310610c665780518252601f199092019160209182019101610c47565b6001836020036101000a038019825116818451168082178552505050505050905001846001600160a01b031660601b8152601401836001600160a01b031660601b815260140182815260200194505050505060405160208183030381529060405280519060200120611c9390919063ffffffff16565b600a549091506001600160a01b03808316911614610d2b5760405162461bcd60e51b81526004018080602001828103825260268152602001806121ff6026913960400191505060405180910390fd5b50505b6040805180820182528281526001600160a01b03861660209182018190526004849055600580546001600160a01b0319169091179055815183815291517fe60f0366d8d61555184ea027447889648bae94ebfb1202a39544b6b6803969db9281900390910190a150505050565b6000546001600160a01b0316331480610dbd57506000546001600160a01b0316155b610e0e576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610e2157600080fd5b6001546040516001600160a01b038084169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b0316151590565b600a546001600160a01b031681565b6001546001600160a01b0316610eb257600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610eeb573d6000803e3d6000fd5b50565b6001600160a01b038216610f0157600080fd5b60408051808201825260168082527529b2ba10333ab73239903232b9ba34b730ba34b7b71d60511b6020808401918252600380546001810190915594513095600095610f5e958995919489948c9493910191829190808383610c66565b600a549091506001600160a01b03808316911614610fad5760405162461bcd60e51b815260040180806020018281038252602d815260200180612286602d913960400191505060405180910390fd5b6001546040516001600160a01b038087169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a35050600180546001600160a01b0319166001600160a01b03939093169290921790915550565b604080516020808201859052825180830382018152918301909252805191012030600061108a8461103c611e7e565b604080516020808201939093526001600160a01b03871681830152606081018c9052608081018b905260a08082018990528251808303909101815260c0909101909152805191012090611c93565b600a549091506001600160a01b038083169116146110d95760405162461bcd60e51b81526004018080602001828103825260258152602001806122d76025913960400191505060405180910390fd5b6009546000906110ea908990611e82565b90506000811161112b5760405162461bcd60e51b815260040180806020018281038252603781526020018061224f6037913960400191505060405180910390fd5b600254604080516370a0823160e01b81526001600160a01b038681166004830152915160009392909216916370a0823191602480820192602092909190829003018186803b15801561117c57600080fd5b505afa158015611190573d6000803e3d6000fd5b505050506040513d60208110156111a657600080fd5b50519050808211156111b6578091505b6009546111c39083611ecb565b6009556002546008546001600160a01b039182169163a9059cbb91166111e9858c611e82565b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561122f57600080fd5b505af1158015611243573d6000803e3d6000fd5b505050506040513d602081101561125957600080fd5b505087156112e2576002546040805163a9059cbb60e01b8152336004820152602481018b905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156112b557600080fd5b505af11580156112c9573d6000803e3d6000fd5b505050506040513d60208110156112df57600080fd5b50505b600854600954604080516001600160a01b0390931683526020830185905282810191909152517f50c3491624aa1825a7653df63d067fecd5c8634ba63c99c4a7cf04ff1436070b9181900360600190a1505050505050505050565b6000546001600160a01b031690565b6007546008546009546001600160a01b03928316929091169083565b6001546001600160a01b031661137d57600080fd5b6002546001600160a01b03828116911614156113ca5760405162461bcd60e51b81526004018080602001828103825260258152602001806120f56025913960400191505060405180910390fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561141957600080fd5b505afa15801561142d573d6000803e3d6000fd5b505050506040513d602081101561144357600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561149e57600080fd5b505af11580156114b2573d6000803e3d6000fd5b505050506040513d60208110156114c857600080fd5b50505050565b4383101561150d5760405162461bcd60e51b815260040180806020018281038252604d815260200180611fff604d913960600191505060405180910390fd5b60408051808201909152600d81526c22bc34ba103932b8bab2b9ba1d60991b6020820152309060009061153e611e7e565b836001600160a01b03168a8a8a6001600160a01b03168a60036000815480929190600101919050556040516020018089805190602001908083835b602083106115985780518252601f199092019160209182019101611579565b51815160209384036101000a60001901801990921691161790529201998a525088810197909752506040808801959095526060870193909352608086019190915260a085015260c0808501919091528151808503909101815260e09093019052815191012091506000905061160d8286611c93565b600a549091506001600160a01b0380831691161461165c5760405162461bcd60e51b81526004018080602001828103825260268152602001806121ff6026913960400191505060405180910390fd5b60006116688386611c93565b6007549091506001600160a01b038083169116146116b75760405162461bcd60e51b81526004018080602001828103825260248152602001806122b36024913960400191505060405180910390fd5b881561177d57888a10156116fc5760405162461bcd60e51b815260040180806020018281038252603e8152602001806121c1603e913960400191505060405180910390fd5b6002546040805163a9059cbb60e01b8152336004820152602481018c905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561175057600080fd5b505af1158015611764573d6000803e3d6000fd5b505050506040513d602081101561177a57600080fd5b50505b60006117898b8b611e82565b6002546040805163a9059cbb60e01b81526001600160a01b038d8116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b1580156117e157600080fd5b505af11580156117f5573d6000803e3d6000fd5b505050506040513d602081101561180b57600080fd5b5050604080516001600160a01b038b1681526020810183905281517f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364929181900390910190a15050505050505050505050565b6000546001600160a01b031633148061188057506000546001600160a01b0316155b6118d1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166119165760405162461bcd60e51b81526004018080602001828103825260268152602001806120cf6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6004546005546001600160a01b031682565b6001546001600160a01b031690565b61199a610e7d565b156119e5576040805162461bcd60e51b8152602060048201526016602482015275125cc8185b1c9958591e481a5b9a5d1a585b1a5e995960521b604482015290519081900360640190fd5b6001600160a01b038316611a39576040805162461bcd60e51b81526020600482015260166024820152754964656e746974792063616e2774206265207a65726f60501b604482015290519081900360640190fd5b6001600160a01b038216611a8d576040805162461bcd60e51b81526020600482015260166024820152754865726d657349442063616e2774206265207a65726f60501b604482015290519081900360640190fd5b6001600160a01b038516611ad25760405162461bcd60e51b81526004018080602001828103825260288152602001806121776028913960400191505060405180910390fd5b600280546001600160a01b038088166001600160a01b031992831617909255600b8054928716929091169190911790558015611b89576002546040805163a9059cbb60e01b81523360048201526024810184905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b158015611b5c57600080fd5b505af1158015611b70573d6000803e3d6000fd5b505050506040513d6020811015611b8657600080fd5b50505b600a80546001600160a01b0319166001600160a01b038581169190911791829055611bb4911661185e565b6040518060600160405280836001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b158015611bf857600080fd5b505afa158015611c0c573d6000803e3d6000fd5b505050506040513d6020811015611c2257600080fd5b50516001600160a01b03908116825293841660208281019190915260006040928301528251600780549187166001600160a01b03199283161790559083015160088054919096169116179093559091015160095550505050565b6002546001600160a01b031681565b436146500190565b60008151604114611ceb576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611d5c5760405162461bcd60e51b815260040180806020018281038252602281526020018061211a6022913960400191505060405180910390fd5b8060ff16601b14158015611d7457508060ff16601c14155b15611db05760405162461bcd60e51b815260040180806020018281038252602281526020018061219f6022913960400191505060405180910390fd5b600060018783868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611e0c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611e74576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9695505050505050565b4690565b6000611ec483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611f25565b9392505050565b600082820183811015611ec4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008184841115611fb45760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f79578181015183820152602001611f61565b50505050905090810190601f168015611fa65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50505090039056fe4368616e6e656c3a2065786974206861766520746f2062652072657175657374656420616e642074696d656c6f636b206861766520746f20626520696e20706173744368616e6e656c3a205f76616c6964556e74696c206861766520746f2062652067726561746572207468616e206f7220657175616c20746f2063757272656e7420626c6f636b206e756d6265724368616e6e656c3a206e657720657869742063616e20626520726571756573746564206f6e6c79207768656e206f6c64206f6e65207761732066696e616c697365644368616e6e656c3a2076616c696420756e74696c206861766520746f2062652067726561746572207468616e2063757272656e7420626c6f636b206e756d6265724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573736e617469766520746f6b656e2066756e64732063616e2774206265207265636f766572656445434453413a20696e76616c6964207369676e6174757265202773272076616c75654368616e6e656c3a2072657175657374206861766520746f2062652076616c69642073686f72746572207468616e2044454c41595f424c4f434b53546f6b656e2063616e2774206265206465706c6f796420696e746f207a65726f206164647265737345434453413a20696e76616c6964207369676e6174757265202776272076616c75654368616e6e656c3a207472616e736163746f72206665652063616e2774206265206269676765722074686174207769746864726177616c20616d6f756e744368616e6e656c3a206861766520746f206265207369676e6564206279206f70657261746f724368616e6e656c3a2062656e65666963696172792063616e2774206265207a65726f2061646472657373616d6f756e7420746f20736574746c652073686f756c642062652067726561746572207468617420616c726561647920736574746c65644368616e6e656c3a206861766520746f206265207369676e65642062792070726f706572206964656e746974794368616e6e656c3a206861766520746f206265207369676e6564206279206865726d65736861766520746f206265207369676e6564206279206368616e6e656c206f70657261746f72a26469706673582212202771ceadbaf087d6400e07e5a5cdeec61d5c3a8235c01b7cfa747395e893e1b564736f6c63430007040033" +var ChannelImplementationBin = "0x608060405234801561001057600080fd5b506122c9806100206000396000f3fe6080604052600436106101025760003560e01c80638da5cb5b11610095578063f2fde38b11610064578063f2fde38b1461083c578063f4b3a1971461086f578063f58c5b6e146108a5578063f7013ef6146108ba578063fc0c546a1461090d57610355565b80638da5cb5b1461065e578063d8092c9214610673578063df8de3e7146106b2578063e9e8ad8b146106e557610355565b8063570ca735116100d1578063570ca735146104935780636931b550146104c45780636a2b76ad146104d95780636f1746301461059a57610355565b806307e8ec1f1461035a578063182f348814610371578063238e130a14610437578063392e53cd1461046a57610355565b36610355576040805160028082526060820183526000926020830190803683375050600a54604080516315ab88c960e31b815290519394506001600160a01b039091169263ad5c464892506004808301926020929190829003018186803b15801561016c57600080fd5b505afa158015610180573d6000803e3d6000fd5b505050506040513d602081101561019657600080fd5b5051815182906000906101a557fe5b6001600160a01b0392831660209182029290920101526002548251911690829060019081106101d057fe5b6001600160a01b03928316602091820292909201810191909152600a54604051637ff36ab560e01b8152600060048201818152306044840181905242606485018190526080602486019081528951608487015289519690981697637ff36ab597349795968b969495939460a49091019187810191028083838b5b8381101561026257818101518382015260200161024a565b50505050905001955050505050506000604051808303818588803b15801561028957600080fd5b505af115801561029d573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156102c757600080fd5b8101908080516040519392919084600160201b8211156102e657600080fd5b9083019060208201858111156102fb57600080fd5b82518660208202830111600160201b8211171561031757600080fd5b82525081516020918201928201910280838360005b8381101561034457818101518382015260200161032c565b505050509050016040525050505050005b600080fd5b34801561036657600080fd5b5061036f610922565b005b34801561037d57600080fd5b5061036f6004803603606081101561039457600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156103c357600080fd5b8201836020820111156103d557600080fd5b803590602001918460018302840111600160201b831117156103f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610ae2945050505050565b34801561044357600080fd5b5061036f6004803603602081101561045a57600080fd5b50356001600160a01b0316610d9c565b34801561047657600080fd5b5061047f610e7e565b604080519115158252519081900360200190f35b34801561049f57600080fd5b506104a8610e8f565b604080516001600160a01b039092168252519081900360200190f35b3480156104d057600080fd5b5061036f610e9e565b3480156104e557600080fd5b5061036f600480360360408110156104fc57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561052657600080fd5b82018360208201111561053857600080fd5b803590602001918460018302840111600160201b8311171561055957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610eef945050505050565b3480156105a657600080fd5b5061036f600480360360808110156105bd57600080fd5b81359160208101359160408201359190810190608081016060820135600160201b8111156105ea57600080fd5b8201836020820111156105fc57600080fd5b803590602001918460018302840111600160201b8311171561061d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061100e945050505050565b34801561066a57600080fd5b506104a861133e565b34801561067f57600080fd5b5061068861134d565b604080516001600160a01b0394851681529290931660208301528183015290519081900360600190f35b3480156106be57600080fd5b5061036f600480360360208110156106d557600080fd5b50356001600160a01b0316611369565b3480156106f157600080fd5b5061036f600480360360c081101561070857600080fd5b8135916020810135916001600160a01b036040830135169160608101359181019060a081016080820135600160201b81111561074357600080fd5b82018360208201111561075557600080fd5b803590602001918460018302840111600160201b8311171561077657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156107c857600080fd5b8201836020820111156107da57600080fd5b803590602001918460018302840111600160201b831117156107fb57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506114cf945050505050565b34801561084857600080fd5b5061036f6004803603602081101561085f57600080fd5b50356001600160a01b031661185f565b34801561087b57600080fd5b50610884611972565b604080519283526001600160a01b0390911660208301528051918290030190f35b3480156108b157600080fd5b506104a8611984565b3480156108c657600080fd5b5061036f600480360360a08110156108dd57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611993565b34801561091957600080fd5b506104a8611c7d565b6004541580159061093557506004544310155b6109705760405162461bcd60e51b8152600401808060200182810382526042815260200180611f556042913960600191505060405180910390fd5b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156109bb57600080fd5b505afa1580156109cf573d6000803e3d6000fd5b505050506040513d60208110156109e557600080fd5b50516002546005546040805163a9059cbb60e01b81526001600160a01b03928316600482015260248101859052905193945091169163a9059cbb916044808201926020929091908290030181600087803b158015610a4257600080fd5b505af1158015610a56573d6000803e3d6000fd5b505050506040513d6020811015610a6c57600080fd5b5050600554604080516001600160a01b0390921682526020820183905280517f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649281900390910190a1506040805180820190915260008082526020909101819052600455600580546001600160a01b0319169055565b6000610aec611c8c565b60045490915015610b2e5760405162461bcd60e51b8152600401808060200182810382526042815260200180611fe46042913960600191505060405180910390fd5b438311610b6c5760405162461bcd60e51b81526004018080602001828103825260418152602001806120266041913960600191505060405180910390fd5b828111610baa5760405162461bcd60e51b815260040180806020018281038252603b8152602001806120d4603b913960400191505060405180910390fd5b6001600160a01b038416610bef5760405162461bcd60e51b815260040180806020018281038252602a8152602001806121bd602a913960400191505060405180910390fd5b6009546001600160a01b03163314610d2f5760003090506000610cdd846040518060400160405280600d81526020016c22bc34ba103932b8bab2b9ba1d60991b8152508489896040516020018085805190602001908083835b60208310610c675780518252601f199092019160209182019101610c48565b6001836020036101000a038019825116818451168082178552505050505050905001846001600160a01b031660601b8152601401836001600160a01b031660601b815260140182815260200194505050505060405160208183030381529060405280519060200120611c9490919063ffffffff16565b6009549091506001600160a01b03808316911614610d2c5760405162461bcd60e51b81526004018080602001828103825260268152602001806121976026913960400191505060405180910390fd5b50505b6040805180820182528281526001600160a01b03861660209182018190526004849055600580546001600160a01b0319169091179055815183815291517fe60f0366d8d61555184ea027447889648bae94ebfb1202a39544b6b6803969db9281900390910190a150505050565b6000546001600160a01b0316331480610dbe57506000546001600160a01b0316155b610e0f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610e2257600080fd5b6001546040516001600160a01b038084169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6009546001600160a01b0316151590565b6009546001600160a01b031681565b6001546001600160a01b0316610eb357600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610eec573d6000803e3d6000fd5b50565b6001600160a01b038216610f0257600080fd5b60408051808201825260168082527529b2ba10333ab73239903232b9ba34b730ba34b7b71d60511b6020808401918252600380546001810190915594513095600095610f5f958995919489948c9493910191829190808383610c67565b6009549091506001600160a01b03808316911614610fae5760405162461bcd60e51b815260040180806020018281038252602d81526020018061221e602d913960400191505060405180910390fd5b6001546040516001600160a01b038087169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a35050600180546001600160a01b0319166001600160a01b03939093169290921790915550565b604080516020808201859052825180830382018152918301909252805191012030600061108b8461103d611d14565b604080516020808201939093526001600160a01b03871681830152606081018c9052608081018b905260a08082018990528251808303909101815260c0909101909152805191012090611c94565b6009549091506001600160a01b038083169116146110da5760405162461bcd60e51b815260040180806020018281038252602581526020018061226f6025913960400191505060405180910390fd5b6008546000906110eb908990611d18565b90506000811161112c5760405162461bcd60e51b81526004018080602001828103825260378152602001806121e76037913960400191505060405180910390fd5b600254604080516370a0823160e01b81526001600160a01b038681166004830152915160009392909216916370a0823191602480820192602092909190829003018186803b15801561117d57600080fd5b505afa158015611191573d6000803e3d6000fd5b505050506040513d60208110156111a757600080fd5b50519050808211156111b7578091505b6008546111c49083611d75565b6008556002546007546001600160a01b039182169163a9059cbb91166111ea858c611d18565b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561123057600080fd5b505af1158015611244573d6000803e3d6000fd5b505050506040513d602081101561125a57600080fd5b505087156112e3576002546040805163a9059cbb60e01b8152336004820152602481018b905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156112b657600080fd5b505af11580156112ca573d6000803e3d6000fd5b505050506040513d60208110156112e057600080fd5b50505b600754600854604080516001600160a01b0390931683526020830185905282810191909152517f50c3491624aa1825a7653df63d067fecd5c8634ba63c99c4a7cf04ff1436070b9181900360600190a1505050505050505050565b6000546001600160a01b031690565b6006546007546008546001600160a01b03928316929091169083565b6001546001600160a01b031661137e57600080fd5b6002546001600160a01b03828116911614156113cb5760405162461bcd60e51b815260040180806020018281038252602581526020018061208d6025913960400191505060405180910390fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561141a57600080fd5b505afa15801561142e573d6000803e3d6000fd5b505050506040513d602081101561144457600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561149f57600080fd5b505af11580156114b3573d6000803e3d6000fd5b505050506040513d60208110156114c957600080fd5b50505050565b4383101561150e5760405162461bcd60e51b815260040180806020018281038252604d815260200180611f97604d913960600191505060405180910390fd5b60408051808201909152600d81526c22bc34ba103932b8bab2b9ba1d60991b6020820152309060009061153f611d14565b836001600160a01b03168a8a8a6001600160a01b03168a60036000815480929190600101919050556040516020018089805190602001908083835b602083106115995780518252601f19909201916020918201910161157a565b51815160209384036101000a60001901801990921691161790529201998a525088810197909752506040808801959095526060870193909352608086019190915260a085015260c0808501919091528151808503909101815260e09093019052815191012091506000905061160e8286611c94565b6009549091506001600160a01b0380831691161461165d5760405162461bcd60e51b81526004018080602001828103825260268152602001806121976026913960400191505060405180910390fd5b60006116698386611c94565b6006549091506001600160a01b038083169116146116b85760405162461bcd60e51b815260040180806020018281038252602481526020018061224b6024913960400191505060405180910390fd5b881561177e57888a10156116fd5760405162461bcd60e51b815260040180806020018281038252603e815260200180612159603e913960400191505060405180910390fd5b6002546040805163a9059cbb60e01b8152336004820152602481018c905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561175157600080fd5b505af1158015611765573d6000803e3d6000fd5b505050506040513d602081101561177b57600080fd5b50505b600061178a8b8b611d18565b6002546040805163a9059cbb60e01b81526001600160a01b038d8116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b1580156117e257600080fd5b505af11580156117f6573d6000803e3d6000fd5b505050506040513d602081101561180c57600080fd5b5050604080516001600160a01b038b1681526020810183905281517f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364929181900390910190a15050505050505050505050565b6000546001600160a01b031633148061188157506000546001600160a01b0316155b6118d2576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166119175760405162461bcd60e51b81526004018080602001828103825260268152602001806120676026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6004546005546001600160a01b031682565b6001546001600160a01b031690565b61199b610e7e565b156119e6576040805162461bcd60e51b8152602060048201526016602482015275125cc8185b1c9958591e481a5b9a5d1a585b1a5e995960521b604482015290519081900360640190fd5b6001600160a01b038316611a3a576040805162461bcd60e51b81526020600482015260166024820152754964656e746974792063616e2774206265207a65726f60501b604482015290519081900360640190fd5b6001600160a01b038216611a8e576040805162461bcd60e51b81526020600482015260166024820152754865726d657349442063616e2774206265207a65726f60501b604482015290519081900360640190fd5b6001600160a01b038516611ad35760405162461bcd60e51b815260040180806020018281038252602881526020018061210f6028913960400191505060405180910390fd5b600280546001600160a01b038088166001600160a01b031992831617909255600a8054928716929091169190911790558015611b8a576002546040805163a9059cbb60e01b81523360048201526024810184905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b158015611b5d57600080fd5b505af1158015611b71573d6000803e3d6000fd5b505050506040513d6020811015611b8757600080fd5b50505b600980546001600160a01b0319166001600160a01b038581169190911791829055611bb5911661185f565b6040518060600160405280836001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b158015611bf957600080fd5b505afa158015611c0d573d6000803e3d6000fd5b505050506040513d6020811015611c2357600080fd5b50516001600160a01b03908116825293841660208281019190915260006040928301528251600680549187166001600160a01b03199283161790559083015160078054919096169116179093559091015160085550505050565b6002546001600160a01b031681565b436146500190565b60008151604114611cec576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a611d0a86828585611dd6565b9695505050505050565b4690565b600082821115611d6f576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082820183811015611dcf576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611e375760405162461bcd60e51b81526004018080602001828103825260228152602001806120b26022913960400191505060405180910390fd5b8360ff16601b1480611e4c57508360ff16601c145b611e875760405162461bcd60e51b81526004018080602001828103825260228152602001806121376022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611ee3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611f4b576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9594505050505056fe4368616e6e656c3a2065786974206861766520746f2062652072657175657374656420616e642074696d656c6f636b206861766520746f20626520696e20706173744368616e6e656c3a205f76616c6964556e74696c206861766520746f2062652067726561746572207468616e206f7220657175616c20746f2063757272656e7420626c6f636b206e756d6265724368616e6e656c3a206e657720657869742063616e20626520726571756573746564206f6e6c79207768656e206f6c64206f6e65207761732066696e616c697365644368616e6e656c3a2076616c696420756e74696c206861766520746f2062652067726561746572207468616e2063757272656e7420626c6f636b206e756d6265724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573736e617469766520746f6b656e2066756e64732063616e2774206265207265636f766572656445434453413a20696e76616c6964207369676e6174757265202773272076616c75654368616e6e656c3a2072657175657374206861766520746f2062652076616c69642073686f72746572207468616e2044454c41595f424c4f434b53546f6b656e2063616e2774206265206465706c6f796420696e746f207a65726f206164647265737345434453413a20696e76616c6964207369676e6174757265202776272076616c75654368616e6e656c3a207472616e736163746f72206665652063616e2774206265206269676765722074686174207769746864726177616c20616d6f756e744368616e6e656c3a206861766520746f206265207369676e6564206279206f70657261746f724368616e6e656c3a2062656e65666963696172792063616e2774206265207a65726f2061646472657373616d6f756e7420746f20736574746c652073686f756c642062652067726561746572207468617420616c726561647920736574746c65644368616e6e656c3a206861766520746f206265207369676e65642062792070726f706572206964656e746974794368616e6e656c3a206861766520746f206265207369676e6564206279206865726d65736861766520746f206265207369676e6564206279206368616e6e656c206f70657261746f72a264697066735822122034614d941533b39a22389a76767515034e9f6d152600cf2226dff56ae10b1f8664736f6c63430007060033" // DeployChannelImplementation deploys a new Ethereum contract, binding an instance of ChannelImplementation to it. func DeployChannelImplementation(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ChannelImplementation, error) { @@ -496,23 +496,23 @@ func (_ChannelImplementation *ChannelImplementationTransactorSession) FinalizeEx // Initialize is a paid mutator transaction binding the contract method 0xf7013ef6. // -// Solidity: function initialize(address _token, address _dexAddress, address _identityHash, address _hermesId, uint256 _fee) returns() -func (_ChannelImplementation *ChannelImplementationTransactor) Initialize(opts *bind.TransactOpts, _token common.Address, _dexAddress common.Address, _identityHash common.Address, _hermesId common.Address, _fee *big.Int) (*types.Transaction, error) { - return _ChannelImplementation.contract.Transact(opts, "initialize", _token, _dexAddress, _identityHash, _hermesId, _fee) +// Solidity: function initialize(address _token, address _dexAddress, address _identity, address _hermesId, uint256 _fee) returns() +func (_ChannelImplementation *ChannelImplementationTransactor) Initialize(opts *bind.TransactOpts, _token common.Address, _dexAddress common.Address, _identity common.Address, _hermesId common.Address, _fee *big.Int) (*types.Transaction, error) { + return _ChannelImplementation.contract.Transact(opts, "initialize", _token, _dexAddress, _identity, _hermesId, _fee) } // Initialize is a paid mutator transaction binding the contract method 0xf7013ef6. // -// Solidity: function initialize(address _token, address _dexAddress, address _identityHash, address _hermesId, uint256 _fee) returns() -func (_ChannelImplementation *ChannelImplementationSession) Initialize(_token common.Address, _dexAddress common.Address, _identityHash common.Address, _hermesId common.Address, _fee *big.Int) (*types.Transaction, error) { - return _ChannelImplementation.Contract.Initialize(&_ChannelImplementation.TransactOpts, _token, _dexAddress, _identityHash, _hermesId, _fee) +// Solidity: function initialize(address _token, address _dexAddress, address _identity, address _hermesId, uint256 _fee) returns() +func (_ChannelImplementation *ChannelImplementationSession) Initialize(_token common.Address, _dexAddress common.Address, _identity common.Address, _hermesId common.Address, _fee *big.Int) (*types.Transaction, error) { + return _ChannelImplementation.Contract.Initialize(&_ChannelImplementation.TransactOpts, _token, _dexAddress, _identity, _hermesId, _fee) } // Initialize is a paid mutator transaction binding the contract method 0xf7013ef6. // -// Solidity: function initialize(address _token, address _dexAddress, address _identityHash, address _hermesId, uint256 _fee) returns() -func (_ChannelImplementation *ChannelImplementationTransactorSession) Initialize(_token common.Address, _dexAddress common.Address, _identityHash common.Address, _hermesId common.Address, _fee *big.Int) (*types.Transaction, error) { - return _ChannelImplementation.Contract.Initialize(&_ChannelImplementation.TransactOpts, _token, _dexAddress, _identityHash, _hermesId, _fee) +// Solidity: function initialize(address _token, address _dexAddress, address _identity, address _hermesId, uint256 _fee) returns() +func (_ChannelImplementation *ChannelImplementationTransactorSession) Initialize(_token common.Address, _dexAddress common.Address, _identity common.Address, _hermesId common.Address, _fee *big.Int) (*types.Transaction, error) { + return _ChannelImplementation.Contract.Initialize(&_ChannelImplementation.TransactOpts, _token, _dexAddress, _identity, _hermesId, _fee) } // RequestExit is a paid mutator transaction binding the contract method 0x182f3488. diff --git a/bindings/HermesImplementation.go b/bindings/HermesImplementation.go index 5e26bdd..a7e31a1 100644 --- a/bindings/HermesImplementation.go +++ b/bindings/HermesImplementation.go @@ -1,6 +1,6 @@ /* Mysterium network payment library. * - * Copyright (C) 2020 BlockDev AG + * Copyright (C) 2021 BlockDev AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -43,10 +43,10 @@ var ( ) // HermesImplementationABI is the input ABI used to generate the binding from. -const HermesImplementationABI = "[{\"anonymous\":false,\"inputs\":[],\"name\":\"ChannelOpeningActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ChannelOpeningPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"DestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"FundsWithdrawned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"HermesClosed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newFee\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"validFromBlock\",\"type\":\"uint64\"}],\"name\":\"HermesFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"activationBlock\",\"type\":\"uint256\"}],\"name\":\"HermesPunishmentActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"HermesPunishmentDeactivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newStake\",\"type\":\"uint256\"}],\"name\":\"HermesStakeIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxStake\",\"type\":\"uint256\"}],\"name\":\"MaxStakeValueUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinStake\",\"type\":\"uint256\"}],\"name\":\"MinStakeValueUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"channelId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"stakeAmount\",\"type\":\"uint256\"}],\"name\":\"NewStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"channelId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountSentToBeneficiary\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"}],\"name\":\"PromiseSettled\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"channels\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"settled\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lastUsedNonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timelock\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimEthers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastFee\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"value\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"validFrom\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousFee\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"value\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"validFrom\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"punishment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"activationBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIERC20Token\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"}],\"name\":\"getChannelId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getActiveFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHermesStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStakeThresholds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enumHermesImplementation.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fee\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"_minStake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxStake\",\"type\":\"uint256\"},{\"internalType\":\"addresspayable\",\"name\":\"_dexAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amountToStake\",\"type\":\"uint256\"}],\"name\":\"openChannel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settlePromise\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_promiseSignature\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_beneficiarySignature\",\"type\":\"bytes\"}],\"name\":\"settleWithBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settleWithDEX\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_channelId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"increaseStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settleIntoStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"decreaseStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolveEmergency\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newMinStake\",\"type\":\"uint256\"}],\"name\":\"setMinStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newMaxStake\",\"type\":\"uint256\"}],\"name\":\"setMaxStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_newFee\",\"type\":\"uint16\"}],\"name\":\"setHermesFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_additionalStake\",\"type\":\"uint256\"}],\"name\":\"increaseHermesStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_channelId\",\"type\":\"bytes32\"}],\"name\":\"isChannelOpened\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isHermesActive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseChannelOpening\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"activateChannelOpening\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeHermes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"}],\"name\":\"getStakeBack\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"calculateHermesFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimalExpectedBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_channelId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"validatePromise\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" +const HermesImplementationABI = "[{\"anonymous\":false,\"inputs\":[],\"name\":\"ChannelOpeningActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ChannelOpeningPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"DestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"FundsWithdrawned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"HermesClosed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newFee\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"validFromBlock\",\"type\":\"uint64\"}],\"name\":\"HermesFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"activationBlock\",\"type\":\"uint256\"}],\"name\":\"HermesPunishmentActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"HermesPunishmentDeactivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newStake\",\"type\":\"uint256\"}],\"name\":\"HermesStakeIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMaxStake\",\"type\":\"uint256\"}],\"name\":\"MaxStakeValueUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinStake\",\"type\":\"uint256\"}],\"name\":\"MinStakeValueUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"channelId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"stakeAmount\",\"type\":\"uint256\"}],\"name\":\"NewStake\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"channelId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountSentToBeneficiary\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"}],\"name\":\"PromiseSettled\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"channels\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"settled\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lastUsedNonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timelock\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimEthers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastFee\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"value\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"validFrom\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousFee\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"value\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"validFrom\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"punishment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"activationBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIERC20Token\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_type\",\"type\":\"string\"}],\"name\":\"getChannelId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"}],\"name\":\"getChannelId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getActiveFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHermesStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStakeThresholds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enumHermesImplementation.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_fee\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"_minStake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxStake\",\"type\":\"uint256\"},{\"internalType\":\"addresspayable\",\"name\":\"_dexAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amountToStake\",\"type\":\"uint256\"}],\"name\":\"openChannel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settlePromise\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_beneficiarySignature\",\"type\":\"bytes\"}],\"name\":\"payAndSettle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_promiseSignature\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_beneficiarySignature\",\"type\":\"bytes\"}],\"name\":\"settleWithBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settleWithDEX\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_channelId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"increaseStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"settleIntoStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"decreaseStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolveEmergency\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newMinStake\",\"type\":\"uint256\"}],\"name\":\"setMinStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newMaxStake\",\"type\":\"uint256\"}],\"name\":\"setMaxStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_newFee\",\"type\":\"uint16\"}],\"name\":\"setHermesFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_additionalStake\",\"type\":\"uint256\"}],\"name\":\"increaseHermesStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_channelId\",\"type\":\"bytes32\"}],\"name\":\"isChannelOpened\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isHermesActive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseChannelOpening\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"activateChannelOpening\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeHermes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"}],\"name\":\"getStakeBack\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"calculateHermesFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimalExpectedBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_channelId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_preimage\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"validatePromise\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" // HermesImplementationBin is the compiled bytecode used for deploying new contracts. -var HermesImplementationBin = "0x608060405234801561001057600080fd5b50613d43806100206000396000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c80637295973a11610151578063bc96a1e9116100c3578063eb295b2711610087578063eb295b2714610acb578063f2fde38b14610af1578063f3fef3a314610b17578063f58c5b6e14610b43578063fbb46b9814610b4b578063fc0c546a14610b5357610269565b8063bc96a1e914610a85578063df8de3e714610a8d578063e1c6648714610ab3578063e58473f214610abb578063e7f43c6814610ac357610269565b806394c7915d1161011557806394c7915d14610a195780639801134e14610a215780639ed9903e14610a50578063aa606dee14610a58578063ab2f0e5114610a60578063ae10ed8414610a6857610269565b80637295973a146108e95780637a7ebd7b146109a95780638c80fd90146109ec5780638d886fac14610a095780638da5cb5b14610a1157610269565b806348d9f01e116101ea5780636931b550116101ae5780636931b550146106da578063699a0885146106e25780636e9094ea1461072e5780636fc148371461074b57806370603a7f1461076857806371d2ff1b1461082457610269565b806348d9f01e146104475780634e69d5601461050c57806353d2a0ff146105355780635ab1bd53146106905780636138dda7146106b457610269565b806324f453d11161023157806324f453d1146103b3578063306db49b146103df57806338df1024146103e7578063392e53cd1461040857806339f976261461042457610269565b806302062d121461026e5780630684cd201461033557806315c73afd146103565780631f4f12c61461035e578063238e130a1461038d575b600080fd5b610333600480360360a081101561028457600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156102bf57600080fd5b8201836020820111156102d157600080fd5b803590602001918460018302840111600160201b831117156102f257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610b5b945050505050565b005b61033d610ec1565b6040805192835260208301919091528051918290030190f35b610333610eca565b61037b6004803603602081101561037457600080fd5b503561111b565b60408051918252519081900360200190f35b610333600480360360208110156103a357600080fd5b50356001600160a01b031661114b565b610333600480360360408110156103c957600080fd5b506001600160a01b038135169060200135611203565b61037b6112b5565b610333600480360360208110156103fd57600080fd5b503561ffff166112bc565b6104106114b7565b604080519115158252519081900360200190f35b6103336004803603604081101561043a57600080fd5b50803590602001356114c8565b610333600480360360a081101561045d57600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b81111561049857600080fd5b8201836020820111156104aa57600080fd5b803590602001918460018302840111600160201b831117156104cb57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061153c945050505050565b6105146116ab565b6040518082600381111561052457fe5b815260200191505060405180910390f35b610333600480360360e081101561054b57600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b81111561058657600080fd5b82018360208201111561059857600080fd5b803590602001918460018302840111600160201b831117156105b957600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561061c57600080fd5b82018360208201111561062e57600080fd5b803590602001918460018302840111600160201b8311171561064f57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506116bb945050505050565b610698611847565b604080516001600160a01b039092168252519081900360200190f35b610333600480360360208110156106ca57600080fd5b50356001600160a01b0316611856565b610333611a57565b610333600480360360c08110156106f857600080fd5b506001600160a01b038135811691602081013582169161ffff6040830135169160608101359160808201359160a0013516611aa8565b6104106004803603602081101561074457600080fd5b5035611db0565b6103336004803603602081101561076157600080fd5b5035611de2565b610410600480360360a081101561077e57600080fd5b81359160208101359160408201359160608101359181019060a081016080820135600160201b8111156107b057600080fd5b8201836020820111156107c257600080fd5b803590602001918460018302840111600160201b831117156107e357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611efa945050505050565b610333600480360360a081101561083a57600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b81111561087557600080fd5b82018360208201111561088757600080fd5b803590602001918460018302840111600160201b831117156108a857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611f8d945050505050565b610333600480360360808110156108ff57600080fd5b6001600160a01b038235169160208101359160408201359190810190608081016060820135600160201b81111561093557600080fd5b82018360208201111561094757600080fd5b803590602001918460018302840111600160201b8311171561096857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fc1945050505050565b6109c6600480360360208110156109bf57600080fd5b50356123ee565b604080519485526020850193909352838301919091526060830152519081900360800190f35b61033360048036036020811015610a0257600080fd5b5035612415565b61037b61252d565b61069861258f565b61037b61259e565b610a296125bc565b6040805161ffff909316835267ffffffffffffffff90911660208301528051918290030190f35b61033d6125d8565b6103336125e2565b61037b6126ba565b61033360048036036020811015610a7e57600080fd5b5035612768565b6104106128a6565b61033360048036036020811015610aa357600080fd5b50356001600160a01b03166128e1565b610a29612a17565b610333612a33565b610698612b28565b61037b60048036036020811015610ae157600080fd5b50356001600160a01b0316612b37565b61033360048036036020811015610b0757600080fd5b50356001600160a01b0316612b7b565b61033360048036036040811015610b2d57600080fd5b506001600160a01b038135169060200135612c8e565b610698612e3f565b610333612e4e565b610698612f20565b6003546040805163505a1b3160e01b81526001600160a01b0388811660048301529151600093929092169163505a1b3191602480820192602092909190829003018186803b158015610bac57600080fd5b505afa158015610bc0573d6000803e3d6000fd5b505050506040513d6020811015610bd657600080fd5b505190506001600160a01b038116610c1f5760405162461bcd60e51b8152600401808060200182810382526042815260200180613a786042913960600191505060405180910390fd5b6000610c2a87612b37565b90506000610c3c828489898989612f2f565b6040805160028082526060808301845293945060009392602083019080368337505060025482519293506001600160a01b031691839150600090610c7c57fe5b6001600160a01b03928316602091820292909201810191909152600a54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b158015610cd057600080fd5b505afa158015610ce4573d6000803e3d6000fd5b505050506040513d6020811015610cfa57600080fd5b5051815182906001908110610d0b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600a60009054906101000a90046001600160a01b03166001600160a01b03166318cbafe584848489426040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610dc4578181015183820152602001610dac565b505050509050019650505050505050600060405180830381600087803b158015610ded57600080fd5b505af1158015610e01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610e2a57600080fd5b8101908080516040519392919084600160201b821115610e4957600080fd5b908301906020820185811115610e5e57600080fd5b82518660208202830111600160201b82111715610e7a57600080fd5b82525081516020918201928201910280838360005b83811015610ea7578181015183820152602001610e8f565b505050509050016040525050505050505050505050505050565b600e54600f5482565b6002610ed46116ab565b6003811115610edf57fe5b14610f1b5760405162461bcd60e51b8152600401808060200182810382526026815260200180613c406026913960400191505060405180910390fd5b6000610f486064610f42610f3b60046005546131b890919063ffffffff16565b6064613218565b90613232565b90506000610f54613274565b600e5490915043036000610f7c600184610f6e8582613218565b81610f7557fe5b049061327a565b90506000610f8a82866131b8565b600f54909150610f9a90826132bc565b600f55600754600090610fb590610faf61259e565b906132bc565b600254604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561100657600080fd5b505afa15801561101a573d6000803e3d6000fd5b505050506040513d602081101561103057600080fd5b50519050818110156110dc576002546001600160a01b03166323b872dd3330611059868661327a565b6040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b1580156110af57600080fd5b505af11580156110c3573d6000803e3d6000fd5b505050506040513d60208110156110d957600080fd5b50505b600a805460ff60a01b191690556040517f5dc43dfad9aedde473e812a66ff033b91a2b1ee060e7dc0746a1a14a4a3bd47c90600090a150505050505050565b6000606461113d606461112c61252d565b85028161113557fe5b046064613218565b8161114457fe5b0492915050565b6004546001600160a01b031633146111945760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b6001600160a01b0381166111a757600080fd5b6001546040516001600160a01b038084169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461124c5760405162461bcd60e51b8152600401808060200182810382526027815260200180613c666027913960400191505060405180910390fd5b60006112566116ab565b600381111561126157fe5b1461129d5760405162461bcd60e51b8152600401808060200182810382526022815260200180613adb6022913960400191505060405180910390fd5b6112b16112a983612b37565b826000613316565b5050565b6008545b90565b6004546001600160a01b031633146113055760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b600361130f6116ab565b600381111561131a57fe5b141561136d576040805162461bcd60e51b815260206004820152601c60248201527f4865726d65733a2073686f756c64206265206e6f7420636c6f73656400000000604482015290519081900360640190fd5b6113888161ffff1611156113b25760405162461bcd60e51b815260040180806020018281038252602481526020018061380b6024913960400191505060405180910390fd5b600b5462010000900467ffffffffffffffff164310156114035760405162461bcd60e51b8152600401808060200182810382526021815260200180613aba6021913960400191505060405180910390fd5b600061140d6134d2565b600b8054600c805467ffffffffffffffff620100008085048216810269ffffffffffffffff00001961ffff1994851661ffff80891691909117821692909217909555604080518082018252918b1680835293891660209283018190529283029490961683179094169290921790945582519384529083015280519293507fea76eb91f1817e0757719ea43e0733faf6f1121425bde387d1dd91badb9d403b92918290030190a15050565b6004546001600160a01b0316151590565b60036114d26116ab565b60038111156114dd57fe5b1415611530576040805162461bcd60e51b815260206004820152601b60248201527f6865726d65732073686f756c64206265206e6f7420636c6f7365640000000000604482015290519081900360640190fd5b6112b182826000613316565b6003546040805163505a1b3160e01b81526001600160a01b0388811660048301529151600093929092169163505a1b3191602480820192602092909190829003018186803b15801561158d57600080fd5b505afa1580156115a1573d6000803e3d6000fd5b505050506040513d60208110156115b757600080fd5b505190506001600160a01b0381166116005760405162461bcd60e51b8152600401808060200182810382526042815260200180613a786042913960600191505060405180910390fd5b600061160b87612b37565b9050600061161d828489898989612f2f565b6002546040805163a9059cbb60e01b81526001600160a01b03878116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b15801561167557600080fd5b505af1158015611689573d6000803e3d6000fd5b505050506040513d602081101561169f57600080fd5b50505050505050505050565b600a54600160a01b900460ff1690565b60035460405163d0171d7960e01b81526001600160a01b03898116600483019081528582166024840152606060448401908152855160648501528551929094169363d0171d79938c938893889390929091608490910190602085019080838360005b8381101561173557818101518382015260200161171d565b50505050905090810190601f1680156117625780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561178357600080fd5b505af1158015611797573d6000803e3d6000fd5b5050505060006117a688612b37565b905060006117b882858a8a8a8a612f2f565b6002546040805163a9059cbb60e01b81526001600160a01b03888116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b15801561181057600080fd5b505af1158015611824573d6000803e3d6000fd5b505050506040513d602081101561183a57600080fd5b5050505050505050505050565b6003546001600160a01b031690565b6004546001600160a01b0316331461189f5760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b60036118a96116ab565b60038111156118b457fe5b14611906576040805162461bcd60e51b815260206004820152601860248201527f6865726d6573206861766520746f20626520636c6f7365640000000000000000604482015290519081900360640190fd5b60095443116119465760405162461bcd60e51b81526004018080602001828103825260268152602001806139db6026913960400191505060405180910390fd5b600f54600254604080516370a0823160e01b815230600482015290516000936119cf9390926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561199d57600080fd5b505afa1580156119b1573d6000803e3d6000fd5b505050506040513d60208110156119c757600080fd5b50519061327a565b6002546040805163a9059cbb60e01b81526001600160a01b03868116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b158015611a2757600080fd5b505af1158015611a3b573d6000803e3d6000fd5b505050506040513d6020811015611a5157600080fd5b50505050565b6001546001600160a01b0316611a6c57600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015611aa5573d6000803e3d6000fd5b50565b611ab06114b7565b15611aec5760405162461bcd60e51b81526004018080602001828103825260228152602001806138df6022913960400191505060405180910390fd5b6001600160a01b038616611b315760405162461bcd60e51b81526004018080602001828103825260308152602001806139016030913960400191505060405180910390fd5b6001600160a01b038516611b8c576040805162461bcd60e51b815260206004820152601f60248201527f4865726d65733a206f70657261746f72206861766520746f2062652073657400604482015290519081900360640190fd5b6113888461ffff161115611bd15760405162461bcd60e51b8152600401808060200182810382526024815260200180613c8d6024913960400191505060405180910390fd5b828211611c0f5760405162461bcd60e51b8152600401808060200182810382526030815260200180613a016030913960400191505060405180910390fd5b60038054336001600160a01b0319918216179091556002805482166001600160a01b0389811691909117918290556004805490931688821617835560408051808201825261ffff89168082524367ffffffffffffffff166020928301819052600b805461ffff191690921769ffffffffffffffff00001916620100009091021790556006889055600787905581516370a0823160e01b81523095810195909552905192909116926370a082319260248083019392829003018186803b158015611cd757600080fd5b505afa158015611ceb573d6000803e3d6000fd5b505050506040513d6020811015611d0157600080fd5b50516008556002546040805163095ea7b360e01b81526001600160a01b03848116600483015260001960248301529151919092169163095ea7b39160448083019260209291908290030181600087803b158015611d5d57600080fd5b505af1158015611d71573d6000803e3d6000fd5b505050506040513d6020811015611d8757600080fd5b5050600a80546001600160a01b0319166001600160a01b03929092169190911790555050505050565b6000818152600d6020526040812054151580611ddc57506000828152600d602052604090206001015415155b92915050565b6004546001600160a01b03163314611e2b5760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b611e336128a6565b611e7f576040805162461bcd60e51b81526020600482015260186024820152774865726d65733a2068617320746f2062652061637469766560401b604482015290519081900360640190fd5b6006548111611ebf5760405162461bcd60e51b815260040180806020018281038252602f8152602001806139ac602f913960400191505060405180910390fd5b60078190556040805182815290517f53f4fb18cb329155d5af04681c1d0846d0484d7de33791619c6988ca61910e3d9181900360200190a150565b604080516020808201859052825180830382018152918301909252805191012060009081611f7084611f2a6134da565b604080516020808201939093528082018d9052606081018c9052608081018b905260a08082018890528251808303909101815260c09091019091528051910120906134de565b6004546001600160a01b0390811691161498975050505050505050565b6000611f9886612b37565b90506000611faa823088888888612f2f565b9050611fb882826001613316565b50505050505050565b6000611fcc85612b37565b9050611fd781611db0565b612028576040805162461bcd60e51b815260206004820181905260248201527f4865726d65733a206368616e6e656c2068617320746f206265206f70656e6564604482015290519081900360640190fd5b828410156120675760405162461bcd60e51b815260040180806020018281038252603381526020018061382f6033913960400191505060405180910390fd5b6000818152600d6020526040902060018101548511156120b85760405162461bcd60e51b8152600401808060200182810382526032815260200180613afd6032913960400191505060405180910390fd5b600281018054600101905560408051808201909152601481527314dd185ad9481c995d1d5c9b881c995c5d595cdd60621b60208201526000906121a59085906120ff6134da565b868a8a88600201546040516020018087805190602001908083835b602083106121395780518252601f19909201916020918201910161211a565b6001836020036101000a0380198251168184511680821785525050505050509050018681526020018581526020018481526020018381526020018281526020019650505050505050604051602081830303815290604052805190602001206134de90919063ffffffff16565b9050826121b182612b37565b146121ed5760405162461bcd60e51b815260040180806020018281038252602a815260200180613ce4602a913960400191505060405180910390fd5b60018201546000906121ff908861327a565b90508515612288576002546040805163a9059cbb60e01b81523360048201526024810189905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561225b57600080fd5b505af115801561226f573d6000803e3d6000fd5b505050506040513d602081101561228557600080fd5b50505b6003546040805163505a1b3160e01b81526001600160a01b038b811660048301529151600093929092169163505a1b3191602480820192602092909190829003018186803b1580156122d957600080fd5b505afa1580156122ed573d6000803e3d6000fd5b505050506040513d602081101561230357600080fd5b50516002549091506001600160a01b031663a9059cbb826123248b8b61327a565b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561236a57600080fd5b505af115801561237e573d6000803e3d6000fd5b505050506040513d602081101561239457600080fd5b5050600184018290556005546123aa908961327a565b60055560408051838152905186917fc5f0715c45dab2e8f14871936119e3c64fd5841d397130c2d1db743d142522cb919081900360200190a2505050505050505050565b600d6020526000908152604090208054600182015460028301546003909301549192909184565b6004546001600160a01b0316331461245e5760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b6124666128a6565b6124b2576040805162461bcd60e51b81526020600482015260186024820152774865726d65733a2068617320746f2062652061637469766560401b604482015290519081900360640190fd5b60075481106124f25760405162461bcd60e51b81526004018080602001828103825260308152602001806139536030913960400191505060405180910390fd5b60068190556040805182815290517fb9e5e6e8db1283ee860f3856d8383e40665c58a5264ede5e6ed8ec1afb0312519181900360200190a150565b60006125376137f3565b600b5462010000900467ffffffffffffffff1643101561255857600c61255b565b600b5b60408051808201909152905461ffff81168083526201000090910467ffffffffffffffff1660209092019190915292915050565b6000546001600160a01b031690565b60006125b7600554610faf600854600e600101546136c9565b905090565b600b5461ffff81169062010000900467ffffffffffffffff1682565b6006546007549091565b6004546001600160a01b0316331461262b5760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b60006126356116ab565b600381111561264057fe5b1461267c5760405162461bcd60e51b8152600401808060200182810382526022815260200180613adb6022913960400191505060405180910390fd5b600a805460ff60a01b1916600160a01b1790556040517f1f4cd5d6edef8a0c4dbe6d547fdc42e0f3575167257553271f2366f9d497f67e90600090a1565b6000806126c561259e565b600254604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561271657600080fd5b505afa15801561272a573d6000803e3d6000fd5b505050506040513d602081101561274057600080fd5b5051905080821115612757576000925050506112b9565b612761818361327a565b9250505090565b6004546001600160a01b031633146127b15760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b806127ba6126ba565b101561285f5760006127d46127cd6126ba565b839061327a565b600254604080516323b872dd60e01b81523360048201523060248201526044810184905290519293506001600160a01b03909116916323b872dd916064808201926020929091908290030181600087803b15801561283157600080fd5b505af1158015612845573d6000803e3d6000fd5b505050506040513d602081101561285b57600080fd5b5050505b60085461286c90826132bc565b600881905560408051918252517feb10b8b69c3eb290299237eaee4760bf1c02734ce3dc7740d6f2017b5ca3ed919181900360200190a150565b6000806128b16116ab565b905060028160038111156128c157fe5b141580156128db575060038160038111156128d857fe5b14155b91505090565b6001546001600160a01b03166128f657600080fd5b6002546001600160a01b03828116911614156129435760405162461bcd60e51b81526004018080602001828103825260258152602001806138ba6025913960400191505060405180910390fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561299257600080fd5b505afa1580156129a6573d6000803e3d6000fd5b505050506040513d60208110156129bc57600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015611a2757600080fd5b600c5461ffff81169062010000900467ffffffffffffffff1682565b6004546001600160a01b03163314612a7c5760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b612a846128a6565b612ad5576040805162461bcd60e51b815260206004820152601760248201527f6865726d65732073686f756c6420626520616374697665000000000000000000604482015290519081900360640190fd5b600a805460ff60a01b1916600360a01b179055612af06136df565b6009556040805143815290517ffa9b0c2718819d67ceaec4f97d36185c2f1d22bdc5ff18f44c52cd56a5dd8e459181900360200190a1565b6004546001600160a01b031690565b60408051606092831b6bffffffffffffffffffffffff19166020808301919091523090931b6034820152815180820360280181526048909101909152805191012090565b6000546001600160a01b0316331480612b9d57506000546001600160a01b0316155b612bee576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c335760405162461bcd60e51b81526004018080602001828103825260268152602001806138626026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b03163314612cd75760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b612cdf6128a6565b612d30576040805162461bcd60e51b815260206004820152601960248201527f4865726d65733a206861766520746f2062652061637469766500000000000000604482015290519081900360640190fd5b80612d396126ba565b1015612d765760405162461bcd60e51b8152600401808060200182810382526034815260200180613b946034913960400191505060405180910390fd5b6002546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015612dcc57600080fd5b505af1158015612de0573d6000803e3d6000fd5b505050506040513d6020811015612df657600080fd5b5050604080518281526001600160a01b038416602082015281517fa2e147ce2b7cb83d9c07e397bb806f23dd42c42e86ea45e1611d6e50eb1ec8bf929181900390910190a15050565b6001546001600160a01b031690565b6004546001600160a01b03163314612e975760405162461bcd60e51b8152600401808060200182810382526033815260200180613cb16033913960400191505060405180910390fd5b6001612ea16116ab565b6003811115612eac57fe5b14612ee85760405162461bcd60e51b8152600401808060200182810382526021815260200180613b736021913960400191505060405180910390fd5b600a805460ff60a01b191690556040517f2d8b6ec230798e206d536342a28b7b61cc8fcfafb1d27c11c5519b3c42eb7df890600090a1565b6002546001600160a01b031681565b6000612f396128a6565b612f745760405162461bcd60e51b81526004018080602001828103825260298152602001806139836029913960400191505060405180910390fd5b612f818786868686611efa565b612fbc5760405162461bcd60e51b81526004018080602001828103825260328152602001806138886032913960400191505060405180910390fd5b6000878152600d6020526040812090612fd36126ba565b9050816001015481101561302d57600a805460ff60a01b1916600160a11b17905543600e81905560408051918252517f23dc47ee5d995fb521fbe4351f353f3177d7b9d9e15bdd01ed358764c25d96299181900360200190a15b815460009061303d90899061327a565b905086811161307d5760405162461bcd60e51b8152600401808060200182810382526034815260200180613c0c6034913960400191505060405180910390fd5b8181118061308c575060075481115b156130a05761309d826007546136e8565b90505b82546130ac90826132bc565b835560006130b98261111b565b905060006130c789836132bc565b90508815613150576002546040805163a9059cbb60e01b8152336004820152602481018c905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561312357600080fd5b505af1158015613137573d6000803e3d6000fd5b505050506040513d602081101561314d57600080fd5b50505b600061315c848361327a565b90508b6001600160a01b03168d7fa5a1f05785a942c5f624cee545c68394881a83bcaf21a83f4d76a9e8240a56688385604051808381526020018281526020019250505060405180910390a39c9b505050505050505050505050565b6000826131c757506000611ddc565b828202828482816131d457fe5b04146132115760405162461bcd60e51b8152600401808060200182810382526021815260200180613b2f6021913960400191505060405180910390fd5b9392505050565b600081826001848601038161322957fe5b04029392505050565b600061321183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506136f7565b61010190565b600061321183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613799565b600082820183811015613211576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082116133555760405162461bcd60e51b8152600401808060200182810382526023815260200180613b506023913960400191505060405180910390fd5b6000838152600d60205260408120600181015490919061337590856132bc565b90506007548111156133b85760405162461bcd60e51b8152600401808060200182810382526044815260200180613bc86044913960600191505060405180910390fd5b8261347e57600254604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561341757600080fd5b505af115801561342b573d6000803e3d6000fd5b505050506040513d602081101561344157600080fd5b505161347e5760405162461bcd60e51b8152600401808060200182810382526025815260200180613a536025913960400191505060405180910390fd5b6001820181905560055461349290856132bc565b60055560408051828152905186917fc5f0715c45dab2e8f14871936119e3c64fd5841d397130c2d1db743d142522cb919081900360200190a25050505050565b436146500190565b4690565b60008151604114613536576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156135a75760405162461bcd60e51b81526004018080602001828103825260228152602001806139316022913960400191505060405180910390fd5b8060ff16601b141580156135bf57508060ff16601c14155b156135fb5760405162461bcd60e51b8152600401808060200182810382526022815260200180613a316022913960400191505060405180910390fd5b600060018783868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613657573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136bf576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9695505050505050565b60008183116136d85781613211565b5090919050565b43621b77400190565b60008183106136d85781613211565b600081836137835760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613748578181015183820152602001613730565b50505050905090810190601f1680156137755780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161378f57fe5b0495945050505050565b600081848411156137eb5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613748578181015183820152602001613730565b505050900390565b60408051808201909152600080825260208201529056fe4865726d65733a206665652063616e2774206265206269676765722074686174203530254865726d65733a20616d6f756e742073686f756c6420626520626967676572207468616e207472616e736163746f72206665654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734865726d65733a206861766520746f2062652070726f7065726c79207369676e6564207061796d656e742070726f6d6973656e617469766520746f6b656e2066756e64732063616e2774206265207265636f76657265644865726d65733a206861766520746f206265206e6f7420696e697469616c697a65644865726d65733a20746f6b656e2063616e2774206265206465706c6f796420696e746f207a65726f206164647265737345434453413a20696e76616c6964207369676e6174757265202773272076616c75654865726d65733a206d696e5374616b652068617320746f20626520736d616c6c6572207468616e206d61785374616b654865726d65733a206865726d6573206861766520746f20626520696e206163746976652073746174654865726d65733a206d61785374616b652068617320746f20626520626967676572207468616e206d696e5374616b6574696d656c6f636b20706572696f64206861766520626520616c7265616479207061737365644865726d65733a206d61785374616b65206861766520746f20626520626967676572207468616e206d696e5374616b6545434453413a20696e76616c6964207369676e6174757265202776272076616c75654865726d65733a20746f6b656e207472616e736665722073686f756c6420737563636565644865726d65733a206964656e74697479206861766520746f20626520726567697374657265642c2062656e6566696369617279206861766520746f206265207365744865726d65733a2063616e27742075706461746520696e616374697665206665654865726d65733a206861766520746f20626520696e206163746976652073746174654865726d65733a2063616e2774207769746864726177206d6f7265207468616e207468652063757272656e74207374616b65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774865726d65733a2073686f756c64207374616b65206d6f7265207468616e207a65726f6865726d6573206861766520746f20626520696e207061757365642073746174654865726d65733a2073686f756c6420626520656e6f7567682066756e647320617661696c61626c6520746f2077697468647261774865726d65733a20746f74616c20616d6f756e7420746f207374616b652063616e277420626520626967676572207468616e206d6178696d616c6c7920616c6c6f7765644865726d65733a20616d6f756e7420746f20736574746c652073686f756c6420636f766572207472616e736163746f72206665654865726d65733a2073686f756c6420626520696e2070756e6973686d656e74207374617475734865726d65733a206f6e6c792072656769737472792063616e206f70656e206368616e6e656c734865726d65733a206665652063616e277420626520626967676572207468616e203530254865726d65733a206f6e6c79206865726d6573206f70657261746f722063616e2063616c6c20746869732066756e6374696f6e4865726d65733a206861766520746f206265207369676e6564206279206368616e6e656c207061727479a264697066735822122091316a3b137a7ad5828b0439a23cb9d6acaaa00fa8325c1e71912be89882c70d64736f6c63430007040033" +var HermesImplementationBin = "0x608060405234801561001057600080fd5b5061411b806100206000396000f3fe608060405234801561001057600080fd5b506004361061027f5760003560e01c80637295973a1161015c578063bc96a1e9116100ce578063eb295b2711610087578063eb295b2714610cf0578063f2fde38b14610d16578063f3fef3a314610d3c578063f58c5b6e14610d68578063fbb46b9814610d70578063fc0c546a14610d785761027f565b8063bc96a1e914610bf6578063df8de3e714610bfe578063e1791b2d14610c24578063e1c6648714610cd8578063e58473f214610ce0578063e7f43c6814610ce85761027f565b806394c7915d1161012057806394c7915d14610b8a5780639801134e14610b925780639ed9903e14610bc1578063aa606dee14610bc9578063ab2f0e5114610bd1578063ae10ed8414610bd95761027f565b80637295973a14610a5a5780637a7ebd7b14610b1a5780638c80fd9014610b5d5780638d886fac14610b7a5780638da5cb5b14610b825761027f565b80634e69d560116101f55780636931b550116101b95780636931b5501461084b578063699a0885146108535780636e9094ea1461089f5780636fc14837146108bc57806370603a7f146108d957806371d2ff1b146109955761027f565b80634e69d5601461052257806352a8e78d1461054b57806353d2a0ff146106a65780635ab1bd53146108015780636138dda7146108255761027f565b806324f453d11161024757806324f453d1146103c9578063306db49b146103f557806338df1024146103fd578063392e53cd1461041e57806339f976261461043a57806348d9f01e1461045d5761027f565b806302062d12146102845780630684cd201461034b57806315c73afd1461036c5780631f4f12c614610374578063238e130a146103a3575b600080fd5b610349600480360360a081101561029a57600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156102d557600080fd5b8201836020820111156102e757600080fd5b803590602001918460018302840111600160201b8311171561030857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610d80945050505050565b005b6103536110e8565b6040805192835260208301919091528051918290030190f35b6103496110f1565b6103916004803603602081101561038a57600080fd5b5035611342565b60408051918252519081900360200190f35b610349600480360360208110156103b957600080fd5b50356001600160a01b0316611372565b610349600480360360408110156103df57600080fd5b506001600160a01b03813516906020013561142a565b6103916114dc565b6103496004803603602081101561041357600080fd5b503561ffff166114e3565b6104266116de565b604080519115158252519081900360200190f35b6103496004803603604081101561045057600080fd5b50803590602001356116ef565b610349600480360360a081101561047357600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156104ae57600080fd5b8201836020820111156104c057600080fd5b803590602001918460018302840111600160201b831117156104e157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611763945050505050565b61052a6118d4565b6040518082600381111561053a57fe5b815260200191505060405180910390f35b610349600480360360e081101561056157600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b81111561059c57600080fd5b8201836020820111156105ae57600080fd5b803590602001918460018302840111600160201b831117156105cf57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561063257600080fd5b82018360208201111561064457600080fd5b803590602001918460018302840111600160201b8311171561066557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506118e4945050505050565b610349600480360360e08110156106bc57600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156106f757600080fd5b82018360208201111561070957600080fd5b803590602001918460018302840111600160201b8311171561072a57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561078d57600080fd5b82018360208201111561079f57600080fd5b803590602001918460018302840111600160201b831117156107c057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611a6c945050505050565b610809611bfa565b604080516001600160a01b039092168252519081900360200190f35b6103496004803603602081101561083b57600080fd5b50356001600160a01b0316611c09565b610349611e0a565b610349600480360360c081101561086957600080fd5b506001600160a01b038135811691602081013582169161ffff6040830135169160608101359160808201359160a0013516611e5b565b610426600480360360208110156108b557600080fd5b5035612168565b610349600480360360208110156108d257600080fd5b503561219a565b610426600480360360a08110156108ef57600080fd5b81359160208101359160408201359160608101359181019060a081016080820135600160201b81111561092157600080fd5b82018360208201111561093357600080fd5b803590602001918460018302840111600160201b8311171561095457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122b2945050505050565b610349600480360360a08110156109ab57600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156109e657600080fd5b8201836020820111156109f857600080fd5b803590602001918460018302840111600160201b83111715610a1957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612345945050505050565b61034960048036036080811015610a7057600080fd5b6001600160a01b038235169160208101359160408201359190810190608081016060820135600160201b811115610aa657600080fd5b820183602082011115610ab857600080fd5b803590602001918460018302840111600160201b83111715610ad957600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061237b945050505050565b610b3760048036036020811015610b3057600080fd5b50356127a8565b604080519485526020850193909352838301919091526060830152519081900360800190f35b61034960048036036020811015610b7357600080fd5b50356127cf565b6103916128e7565b610809612944565b610391612953565b610b9a612971565b6040805161ffff909316835267ffffffffffffffff90911660208301528051918290030190f35b61035361298d565b610349612997565b610391612a6f565b61034960048036036020811015610bef57600080fd5b5035612b1d565b610426612c5b565b61034960048036036020811015610c1457600080fd5b50356001600160a01b0316612c96565b61039160048036036040811015610c3a57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610c6457600080fd5b820183602082011115610c7657600080fd5b803590602001918460018302840111600160201b83111715610c9757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612dcc945050505050565b610b9a612e6c565b610349612e88565b610809612f7d565b61039160048036036020811015610d0657600080fd5b50356001600160a01b0316612f8c565b61034960048036036020811015610d2c57600080fd5b50356001600160a01b0316612fd0565b61034960048036036040811015610d5257600080fd5b506001600160a01b0381351690602001356130e3565b610809613294565b6103496132a3565b610809613375565b6003546040805163505a1b3160e01b81526001600160a01b0388811660048301529151600093929092169163505a1b3191602480820192602092909190829003018186803b158015610dd157600080fd5b505afa158015610de5573d6000803e3d6000fd5b505050506040513d6020811015610dfb57600080fd5b505190506001600160a01b038116610e445760405162461bcd60e51b8152600401808060200182810382526042815260200180613e506042913960600191505060405180910390fd5b6000610e4f87612f8c565b90506000610e638284898989896001613384565b6040805160028082526060820183529293506000928392602083019080368337505060025482519293506001600160a01b031691839150600090610ea357fe5b6001600160a01b03928316602091820292909201810191909152600a54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b158015610ef757600080fd5b505afa158015610f0b573d6000803e3d6000fd5b505050506040513d6020811015610f2157600080fd5b5051815182906001908110610f3257fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600a60009054906101000a90046001600160a01b03166001600160a01b03166318cbafe584848489426040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610feb578181015183820152602001610fd3565b505050509050019650505050505050600060405180830381600087803b15801561101457600080fd5b505af1158015611028573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561105157600080fd5b8101908080516040519392919084600160201b82111561107057600080fd5b90830190602082018581111561108557600080fd5b82518660208202830111600160201b821117156110a157600080fd5b82525081516020918201928201910280838360005b838110156110ce5781810151838201526020016110b6565b505050509050016040525050505050505050505050505050565b600e54600f5482565b60026110fb6118d4565b600381111561110657fe5b146111425760405162461bcd60e51b81526004018080602001828103825260268152602001806140186026913960400191505060405180910390fd5b600061116f6064611169611162600460055461361a90919063ffffffff16565b606461367a565b90613694565b9050600061117b6136fb565b600e54909150430360006111a3600184611195858261367a565b8161119c57fe5b0490613701565b905060006111b1828661361a565b600f549091506111c1908261375e565b600f556007546000906111dc906111d6612953565b9061375e565b600254604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561122d57600080fd5b505afa158015611241573d6000803e3d6000fd5b505050506040513d602081101561125757600080fd5b5051905081811015611303576002546001600160a01b03166323b872dd33306112808686613701565b6040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b1580156112d657600080fd5b505af11580156112ea573d6000803e3d6000fd5b505050506040513d602081101561130057600080fd5b50505b600a805460ff60a01b191690556040517f5dc43dfad9aedde473e812a66ff033b91a2b1ee060e7dc0746a1a14a4a3bd47c90600090a150505050505050565b6000606461136460646113536128e7565b85028161135c57fe5b04606461367a565b8161136b57fe5b0492915050565b6004546001600160a01b031633146113bb5760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b6001600160a01b0381166113ce57600080fd5b6001546040516001600160a01b038084169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146114735760405162461bcd60e51b815260040180806020018281038252602781526020018061403e6027913960400191505060405180910390fd5b600061147d6118d4565b600381111561148857fe5b146114c45760405162461bcd60e51b8152600401808060200182810382526022815260200180613eb36022913960400191505060405180910390fd5b6114d86114d083612f8c565b8260006137b8565b5050565b6008545b90565b6004546001600160a01b0316331461152c5760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b60036115366118d4565b600381111561154157fe5b1415611594576040805162461bcd60e51b815260206004820152601c60248201527f4865726d65733a2073686f756c64206265206e6f7420636c6f73656400000000604482015290519081900360640190fd5b6113888161ffff1611156115d95760405162461bcd60e51b8152600401808060200182810382526024815260200180613bad6024913960400191505060405180910390fd5b600b5462010000900467ffffffffffffffff1643101561162a5760405162461bcd60e51b8152600401808060200182810382526021815260200180613e926021913960400191505060405180910390fd5b6000611634613974565b600b8054600c805467ffffffffffffffff620100008085048216810269ffffffffffffffff00001961ffff1994851661ffff80891691909117821692909217909555604080518082018252918b1680835293891660209283018190529283029490961683179094169290921790945582519384529083015280519293507fea76eb91f1817e0757719ea43e0733faf6f1121425bde387d1dd91badb9d403b92918290030190a15050565b6004546001600160a01b0316151590565b60036116f96118d4565b600381111561170457fe5b1415611757576040805162461bcd60e51b815260206004820152601b60248201527f6865726d65732073686f756c64206265206e6f7420636c6f7365640000000000604482015290519081900360640190fd5b6114d8828260006137b8565b6003546040805163505a1b3160e01b81526001600160a01b0388811660048301529151600093929092169163505a1b3191602480820192602092909190829003018186803b1580156117b457600080fd5b505afa1580156117c8573d6000803e3d6000fd5b505050506040513d60208110156117de57600080fd5b505190506001600160a01b0381166118275760405162461bcd60e51b8152600401808060200182810382526042815260200180613e506042913960600191505060405180910390fd5b600061183287612f8c565b905060006118468284898989896001613384565b6002546040805163a9059cbb60e01b81526001600160a01b03878116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b15801561189e57600080fd5b505af11580156118b2573d6000803e3d6000fd5b505050506040513d60208110156118c857600080fd5b50505050505050505050565b600a54600160a01b900460ff1690565b6000611912886040518060400160405280600a8152602001691dda5d1a191c985dd85b60b21b815250612dcc565b905060006119788361192261397c565b6040805160208082019390935280820187905260608082018e9052608082018c905289901b6bffffffffffffffffffffffff191660a08201528151808203609401815260b4909101909152805191012090613980565b9050886001600160a01b0316816001600160a01b0316146119ca5760405162461bcd60e51b8152600401808060200182810382526036815260200180613c5c6036913960400191505060405180910390fd5b60006119dc83868b8b8b8b6000613384565b6002546040805163a9059cbb60e01b81526001600160a01b03898116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b158015611a3457600080fd5b505af1158015611a48573d6000803e3d6000fd5b505050506040513d6020811015611a5e57600080fd5b505050505050505050505050565b60035460405163d0171d7960e01b81526001600160a01b03898116600483019081528582166024840152606060448401908152855160648501528551929094169363d0171d79938c938893889390929091608490910190602085019080838360005b83811015611ae6578181015183820152602001611ace565b50505050905090810190601f168015611b135780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611b3457600080fd5b505af1158015611b48573d6000803e3d6000fd5b505050506000611b5788612f8c565b90506000611b6b82858a8a8a8a6001613384565b6002546040805163a9059cbb60e01b81526001600160a01b03888116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b158015611bc357600080fd5b505af1158015611bd7573d6000803e3d6000fd5b505050506040513d6020811015611bed57600080fd5b5050505050505050505050565b6003546001600160a01b031690565b6004546001600160a01b03163314611c525760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b6003611c5c6118d4565b6003811115611c6757fe5b14611cb9576040805162461bcd60e51b815260206004820152601860248201527f6865726d6573206861766520746f20626520636c6f7365640000000000000000604482015290519081900360640190fd5b6009544311611cf95760405162461bcd60e51b8152600401808060200182810382526026815260200180613db36026913960400191505060405180910390fd5b600f54600254604080516370a0823160e01b81523060048201529051600093611d829390926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b158015611d5057600080fd5b505afa158015611d64573d6000803e3d6000fd5b505050506040513d6020811015611d7a57600080fd5b505190613701565b6002546040805163a9059cbb60e01b81526001600160a01b03868116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b158015611dda57600080fd5b505af1158015611dee573d6000803e3d6000fd5b505050506040513d6020811015611e0457600080fd5b50505050565b6001546001600160a01b0316611e1f57600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015611e58573d6000803e3d6000fd5b50565b611e636116de565b15611e9f5760405162461bcd60e51b8152600401808060200182810382526022815260200180613cb76022913960400191505060405180910390fd5b6001600160a01b038616611ee45760405162461bcd60e51b8152600401808060200182810382526030815260200180613cd96030913960400191505060405180910390fd5b6001600160a01b038516611f3f576040805162461bcd60e51b815260206004820152601f60248201527f4865726d65733a206f70657261746f72206861766520746f2062652073657400604482015290519081900360640190fd5b6113888461ffff161115611f845760405162461bcd60e51b81526004018080602001828103825260248152602001806140656024913960400191505060405180910390fd5b828211611fc25760405162461bcd60e51b8152600401808060200182810382526030815260200180613dd96030913960400191505060405180910390fd5b60038054336001600160a01b0319918216179091556002805482166001600160a01b0389811691909117918290556004805490931688821617835560408051808201825261ffff89168082524367ffffffffffffffff166020928301819052600b805461ffff191690921769ffffffffffffffff00001916620100009091021790556006889055600787905581516370a0823160e01b81523095810195909552905192909116926370a082319260248083019392829003018186803b15801561208a57600080fd5b505afa15801561209e573d6000803e3d6000fd5b505050506040513d60208110156120b457600080fd5b50516008556002546040805163095ea7b360e01b81526001600160a01b03848116600483015260001960248301529151919092169163095ea7b39160448083019260209291908290030181600087803b15801561211057600080fd5b505af1158015612124573d6000803e3d6000fd5b505050506040513d602081101561213a57600080fd5b5050600a80546001600160a01b0319166001600160a01b03831617905561216085612fd0565b505050505050565b6000818152600d602052604081205415158061219457506000828152600d602052604090206001015415155b92915050565b6004546001600160a01b031633146121e35760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b6121eb612c5b565b612237576040805162461bcd60e51b81526020600482015260186024820152774865726d65733a2068617320746f2062652061637469766560401b604482015290519081900360640190fd5b60065481116122775760405162461bcd60e51b815260040180806020018281038252602f815260200180613d84602f913960400191505060405180910390fd5b60078190556040805182815290517f53f4fb18cb329155d5af04681c1d0846d0484d7de33791619c6988ca61910e3d9181900360200190a150565b604080516020808201859052825180830382018152918301909252805191012060009081612328846122e261397c565b604080516020808201939093528082018d9052606081018c9052608081018b905260a08082018890528251808303909101815260c0909101909152805191012090613980565b6004546001600160a01b0390811691161498975050505050505050565b600061235086612f8c565b905060006123648230888888886001613384565b9050612372828260016137b8565b50505050505050565b600061238685612f8c565b905061239181612168565b6123e2576040805162461bcd60e51b815260206004820181905260248201527f4865726d65733a206368616e6e656c2068617320746f206265206f70656e6564604482015290519081900360640190fd5b828410156124215760405162461bcd60e51b8152600401808060200182810382526033815260200180613bd16033913960400191505060405180910390fd5b6000818152600d6020526040902060018101548511156124725760405162461bcd60e51b8152600401808060200182810382526032815260200180613ed56032913960400191505060405180910390fd5b600281018054600101905560408051808201909152601481527314dd185ad9481c995d1d5c9b881c995c5d595cdd60621b602082015260009061255f9085906124b961397c565b868a8a88600201546040516020018087805190602001908083835b602083106124f35780518252601f1990920191602091820191016124d4565b6001836020036101000a03801982511681845116808217855250505050505090500186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012061398090919063ffffffff16565b90508261256b82612f8c565b146125a75760405162461bcd60e51b815260040180806020018281038252602a8152602001806140bc602a913960400191505060405180910390fd5b60018201546000906125b99088613701565b90508515612642576002546040805163a9059cbb60e01b81523360048201526024810189905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561261557600080fd5b505af1158015612629573d6000803e3d6000fd5b505050506040513d602081101561263f57600080fd5b50505b6003546040805163505a1b3160e01b81526001600160a01b038b811660048301529151600093929092169163505a1b3191602480820192602092909190829003018186803b15801561269357600080fd5b505afa1580156126a7573d6000803e3d6000fd5b505050506040513d60208110156126bd57600080fd5b50516002549091506001600160a01b031663a9059cbb826126de8b8b613701565b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561272457600080fd5b505af1158015612738573d6000803e3d6000fd5b505050506040513d602081101561274e57600080fd5b5050600184018290556005546127649089613701565b60055560408051838152905186917fc5f0715c45dab2e8f14871936119e3c64fd5841d397130c2d1db743d142522cb919081900360200190a2505050505050505050565b600d6020526000908152604090208054600182015460028301546003909301549192909184565b6004546001600160a01b031633146128185760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b612820612c5b565b61286c576040805162461bcd60e51b81526020600482015260186024820152774865726d65733a2068617320746f2062652061637469766560401b604482015290519081900360640190fd5b60075481106128ac5760405162461bcd60e51b8152600401808060200182810382526030815260200180613d2b6030913960400191505060405180910390fd5b60068190556040805182815290517fb9e5e6e8db1283ee860f3856d8383e40665c58a5264ede5e6ed8ec1afb0312519181900360200190a150565b600b54600090819062010000900467ffffffffffffffff1643101561290d57600c612910565b600b5b60408051808201909152905461ffff81168083526201000090910467ffffffffffffffff1660209092019190915292915050565b6000546001600160a01b031690565b600061296c6005546111d6600854600e60010154613a00565b905090565b600b5461ffff81169062010000900467ffffffffffffffff1682565b6006546007549091565b6004546001600160a01b031633146129e05760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b60006129ea6118d4565b60038111156129f557fe5b14612a315760405162461bcd60e51b8152600401808060200182810382526022815260200180613eb36022913960400191505060405180910390fd5b600a805460ff60a01b1916600160a01b1790556040517f1f4cd5d6edef8a0c4dbe6d547fdc42e0f3575167257553271f2366f9d497f67e90600090a1565b600080612a7a612953565b600254604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015612acb57600080fd5b505afa158015612adf573d6000803e3d6000fd5b505050506040513d6020811015612af557600080fd5b5051905080821115612b0c576000925050506114e0565b612b168183613701565b9250505090565b6004546001600160a01b03163314612b665760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b80612b6f612a6f565b1015612c14576000612b89612b82612a6f565b8390613701565b600254604080516323b872dd60e01b81523360048201523060248201526044810184905290519293506001600160a01b03909116916323b872dd916064808201926020929091908290030181600087803b158015612be657600080fd5b505af1158015612bfa573d6000803e3d6000fd5b505050506040513d6020811015612c1057600080fd5b5050505b600854612c21908261375e565b600881905560408051918252517feb10b8b69c3eb290299237eaee4760bf1c02734ce3dc7740d6f2017b5ca3ed919181900360200190a150565b600080612c666118d4565b90506002816003811115612c7657fe5b14158015612c9057506003816003811115612c8d57fe5b14155b91505090565b6001546001600160a01b0316612cab57600080fd5b6002546001600160a01b0382811691161415612cf85760405162461bcd60e51b8152600401808060200182810382526025815260200180613c926025913960400191505060405180910390fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612d4757600080fd5b505afa158015612d5b573d6000803e3d6000fd5b505050506040513d6020811015612d7157600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015611dda57600080fd5b600082308360405160200180846001600160a01b031660601b8152601401836001600160a01b031660601b815260140182805190602001908083835b60208310612e275780518252601f199092019160209182019101612e08565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405280519060200120905092915050565b600c5461ffff81169062010000900467ffffffffffffffff1682565b6004546001600160a01b03163314612ed15760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b612ed9612c5b565b612f2a576040805162461bcd60e51b815260206004820152601760248201527f6865726d65732073686f756c6420626520616374697665000000000000000000604482015290519081900360640190fd5b600a805460ff60a01b1916600360a01b179055612f45613a16565b6009556040805143815290517ffa9b0c2718819d67ceaec4f97d36185c2f1d22bdc5ff18f44c52cd56a5dd8e459181900360200190a1565b6004546001600160a01b031690565b60408051606092831b6bffffffffffffffffffffffff19166020808301919091523090931b6034820152815180820360280181526048909101909152805191012090565b6000546001600160a01b0316331480612ff257506000546001600160a01b0316155b613043576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166130885760405162461bcd60e51b8152600401808060200182810382526026815260200180613c046026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b0316331461312c5760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b613134612c5b565b613185576040805162461bcd60e51b815260206004820152601960248201527f4865726d65733a206861766520746f2062652061637469766500000000000000604482015290519081900360640190fd5b8061318e612a6f565b10156131cb5760405162461bcd60e51b8152600401808060200182810382526034815260200180613f6c6034913960400191505060405180910390fd5b6002546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561322157600080fd5b505af1158015613235573d6000803e3d6000fd5b505050506040513d602081101561324b57600080fd5b5050604080518281526001600160a01b038416602082015281517fa2e147ce2b7cb83d9c07e397bb806f23dd42c42e86ea45e1611d6e50eb1ec8bf929181900390910190a15050565b6001546001600160a01b031690565b6004546001600160a01b031633146132ec5760405162461bcd60e51b81526004018080602001828103825260338152602001806140896033913960400191505060405180910390fd5b60016132f66118d4565b600381111561330157fe5b1461333d5760405162461bcd60e51b8152600401808060200182810382526021815260200180613f4b6021913960400191505060405180910390fd5b600a805460ff60a01b191690556040517f2d8b6ec230798e206d536342a28b7b61cc8fcfafb1d27c11c5519b3c42eb7df890600090a1565b6002546001600160a01b031681565b600061338e612c5b565b6133c95760405162461bcd60e51b8152600401808060200182810382526029815260200180613d5b6029913960400191505060405180910390fd5b6133d688878787876122b2565b6134115760405162461bcd60e51b8152600401808060200182810382526032815260200180613c2a6032913960400191505060405180910390fd5b6000888152600d6020526040812090613428612a6f565b9050816001015481101561348257600a805460ff60a01b1916600160a11b17905543600e81905560408051918252517f23dc47ee5d995fb521fbe4351f353f3177d7b9d9e15bdd01ed358764c25d96299181900360200190a15b8154600090613492908a90613701565b90508781116134d25760405162461bcd60e51b8152600401808060200182810382526034815260200180613fe46034913960400191505060405180910390fd5b818111806134e1575060075481115b156134f5576134f282600754613a1f565b90505b8254613501908261375e565b835560008561351157600061351a565b61351a82611342565b905060006135288a8361375e565b905089156135b1576002546040805163a9059cbb60e01b8152336004820152602481018d905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561358457600080fd5b505af1158015613598573d6000803e3d6000fd5b505050506040513d60208110156135ae57600080fd5b50505b60006135bd8483613701565b90508c6001600160a01b03168e7fa5a1f05785a942c5f624cee545c68394881a83bcaf21a83f4d76a9e8240a56688385604051808381526020018281526020019250505060405180910390a39d9c50505050505050505050505050565b60008261362957506000612194565b8282028284828161363657fe5b04146136735760405162461bcd60e51b8152600401808060200182810382526021815260200180613f076021913960400191505060405180910390fd5b9392505050565b600081826001848601038161368b57fe5b04029392505050565b60008082116136ea576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816136f357fe5b049392505050565b61010190565b600082821115613758576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082820183811015613673576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082116137f75760405162461bcd60e51b8152600401808060200182810382526023815260200180613f286023913960400191505060405180910390fd5b6000838152600d602052604081206001810154909190613817908561375e565b905060075481111561385a5760405162461bcd60e51b8152600401808060200182810382526044815260200180613fa06044913960600191505060405180910390fd5b8261392057600254604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156138b957600080fd5b505af11580156138cd573d6000803e3d6000fd5b505050506040513d60208110156138e357600080fd5b50516139205760405162461bcd60e51b8152600401808060200182810382526025815260200180613e2b6025913960400191505060405180910390fd5b60018201819055600554613934908561375e565b60055560408051828152905186917fc5f0715c45dab2e8f14871936119e3c64fd5841d397130c2d1db743d142522cb919081900360200190a25050505050565b436146500190565b4690565b600081516041146139d8576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a6139f686828585613a2e565b9695505050505050565b6000818311613a0f5781613673565b5090919050565b43621b77400190565b6000818310613a0f5781613673565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613a8f5760405162461bcd60e51b8152600401808060200182810382526022815260200180613d096022913960400191505060405180910390fd5b8360ff16601b1480613aa457508360ff16601c145b613adf5760405162461bcd60e51b8152600401808060200182810382526022815260200180613e096022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613b3b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613ba3576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9594505050505056fe4865726d65733a206665652063616e2774206265206269676765722074686174203530254865726d65733a20616d6f756e742073686f756c6420626520626967676572207468616e207472616e736163746f72206665654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734865726d65733a206861766520746f2062652070726f7065726c79207369676e6564207061796d656e742070726f6d6973654865726d65733a20706179416e64536574746c6520726571756573742073686f756c642062652070726f7065726c79207369676e65646e617469766520746f6b656e2066756e64732063616e2774206265207265636f76657265644865726d65733a206861766520746f206265206e6f7420696e697469616c697a65644865726d65733a20746f6b656e2063616e2774206265206465706c6f796420696e746f207a65726f206164647265737345434453413a20696e76616c6964207369676e6174757265202773272076616c75654865726d65733a206d696e5374616b652068617320746f20626520736d616c6c6572207468616e206d61785374616b654865726d65733a206865726d6573206861766520746f20626520696e206163746976652073746174654865726d65733a206d61785374616b652068617320746f20626520626967676572207468616e206d696e5374616b6574696d656c6f636b20706572696f64206861766520626520616c7265616479207061737365644865726d65733a206d61785374616b65206861766520746f20626520626967676572207468616e206d696e5374616b6545434453413a20696e76616c6964207369676e6174757265202776272076616c75654865726d65733a20746f6b656e207472616e736665722073686f756c6420737563636565644865726d65733a206964656e74697479206861766520746f20626520726567697374657265642c2062656e6566696369617279206861766520746f206265207365744865726d65733a2063616e27742075706461746520696e616374697665206665654865726d65733a206861766520746f20626520696e206163746976652073746174654865726d65733a2063616e2774207769746864726177206d6f7265207468616e207468652063757272656e74207374616b65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774865726d65733a2073686f756c64207374616b65206d6f7265207468616e207a65726f6865726d6573206861766520746f20626520696e207061757365642073746174654865726d65733a2073686f756c6420626520656e6f7567682066756e647320617661696c61626c6520746f2077697468647261774865726d65733a20746f74616c20616d6f756e7420746f207374616b652063616e277420626520626967676572207468616e206d6178696d616c6c7920616c6c6f7765644865726d65733a20616d6f756e7420746f20736574746c652073686f756c6420636f766572207472616e736163746f72206665654865726d65733a2073686f756c6420626520696e2070756e6973686d656e74207374617475734865726d65733a206f6e6c792072656769737472792063616e206f70656e206368616e6e656c734865726d65733a206665652063616e277420626520626967676572207468616e203530254865726d65733a206f6e6c79206865726d6573206f70657261746f722063616e2063616c6c20746869732066756e6374696f6e4865726d65733a206861766520746f206265207369676e6564206279206368616e6e656c207061727479a2646970667358221220f9983545f1d13554c0ee71ebc93d6cc42a742bc684b0326f50c6465f98f58e4864736f6c63430007060033" // DeployHermesImplementation deploys a new Ethereum contract, binding an instance of HermesImplementation to it. func DeployHermesImplementation(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *HermesImplementation, error) { @@ -326,30 +326,56 @@ func (_HermesImplementation *HermesImplementationCallerSession) GetActiveFee() ( return _HermesImplementation.Contract.GetActiveFee(&_HermesImplementation.CallOpts) } -// GetChannelId is a free data retrieval call binding the contract method 0xeb295b27. +// GetChannelId is a free data retrieval call binding the contract method 0xe1791b2d. +// +// Solidity: function getChannelId(address _identity, string _type) view returns(bytes32) +func (_HermesImplementation *HermesImplementationCaller) GetChannelId(opts *bind.CallOpts, _identity common.Address, _type string) ([32]byte, error) { + var ( + ret0 = new([32]byte) + ) + out := ret0 + err := _HermesImplementation.contract.Call(opts, out, "getChannelId", _identity, _type) + return *ret0, err +} + +// GetChannelId is a free data retrieval call binding the contract method 0xe1791b2d. +// +// Solidity: function getChannelId(address _identity, string _type) view returns(bytes32) +func (_HermesImplementation *HermesImplementationSession) GetChannelId(_identity common.Address, _type string) ([32]byte, error) { + return _HermesImplementation.Contract.GetChannelId(&_HermesImplementation.CallOpts, _identity, _type) +} + +// GetChannelId is a free data retrieval call binding the contract method 0xe1791b2d. +// +// Solidity: function getChannelId(address _identity, string _type) view returns(bytes32) +func (_HermesImplementation *HermesImplementationCallerSession) GetChannelId(_identity common.Address, _type string) ([32]byte, error) { + return _HermesImplementation.Contract.GetChannelId(&_HermesImplementation.CallOpts, _identity, _type) +} + +// GetChannelId0 is a free data retrieval call binding the contract method 0xeb295b27. // // Solidity: function getChannelId(address _identity) view returns(bytes32) -func (_HermesImplementation *HermesImplementationCaller) GetChannelId(opts *bind.CallOpts, _identity common.Address) ([32]byte, error) { +func (_HermesImplementation *HermesImplementationCaller) GetChannelId0(opts *bind.CallOpts, _identity common.Address) ([32]byte, error) { var ( ret0 = new([32]byte) ) out := ret0 - err := _HermesImplementation.contract.Call(opts, out, "getChannelId", _identity) + err := _HermesImplementation.contract.Call(opts, out, "getChannelId0", _identity) return *ret0, err } -// GetChannelId is a free data retrieval call binding the contract method 0xeb295b27. +// GetChannelId0 is a free data retrieval call binding the contract method 0xeb295b27. // // Solidity: function getChannelId(address _identity) view returns(bytes32) -func (_HermesImplementation *HermesImplementationSession) GetChannelId(_identity common.Address) ([32]byte, error) { - return _HermesImplementation.Contract.GetChannelId(&_HermesImplementation.CallOpts, _identity) +func (_HermesImplementation *HermesImplementationSession) GetChannelId0(_identity common.Address) ([32]byte, error) { + return _HermesImplementation.Contract.GetChannelId0(&_HermesImplementation.CallOpts, _identity) } -// GetChannelId is a free data retrieval call binding the contract method 0xeb295b27. +// GetChannelId0 is a free data retrieval call binding the contract method 0xeb295b27. // // Solidity: function getChannelId(address _identity) view returns(bytes32) -func (_HermesImplementation *HermesImplementationCallerSession) GetChannelId(_identity common.Address) ([32]byte, error) { - return _HermesImplementation.Contract.GetChannelId(&_HermesImplementation.CallOpts, _identity) +func (_HermesImplementation *HermesImplementationCallerSession) GetChannelId0(_identity common.Address) ([32]byte, error) { + return _HermesImplementation.Contract.GetChannelId0(&_HermesImplementation.CallOpts, _identity) } // GetFundsDestination is a free data retrieval call binding the contract method 0xf58c5b6e. @@ -1033,6 +1059,27 @@ func (_HermesImplementation *HermesImplementationTransactorSession) PauseChannel return _HermesImplementation.Contract.PauseChannelOpening(&_HermesImplementation.TransactOpts) } +// PayAndSettle is a paid mutator transaction binding the contract method 0x52a8e78d. +// +// Solidity: function payAndSettle(address _identity, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes _signature, address _beneficiary, bytes _beneficiarySignature) returns() +func (_HermesImplementation *HermesImplementationTransactor) PayAndSettle(opts *bind.TransactOpts, _identity common.Address, _amount *big.Int, _transactorFee *big.Int, _preimage [32]byte, _signature []byte, _beneficiary common.Address, _beneficiarySignature []byte) (*types.Transaction, error) { + return _HermesImplementation.contract.Transact(opts, "payAndSettle", _identity, _amount, _transactorFee, _preimage, _signature, _beneficiary, _beneficiarySignature) +} + +// PayAndSettle is a paid mutator transaction binding the contract method 0x52a8e78d. +// +// Solidity: function payAndSettle(address _identity, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes _signature, address _beneficiary, bytes _beneficiarySignature) returns() +func (_HermesImplementation *HermesImplementationSession) PayAndSettle(_identity common.Address, _amount *big.Int, _transactorFee *big.Int, _preimage [32]byte, _signature []byte, _beneficiary common.Address, _beneficiarySignature []byte) (*types.Transaction, error) { + return _HermesImplementation.Contract.PayAndSettle(&_HermesImplementation.TransactOpts, _identity, _amount, _transactorFee, _preimage, _signature, _beneficiary, _beneficiarySignature) +} + +// PayAndSettle is a paid mutator transaction binding the contract method 0x52a8e78d. +// +// Solidity: function payAndSettle(address _identity, uint256 _amount, uint256 _transactorFee, bytes32 _preimage, bytes _signature, address _beneficiary, bytes _beneficiarySignature) returns() +func (_HermesImplementation *HermesImplementationTransactorSession) PayAndSettle(_identity common.Address, _amount *big.Int, _transactorFee *big.Int, _preimage [32]byte, _signature []byte, _beneficiary common.Address, _beneficiarySignature []byte) (*types.Transaction, error) { + return _HermesImplementation.Contract.PayAndSettle(&_HermesImplementation.TransactOpts, _identity, _amount, _transactorFee, _preimage, _signature, _beneficiary, _beneficiarySignature) +} + // ResolveEmergency is a paid mutator transaction binding the contract method 0x15c73afd. // // Solidity: function resolveEmergency() returns() diff --git a/bindings/MystToken.go b/bindings/MystToken.go index 38d165a..e7bb7da 100644 --- a/bindings/MystToken.go +++ b/bindings/MystToken.go @@ -1,6 +1,6 @@ /* Mysterium network payment library. * - * Copyright (C) 2020 BlockDev AG + * Copyright (C) 2021 BlockDev AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -46,7 +46,7 @@ var ( const MystTokenABI = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"FundsRecoveryDestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Upgrade\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"UpgradeAgentSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"master\",\"type\":\"address\"}],\"name\":\"UpgradeMasterSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PERMIT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isUpgradeAgent\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenHolder\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"originalToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"originalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"upgradeFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upgradeMaster\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upgradeAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalUpgraded\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newUpgradeMaster\",\"type\":\"address\"}],\"name\":\"setUpgradeMaster\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"setUpgradeAgent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUpgradeState\",\"outputs\":[{\"internalType\":\"enumMystToken.UpgradeState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" // MystTokenBin is the compiled bytecode used for deploying new contracts. -var MystTokenBin = "0x60c06040523480156200001157600080fd5b5060405162001f9d38038062001f9d833981810160405260208110156200003757600080fd5b50516001600160601b0319606082901b16608052604080516318160ddd60e01b815290516001600160a01b038316916318160ddd916004808301926020929190829003018186803b1580156200008c57600080fd5b505afa158015620000a1573d6000803e3d6000fd5b505050506040513d6020811015620000b857600080fd5b505160a052620000c7620001d3565b600080546001600160a01b0319166001600160a01b039290921691909117905560408051808201825260098152684d797374657269756d60b81b602091820152815180830190925260018252603160f81b9101527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f5a6b6ed89c9a1a7ef403de5fac83d634f25f39cd4318f8dabc0fdddabbba7bd17fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc662000188620001d7565b6040805160208082019690965280820194909452606084019290925260808301523060a0808401919091528151808403909101815260c09092019052805191012060055550620001db565b3390565b4690565b60805160601c60a051611d9b6200020260003980610b3052508061066a5250611d9b6000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c8063600440cb1161010f578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105a3578063df8de3e7146105d1578063f58c5b6e146105f7578063ffeb7d75146105ff576101e5565b8063a9059cbb146104f8578063c752ff6214610524578063d505accf1461052c578063d7e7088a1461057d576101e5565b80637ecebe00116100de5780637ecebe00146104755780638444b3911461049b57806395d89b41146104c4578063a457c2d7146104cc576101e5565b8063600440cb1461041357806361d3d7a61461041b57806370a0823114610423578063753e88e514610449576101e5565b8063313ce5671161018757806342966c681161015657806342966c68146103c957806345977d03146103e65780634b2ba0dd146104035780635de4ccb01461040b576101e5565b8063313ce5671461034b5780633644e51514610369578063395093511461037157806340c10f191461039d576101e5565b806318160ddd116101c357806318160ddd146102cb578063238e130a146102e557806323b872dd1461030d57806330adf81f14610343576101e5565b806306fdde03146101ea578063095ea7b3146102675780630e7c1cb5146102a7575b600080fd5b6101f2610625565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561022c578181015183820152602001610214565b50505050905090810190601f1680156102595780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102936004803603604081101561027d57600080fd5b506001600160a01b03813516906020013561064a565b604080519115158252519081900360200190f35b6102af610668565b604080516001600160a01b039092168252519081900360200190f35b6102d361068d565b60408051918252519081900360200190f35b61030b600480360360208110156102fb57600080fd5b50356001600160a01b0316610693565b005b6102936004803603606081101561032357600080fd5b506001600160a01b03813581169160208101359091169060400135610781565b6102d361088c565b6103536108b0565b6040805160ff9092168252519081900360200190f35b6102d36108b5565b6102936004803603604081101561038757600080fd5b506001600160a01b0381351690602001356108bb565b61030b600480360360408110156103b357600080fd5b506001600160a01b038135169060200135610909565b61030b600480360360208110156103df57600080fd5b5035610986565b61030b600480360360208110156103fc57600080fd5b503561099a565b6102d3610b2e565b6102af610b52565b6102af610b61565b610293610b70565b6102d36004803603602081101561043957600080fd5b50356001600160a01b0316610b75565b61030b6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610b90565b6102d36004803603602081101561048b57600080fd5b50356001600160a01b0316610c5b565b6104a3610c6d565b604051808260058111156104b357fe5b815260200191505060405180910390f35b6101f2610cb3565b610293600480360360408110156104e257600080fd5b506001600160a01b038135169060200135610cd3565b6102936004803603604081101561050e57600080fd5b506001600160a01b038135169060200135610d3b565b6102d3610d4f565b61030b600480360360e081101561054257600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610d55565b61030b6004803603602081101561059357600080fd5b50356001600160a01b0316610f59565b6102d3600480360360408110156105b957600080fd5b506001600160a01b0381358116916020013516611227565b61030b600480360360208110156105e757600080fd5b50356001600160a01b0316611252565b6102af61136b565b61030b6004803603602081101561061557600080fd5b50356001600160a01b031661137a565b604051806040016040528060098152602001684d797374657269756d60b81b81525081565b600061065e61065761145c565b8484611460565b5060015b92915050565b7f00000000000000000000000000000000000000000000000000000000000000005b90565b60045490565b6000546001600160a01b03166106a761145c565b6001600160a01b0316146106ec5760405162461bcd60e51b815260040180806020018281038252602d815260200180611ba2602d913960400191505060405180910390fd5b6001600160a01b0381166107315760405162461bcd60e51b815260040180806020018281038252602e815260200180611c1e602e913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383811691821792839055604051919216907f2e1db88922daae16be4e3c1a1f4bfab0cf6741938844967bd985ac8b2a12c80490600090a350565b60006001600160a01b0384166107c85760405162461bcd60e51b8152600401808060200182810382526024815260200180611b026024913960400191505060405180910390fd5b60006107d261145c565b9050806001600160a01b0316856001600160a01b03161415801561081d57506001600160a01b0380861660009081526007602090815260408083209385168352929052205460001914155b1561087657610876858261087186604051806060016040528060278152602001611b26602791396001600160a01b03808c166000908152600760209081526040808320938b1683529290522054919061154c565b611460565b6108818585856115e3565b506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601281565b60055481565b600061065e6108c861145c565b8461087185600760006108d961145c565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906116c9565b6000546001600160a01b031661091d61145c565b6001600160a01b031614610978576040805162461bcd60e51b815260206004820152601c60248201527f4d5953543a206f6e6c792061206d61737465722063616e206d696e7400000000604482015290519081900360640190fd5b610982828261172a565b5050565b61099761099161145c565b8261184f565b50565b60006109a4610c6d565b905060038160058111156109b457fe5b14806109cb575060048160058111156109c957fe5b145b610a065760405162461bcd60e51b8152600401808060200182810382526025815260200180611bf96025913960400191505060405180910390fd5b81610a425760405162461bcd60e51b815260040180806020018281038252602d815260200180611ceb602d913960400191505060405180910390fd5b6000610a4c61145c565b9050610a58818461184f565b600254610a6590846116c9565b6002556001546040805163753e88e560e01b81526001600160a01b038481166004830152602482018790529151919092169163753e88e591604480830192600092919082900301818387803b158015610abd57600080fd5b505af1158015610ad1573d6000803e3d6000fd5b50505050806001600160a01b03167f7e5c344a8141a805725cb476f76c6953b842222b967edd1f78ddb6e8b3f397ac610b08610b52565b604080516001600160a01b039092168252602082018790528051918290030190a2505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001546001600160a01b031690565b6000546001600160a01b031690565b600181565b6001600160a01b031660009081526003602052604090205490565b610b98610668565b6001600160a01b0316336001600160a01b031614610be75760405162461bcd60e51b8152600401808060200182810382526028815260200180611ab96028913960400191505060405180910390fd5b610bff82610bfa836402540be400611994565b61172a565b610c166402540be400610c10610b2e565b90611994565b610c1e61068d565b11156109825760405162461bcd60e51b8152600401808060200182810382526032815260200180611c4c6032913960400191505060405180910390fd5b60066020526000908152604090205481565b6001546000906001600160a01b0316610c885750600261068a565b600254610c975750600361068a565b610c9f61068d565b610cab5750600561068a565b50600461068a565b60405180604001604052806004815260200163135654d560e21b81525081565b600061065e610ce061145c565b8461087185604051806060016040528060258152602001611d186025913960076000610d0a61145c565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919061154c565b600061065e610d4861145c565b84846115e3565b60025490565b42841015610da1576040805162461bcd60e51b8152602060048201526014602482015273135654d50e8814195c9b5a5d08195e1c1a5c995960621b604482015290519081900360640190fd5b6005546001600160a01b0380891660008181526006602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e08501825280519083012061190160f01b6101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e280820193601f1981019281900390910190855afa158015610ebc573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610ef25750886001600160a01b0316816001600160a01b0316145b610f43576040805162461bcd60e51b815260206004820152601760248201527f4d5953543a20696e76616c6964207369676e6174757265000000000000000000604482015290519081900360640190fd5b610f4e898989611460565b505050505050505050565b6000546001600160a01b0316610f6d61145c565b6001600160a01b031614610fb25760405162461bcd60e51b8152600401808060200182810382526030815260200180611a896030913960400191505060405180910390fd5b6001600160a01b038116610ff75760405162461bcd60e51b8152600401808060200182810382526029815260200180611cc26029913960400191505060405180910390fd5b6004611001610c6d565b600581111561100c57fe5b141561105f576040805162461bcd60e51b815260206004820152601f60248201527f4d5953543a20757067726164652068617320616c726561647920626567756e00604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b038381169190911791829055604080516330e9ebd360e11b8152905192909116916361d3d7a691600480820192602092909190829003018186803b1580156110bb57600080fd5b505afa1580156110cf573d6000803e3d6000fd5b505050506040513d60208110156110e557600080fd5b50516111225760405162461bcd60e51b8152600401808060200182810382526034815260200180611b6e6034913960400191505060405180910390fd5b61112a61068d565b600160009054906101000a90046001600160a01b03166001600160a01b0316634b2ba0dd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117857600080fd5b505afa15801561118c573d6000803e3d6000fd5b505050506040513d60208110156111a257600080fd5b5051146111e05760405162461bcd60e51b8152600401808060200182810382526034815260200180611a556034913960400191505060405180910390fd5b7f7845d5aa74cc410e35571258d954f23b82276e160fe8c188fa80566580f279cc611209610b52565b604080516001600160a01b039092168252519081900360200190a150565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205490565b6008546001600160a01b031661126757600080fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156112b657600080fd5b505afa1580156112ca573d6000803e3d6000fd5b505050506040513d60208110156112e057600080fd5b50516008546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561133b57600080fd5b505af115801561134f573d6000803e3d6000fd5b505050506040513d602081101561136557600080fd5b50505050565b6008546001600160a01b031690565b6001600160a01b0381166113bf5760405162461bcd60e51b815260040180806020018281038252602a815260200180611bcf602a913960400191505060405180910390fd5b6000546001600160a01b03166113d361145c565b6001600160a01b0316146114185760405162461bcd60e51b8152600401808060200182810382526029815260200180611d3d6029913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b0383161790557f0bae748e6d38d2b1532af619519837d91d74845ad693f6f229677b4ac20b2d50611209610b61565b3390565b6001600160a01b0383166114a55760405162461bcd60e51b8152600401808060200182810382526023815260200180611c9f6023913960400191505060405180910390fd5b6001600160a01b0382166114ea5760405162461bcd60e51b8152600401808060200182810382526021815260200180611ae16021913960400191505060405180910390fd5b6001600160a01b03808416600081815260076020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600081848411156115db5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115a0578181015183820152602001611588565b50505050905090810190601f1680156115cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038216611600576115fb838261184f565b6116c4565b61163d81604051806060016040528060258152602001611a30602591396001600160a01b038616600090815260036020526040902054919061154c565b6001600160a01b03808516600090815260036020526040808220939093559084168152205461166c90826116c9565b6001600160a01b0380841660008181526003602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35b505050565b600082820183811015611723576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611785576040805162461bcd60e51b815260206004820152601e60248201527f4d5953543a206d696e7420746f20746865207a65726f20616464726573730000604482015290519081900360640190fd5b60045461179290826116c9565b6004556001600160a01b0382166000908152600360205260409020546117b890826116c9565b6001600160a01b038316600081815260036020908152604091829020939093558051848152905191927f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe92918290030190a26040805182815290516001600160a01b038416916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b0382166118aa576040805162461bcd60e51b815260206004820181905260248201527f4d5953543a206275726e2066726f6d20746865207a65726f2061646472657373604482015290519081900360640190fd5b6118e781604051806060016040528060218152602001611c7e602191396001600160a01b038516600090815260036020526040902054919061154c565b6001600160a01b03831660009081526003602052604090205560045461190d90826119ed565b6004556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a36040805182815290516001600160a01b038416917f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7919081900360200190a25050565b6000826119a357506000610662565b828202828482816119b057fe5b04146117235760405162461bcd60e51b8152600401808060200182810382526021815260200180611b4d6021913960400191505060405180910390fd5b600061172383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061154c56fe4d5953543a207472616e7366657220616d6f756e7420657863656564732062616c616e63654d5953543a2075706772616465206167656e742073686f756c64206b6e6f7720746f6b656e277320746f74616c20737570706c794d5953543a206f6e6c792061206d61737465722063616e2064657369676e61746520746865206e657874206167656e746f6e6c79206f726967696e616c20746f6b656e2063616e2063616c6c207570677261646546726f6d4d5953543a20617070726f766520746f20746865207a65726f20616464726573734d5953543a207472616e736665722066726f6d20746865207a65726f20616464726573734d5953543a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d5953543a206167656e742073686f756c6420696d706c656d656e742049557067726164654167656e7420696e746572666163654d5953543a206f6e6c792061206d61737465722063616e207365742066756e64732064657374696e6174696f6e4d5953543a2075706772616465206d61737465722063616e2774206265207a65726f20616464726573734d5953543a20746f6b656e206973206e6f7420696e20757067726164696e672073746174654d5953543a2066756e64732064657374696e6174696f6e2063616e2774206265207a65726f20616464726565737363616e206e6f74206d696e74206d6f726520746f6b656e73207468616e20696e206f726967696e616c20636f6e74726163744d5953543a206275726e20616d6f756e7420657863656564732062616c616e63654d5953543a20617070726f76652066726f6d20746865207a65726f20616464726573734d5953543a2075706772616465206167656e742063616e2774206265207a65726f20616464726573734d5953543a2075706772616461626c6520616d6f756e742073686f756c64206265206d6f7265207468616e203045524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f4d5953543a206f6e6c792075706772616465206d61737465722063616e20736574206e6577206f6e65a26469706673582212201cda6413f6ed0a2088f3c1e72f0dfbc0313b610e07cc6c11806a4dcd5271815064736f6c63430007040033" +var MystTokenBin = "0x60c06040523480156200001157600080fd5b5060405162001fb838038062001fb8833981810160405260208110156200003757600080fd5b50516001600160601b0319606082901b16608052604080516318160ddd60e01b815290516001600160a01b038316916318160ddd916004808301926020929190829003018186803b1580156200008c57600080fd5b505afa158015620000a1573d6000803e3d6000fd5b505050506040513d6020811015620000b857600080fd5b505160a052620000c7620001d3565b600080546001600160a01b0319166001600160a01b039290921691909117905560408051808201825260098152684d797374657269756d60b81b602091820152815180830190925260018252603160f81b9101527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f5a6b6ed89c9a1a7ef403de5fac83d634f25f39cd4318f8dabc0fdddabbba7bd17fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc662000188620001d7565b6040805160208082019690965280820194909452606084019290925260808301523060a0808401919091528151808403909101815260c09092019052805191012060055550620001db565b3390565b4690565b60805160601c60a051611db66200020260003980610b3052508061066a5250611db66000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c8063600440cb1161010f578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105a3578063df8de3e7146105d1578063f58c5b6e146105f7578063ffeb7d75146105ff576101e5565b8063a9059cbb146104f8578063c752ff6214610524578063d505accf1461052c578063d7e7088a1461057d576101e5565b80637ecebe00116100de5780637ecebe00146104755780638444b3911461049b57806395d89b41146104c4578063a457c2d7146104cc576101e5565b8063600440cb1461041357806361d3d7a61461041b57806370a0823114610423578063753e88e514610449576101e5565b8063313ce5671161018757806342966c681161015657806342966c68146103c957806345977d03146103e65780634b2ba0dd146104035780635de4ccb01461040b576101e5565b8063313ce5671461034b5780633644e51514610369578063395093511461037157806340c10f191461039d576101e5565b806318160ddd116101c357806318160ddd146102cb578063238e130a146102e557806323b872dd1461030d57806330adf81f14610343576101e5565b806306fdde03146101ea578063095ea7b3146102675780630e7c1cb5146102a7575b600080fd5b6101f2610625565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561022c578181015183820152602001610214565b50505050905090810190601f1680156102595780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102936004803603604081101561027d57600080fd5b506001600160a01b03813516906020013561064a565b604080519115158252519081900360200190f35b6102af610668565b604080516001600160a01b039092168252519081900360200190f35b6102d361068d565b60408051918252519081900360200190f35b61030b600480360360208110156102fb57600080fd5b50356001600160a01b0316610693565b005b6102936004803603606081101561032357600080fd5b506001600160a01b03813581169160208101359091169060400135610781565b6102d361088c565b6103536108b0565b6040805160ff9092168252519081900360200190f35b6102d36108b5565b6102936004803603604081101561038757600080fd5b506001600160a01b0381351690602001356108bb565b61030b600480360360408110156103b357600080fd5b506001600160a01b038135169060200135610909565b61030b600480360360208110156103df57600080fd5b5035610986565b61030b600480360360208110156103fc57600080fd5b503561099a565b6102d3610b2e565b6102af610b52565b6102af610b61565b610293610b70565b6102d36004803603602081101561043957600080fd5b50356001600160a01b0316610b75565b61030b6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610b90565b6102d36004803603602081101561048b57600080fd5b50356001600160a01b0316610c5b565b6104a3610c6d565b604051808260058111156104b357fe5b815260200191505060405180910390f35b6101f2610cb3565b610293600480360360408110156104e257600080fd5b506001600160a01b038135169060200135610cd3565b6102936004803603604081101561050e57600080fd5b506001600160a01b038135169060200135610d3b565b6102d3610d4f565b61030b600480360360e081101561054257600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610d55565b61030b6004803603602081101561059357600080fd5b50356001600160a01b0316610f59565b6102d3600480360360408110156105b957600080fd5b506001600160a01b0381358116916020013516611227565b61030b600480360360208110156105e757600080fd5b50356001600160a01b0316611252565b6102af61136b565b61030b6004803603602081101561061557600080fd5b50356001600160a01b031661137a565b604051806040016040528060098152602001684d797374657269756d60b81b81525081565b600061065e61065761145c565b8484611460565b5060015b92915050565b7f00000000000000000000000000000000000000000000000000000000000000005b90565b60045490565b6000546001600160a01b03166106a761145c565b6001600160a01b0316146106ec5760405162461bcd60e51b815260040180806020018281038252602d815260200180611bbd602d913960400191505060405180910390fd5b6001600160a01b0381166107315760405162461bcd60e51b815260040180806020018281038252602e815260200180611c39602e913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383811691821792839055604051919216907f2e1db88922daae16be4e3c1a1f4bfab0cf6741938844967bd985ac8b2a12c80490600090a350565b60006001600160a01b0384166107c85760405162461bcd60e51b8152600401808060200182810382526024815260200180611b1d6024913960400191505060405180910390fd5b60006107d261145c565b9050806001600160a01b0316856001600160a01b03161415801561081d57506001600160a01b0380861660009081526007602090815260408083209385168352929052205460001914155b1561087657610876858261087186604051806060016040528060278152602001611b41602791396001600160a01b03808c166000908152600760209081526040808320938b1683529290522054919061154c565b611460565b6108818585856115e3565b506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601281565b60055481565b600061065e6108c861145c565b8461087185600760006108d961145c565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906116c9565b6000546001600160a01b031661091d61145c565b6001600160a01b031614610978576040805162461bcd60e51b815260206004820152601c60248201527f4d5953543a206f6e6c792061206d61737465722063616e206d696e7400000000604482015290519081900360640190fd5b610982828261172a565b5050565b61099761099161145c565b8261184f565b50565b60006109a4610c6d565b905060038160058111156109b457fe5b14806109cb575060048160058111156109c957fe5b145b610a065760405162461bcd60e51b8152600401808060200182810382526025815260200180611c146025913960400191505060405180910390fd5b81610a425760405162461bcd60e51b815260040180806020018281038252602d815260200180611d06602d913960400191505060405180910390fd5b6000610a4c61145c565b9050610a58818461184f565b600254610a6590846116c9565b6002556001546040805163753e88e560e01b81526001600160a01b038481166004830152602482018790529151919092169163753e88e591604480830192600092919082900301818387803b158015610abd57600080fd5b505af1158015610ad1573d6000803e3d6000fd5b50505050806001600160a01b03167f7e5c344a8141a805725cb476f76c6953b842222b967edd1f78ddb6e8b3f397ac610b08610b52565b604080516001600160a01b039092168252602082018790528051918290030190a2505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001546001600160a01b031690565b6000546001600160a01b031690565b600181565b6001600160a01b031660009081526003602052604090205490565b610b98610668565b6001600160a01b0316336001600160a01b031614610be75760405162461bcd60e51b8152600401808060200182810382526028815260200180611ad46028913960400191505060405180910390fd5b610bff82610bfa836402540be400611994565b61172a565b610c166402540be400610c10610b2e565b90611994565b610c1e61068d565b11156109825760405162461bcd60e51b8152600401808060200182810382526032815260200180611c676032913960400191505060405180910390fd5b60066020526000908152604090205481565b6001546000906001600160a01b0316610c885750600261068a565b600254610c975750600361068a565b610c9f61068d565b610cab5750600561068a565b50600461068a565b60405180604001604052806004815260200163135654d560e21b81525081565b600061065e610ce061145c565b8461087185604051806060016040528060258152602001611d336025913960076000610d0a61145c565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919061154c565b600061065e610d4861145c565b84846115e3565b60025490565b42841015610da1576040805162461bcd60e51b8152602060048201526014602482015273135654d50e8814195c9b5a5d08195e1c1a5c995960621b604482015290519081900360640190fd5b6005546001600160a01b0380891660008181526006602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e08501825280519083012061190160f01b6101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e280820193601f1981019281900390910190855afa158015610ebc573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610ef25750886001600160a01b0316816001600160a01b0316145b610f43576040805162461bcd60e51b815260206004820152601760248201527f4d5953543a20696e76616c6964207369676e6174757265000000000000000000604482015290519081900360640190fd5b610f4e898989611460565b505050505050505050565b6000546001600160a01b0316610f6d61145c565b6001600160a01b031614610fb25760405162461bcd60e51b8152600401808060200182810382526030815260200180611aa46030913960400191505060405180910390fd5b6001600160a01b038116610ff75760405162461bcd60e51b8152600401808060200182810382526029815260200180611cdd6029913960400191505060405180910390fd5b6004611001610c6d565b600581111561100c57fe5b141561105f576040805162461bcd60e51b815260206004820152601f60248201527f4d5953543a20757067726164652068617320616c726561647920626567756e00604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b038381169190911791829055604080516330e9ebd360e11b8152905192909116916361d3d7a691600480820192602092909190829003018186803b1580156110bb57600080fd5b505afa1580156110cf573d6000803e3d6000fd5b505050506040513d60208110156110e557600080fd5b50516111225760405162461bcd60e51b8152600401808060200182810382526034815260200180611b896034913960400191505060405180910390fd5b61112a61068d565b600160009054906101000a90046001600160a01b03166001600160a01b0316634b2ba0dd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117857600080fd5b505afa15801561118c573d6000803e3d6000fd5b505050506040513d60208110156111a257600080fd5b5051146111e05760405162461bcd60e51b8152600401808060200182810382526034815260200180611a706034913960400191505060405180910390fd5b7f7845d5aa74cc410e35571258d954f23b82276e160fe8c188fa80566580f279cc611209610b52565b604080516001600160a01b039092168252519081900360200190a150565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205490565b6008546001600160a01b031661126757600080fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156112b657600080fd5b505afa1580156112ca573d6000803e3d6000fd5b505050506040513d60208110156112e057600080fd5b50516008546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561133b57600080fd5b505af115801561134f573d6000803e3d6000fd5b505050506040513d602081101561136557600080fd5b50505050565b6008546001600160a01b031690565b6001600160a01b0381166113bf5760405162461bcd60e51b815260040180806020018281038252602a815260200180611bea602a913960400191505060405180910390fd5b6000546001600160a01b03166113d361145c565b6001600160a01b0316146114185760405162461bcd60e51b8152600401808060200182810382526029815260200180611d586029913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b0383161790557f0bae748e6d38d2b1532af619519837d91d74845ad693f6f229677b4ac20b2d50611209610b61565b3390565b6001600160a01b0383166114a55760405162461bcd60e51b8152600401808060200182810382526023815260200180611cba6023913960400191505060405180910390fd5b6001600160a01b0382166114ea5760405162461bcd60e51b8152600401808060200182810382526021815260200180611afc6021913960400191505060405180910390fd5b6001600160a01b03808416600081815260076020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600081848411156115db5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115a0578181015183820152602001611588565b50505050905090810190601f1680156115cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038216611600576115fb838261184f565b6116c4565b61163d81604051806060016040528060258152602001611a4b602591396001600160a01b038616600090815260036020526040902054919061154c565b6001600160a01b03808516600090815260036020526040808220939093559084168152205461166c90826116c9565b6001600160a01b0380841660008181526003602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35b505050565b600082820183811015611723576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611785576040805162461bcd60e51b815260206004820152601e60248201527f4d5953543a206d696e7420746f20746865207a65726f20616464726573730000604482015290519081900360640190fd5b60045461179290826116c9565b6004556001600160a01b0382166000908152600360205260409020546117b890826116c9565b6001600160a01b038316600081815260036020908152604091829020939093558051848152905191927f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe92918290030190a26040805182815290516001600160a01b038416916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b0382166118aa576040805162461bcd60e51b815260206004820181905260248201527f4d5953543a206275726e2066726f6d20746865207a65726f2061646472657373604482015290519081900360640190fd5b6118e781604051806060016040528060218152602001611c99602191396001600160a01b038516600090815260036020526040902054919061154c565b6001600160a01b03831660009081526003602052604090205560045461190d90826119ed565b6004556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a36040805182815290516001600160a01b038416917f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7919081900360200190a25050565b6000826119a357506000610662565b828202828482816119b057fe5b04146117235760405162461bcd60e51b8152600401808060200182810382526021815260200180611b686021913960400191505060405180910390fd5b600082821115611a44576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe4d5953543a207472616e7366657220616d6f756e7420657863656564732062616c616e63654d5953543a2075706772616465206167656e742073686f756c64206b6e6f7720746f6b656e277320746f74616c20737570706c794d5953543a206f6e6c792061206d61737465722063616e2064657369676e61746520746865206e657874206167656e746f6e6c79206f726967696e616c20746f6b656e2063616e2063616c6c207570677261646546726f6d4d5953543a20617070726f766520746f20746865207a65726f20616464726573734d5953543a207472616e736665722066726f6d20746865207a65726f20616464726573734d5953543a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d5953543a206167656e742073686f756c6420696d706c656d656e742049557067726164654167656e7420696e746572666163654d5953543a206f6e6c792061206d61737465722063616e207365742066756e64732064657374696e6174696f6e4d5953543a2075706772616465206d61737465722063616e2774206265207a65726f20616464726573734d5953543a20746f6b656e206973206e6f7420696e20757067726164696e672073746174654d5953543a2066756e64732064657374696e6174696f6e2063616e2774206265207a65726f20616464726565737363616e206e6f74206d696e74206d6f726520746f6b656e73207468616e20696e206f726967696e616c20636f6e74726163744d5953543a206275726e20616d6f756e7420657863656564732062616c616e63654d5953543a20617070726f76652066726f6d20746865207a65726f20616464726573734d5953543a2075706772616465206167656e742063616e2774206265207a65726f20616464726573734d5953543a2075706772616461626c6520616d6f756e742073686f756c64206265206d6f7265207468616e203045524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f4d5953543a206f6e6c792075706772616465206d61737465722063616e20736574206e6577206f6e65a2646970667358221220b5a52055dc0a82cdd576cdf9ff956f3d8cd72b456a455f4f5144319a26ff251564736f6c63430007060033" // DeployMystToken deploys a new Ethereum contract, binding an instance of MystToken to it. func DeployMystToken(auth *bind.TransactOpts, backend bind.ContractBackend, tokenAddress common.Address) (common.Address, *types.Transaction, *MystToken, error) { diff --git a/bindings/Registry.go b/bindings/Registry.go index b365490..a896e1a 100644 --- a/bindings/Registry.go +++ b/bindings/Registry.go @@ -1,6 +1,6 @@ /* Mysterium network payment library. * - * Copyright (C) 2020 BlockDev AG + * Copyright (C) 2021 BlockDev AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -42,20 +42,28 @@ var ( _ = event.NewSubscription ) +// RegistryHermes is an auto generated low-level Go binding around an user-defined struct. +type RegistryHermes struct { + Operator common.Address + ImplVer *big.Int + Stake [24]byte + Url []byte +} + // RegistryABI is the input ABI used to generate the binding from. -const RegistryABI = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"_dexAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minimalHermesStake\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_channelImplementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesImplementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hermesId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"channelAddress\",\"type\":\"address\"}],\"name\":\"ConsumerChannelCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"DestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hermesId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newURL\",\"type\":\"bytes\"}],\"name\":\"HermesURLUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hermesId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"hermesOperator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"ur\",\"type\":\"bytes\"}],\"name\":\"RegisteredHermes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"RegisteredIdentity\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"claimEthers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dex\",\"outputs\":[{\"internalType\":\"addresspayable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hermeses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"implVer\",\"type\":\"uint256\"},{\"internalType\":\"function()viewexternalreturns(uint256)\",\"name\":\"stake\",\"type\":\"function\"},{\"internalType\":\"bytes\",\"name\":\"url\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimalHermesStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIERC20Token\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_stakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"registerIdentity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesOperator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_hermesStake\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_hermesFee\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"_minChannelStake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxChannelStake\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_url\",\"type\":\"bytes\"}],\"name\":\"registerHermes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"getChannelAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesOperator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_implVer\",\"type\":\"uint256\"}],\"name\":\"getHermesAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesOperator\",\"type\":\"address\"}],\"name\":\"getHermesAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"getHermesURL\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_url\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"updateHermesURL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getProxyCode\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"}],\"name\":\"getBeneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"setBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_implVer\",\"type\":\"uint256\"}],\"name\":\"getChannelImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChannelImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_implVer\",\"type\":\"uint256\"}],\"name\":\"getHermesImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHermesImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newChannelImplAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newHermesImplAddress\",\"type\":\"address\"}],\"name\":\"setImplementations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastImplVer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"hasParentRegistry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"}],\"name\":\"isRegistered\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"isHermes\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"}],\"name\":\"transferCollectedFeeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" +const RegistryABI = "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hermesId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"channelAddress\",\"type\":\"address\"}],\"name\":\"ConsumerChannelCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousDestination\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newDestination\",\"type\":\"address\"}],\"name\":\"DestinationChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hermesId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newURL\",\"type\":\"bytes\"}],\"name\":\"HermesURLUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinimalStake\",\"type\":\"uint256\"}],\"name\":\"MinimalHermesStakeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hermesId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"hermesOperator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"ur\",\"type\":\"bytes\"}],\"name\":\"RegisteredHermes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"identity\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"RegisteredIdentity\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"claimEthers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"claimTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dex\",\"outputs\":[{\"internalType\":\"addresspayable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFundsDestination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimalHermesStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"parentRegistry\",\"outputs\":[{\"internalType\":\"contractRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_newDestination\",\"type\":\"address\"}],\"name\":\"setFundsDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIERC20Token\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"_dexAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minimalHermesStake\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_channelImplementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesImplementation\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"_parentRegistry\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_stakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"registerIdentity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_transactorFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"openConsumerChannel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"openConsumerChannel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesOperator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_hermesStake\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"_hermesFee\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"_minChannelStake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxChannelStake\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_url\",\"type\":\"bytes\"}],\"name\":\"registerHermes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"getChannelAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"getHermes\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"implVer\",\"type\":\"uint256\"},{\"internalType\":\"function()viewexternalreturns(uint256)\",\"name\":\"stake\",\"type\":\"function\"},{\"internalType\":\"bytes\",\"name\":\"url\",\"type\":\"bytes\"}],\"internalType\":\"structRegistry.Hermes\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesOperator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_implVer\",\"type\":\"uint256\"}],\"name\":\"getHermesAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesOperator\",\"type\":\"address\"}],\"name\":\"getHermesAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"getHermesURL\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_url\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"updateHermesURL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getProxyCode\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"}],\"name\":\"getBeneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"setBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newMinimalStake\",\"type\":\"uint256\"}],\"name\":\"setMinimalHermesStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_implVer\",\"type\":\"uint256\"}],\"name\":\"getChannelImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChannelImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_implVer\",\"type\":\"uint256\"}],\"name\":\"getHermesImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHermesImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newChannelImplAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newHermesImplAddress\",\"type\":\"address\"}],\"name\":\"setImplementations\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastImplVer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hasParentRegistry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"}],\"name\":\"isRegistered\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"isHermes\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_identity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hermesId\",\"type\":\"address\"}],\"name\":\"isChannelOpened\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"}],\"name\":\"transferCollectedFeeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" // RegistryBin is the compiled bytecode used for deploying new contracts. -var RegistryBin = "0x60806040523480156200001157600080fd5b5060405162002e9038038062002e90833981810160405260a08110156200003757600080fd5b5080516020820151604083015160608401516080909401516005829055929391929091906001600160a01b0385166200006f57600080fd5b600280546001600160a01b0319166001600160a01b038781169190911790915584166200009b57600080fd5b600480546001600160a01b0319166001600160a01b038616179055620000c28282620000d8565b620000cd3362000239565b505050505062000345565b6000546001600160a01b0316331480620000fb57506000546001600160a01b0316155b6200013c576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e70833981519152604482015290519081900360640190fd5b62000147826200033f565b80156200015a57506200015a816200033f565b620001975760405162461bcd60e51b815260040180806020018281038252603481526020018062002e166034913960400191505060405180910390fd5b604080518082019091526001600160a01b0392831681529082166020820190815260068054600181018255600091909152915160029092027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f810180549385166001600160a01b031994851617905590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d409091018054919093169116179055565b6000546001600160a01b03163314806200025c57506000546001600160a01b0316155b6200029d576040805162461bcd60e51b8152602060048201819052602482015260008051602062002e70833981519152604482015290519081900360640190fd5b6001600160a01b038116620002e45760405162461bcd60e51b815260040180806020018281038252602681526020018062002e4a6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3b151590565b612ac180620003556000396000f3fe6080604052600436106101dc5760003560e01c80639936a87b11610102578063d0171d7911610095578063e617aaac11610064578063e617aaac14610adf578063f2fde38b14610b1a578063f58c5b6e14610b4d578063fc0c546a14610b6257610218565b8063d0171d79146108d2578063d5929fe31461099c578063df8de3e714610a79578063e325253714610aac57610218565b8063bf1eb88a116100d1578063bf1eb88a14610764578063c3c5a54714610797578063cdd596e0146107ca578063cf10c969146107fd57610218565b80639936a87b1461052e578063ab86721314610543578063acc831d0146105eb578063add10dda1461061e57610218565b80636332b0801161017a5780637c671a21116101495780637c671a211461049f57806385bff341146104b45780638cfef547146104ef5780638da5cb5b1461051957610218565b80636332b0801461044b57806366cf587514610460578063692058c2146104755780636931b5501461048a57610218565b806341ca71ab116101b657806341ca71ab146103725780634b6bd6be146103b8578063505a1b31146103f157806352631ab41461042457610218565b806303fb422f1461021d578063238e130a146102f6578063332ff7bd1461032b57610218565b366102185760405162461bcd60e51b81526004018080602001828103825260278152602001806129c76027913960400191505060405180910390fd5b600080fd5b34801561022957600080fd5b506102506004803603602081101561024057600080fd5b50356001600160a01b0316610b77565b60405180866001600160a01b03168152602001858152602001848463ffffffff169060201b1760401b815260200180602001828103825283818151815260200191508051906020019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34801561030257600080fd5b506103296004803603602081101561031957600080fd5b50356001600160a01b0316610c43565b005b34801561033757600080fd5b5061035e6004803603602081101561034e57600080fd5b50356001600160a01b0316610d13565b604080519115158252519081900360200190f35b34801561037e57600080fd5b5061039c6004803603602081101561039557600080fd5b5035610d1b565b604080516001600160a01b039092168252519081900360200190f35b3480156103c457600080fd5b5061039c600480360360408110156103db57600080fd5b506001600160a01b038135169060200135610d4a565b3480156103fd57600080fd5b5061039c6004803603602081101561041457600080fd5b50356001600160a01b0316610d83565b34801561043057600080fd5b50610439610da1565b60408051918252519081900360200190f35b34801561045757600080fd5b50610439610da7565b34801561046c57600080fd5b50610439610db1565b34801561048157600080fd5b5061039c610db7565b34801561049657600080fd5b50610329610dc6565b3480156104ab57600080fd5b5061039c610e17565b3480156104c057600080fd5b50610329600480360360408110156104d757600080fd5b506001600160a01b0381358116916020013516610e4c565b3480156104fb57600080fd5b5061039c6004803603602081101561051257600080fd5b5035610fa3565b34801561052557600080fd5b5061039c610fd5565b34801561053a57600080fd5b5061039c610fe4565b34801561054f57600080fd5b506105766004803603602081101561056657600080fd5b50356001600160a01b031661101c565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105b0578181015183820152602001610598565b50505050905090810190601f1680156105dd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105f757600080fd5b5061039c6004803603602081101561060e57600080fd5b50356001600160a01b031661109b565b34801561062a57600080fd5b506103296004803603606081101561064157600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561066b57600080fd5b82018360208201111561067d57600080fd5b803590602001918460018302840111600160201b8311171561069e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156106f057600080fd5b82018360208201111561070257600080fd5b803590602001918460018302840111600160201b8311171561072357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506110cd945050505050565b34801561077057600080fd5b506105766004803603602081101561078757600080fd5b50356001600160a01b0316611302565b3480156107a357600080fd5b5061035e600480360360208110156107ba57600080fd5b50356001600160a01b03166113b0565b3480156107d657600080fd5b5061035e600480360360208110156107ed57600080fd5b50356001600160a01b03166113d0565b34801561080957600080fd5b50610329600480360360a081101561082057600080fd5b6001600160a01b038235811692602081013592604082013592606083013516919081019060a081016080820135600160201b81111561085e57600080fd5b82018360208201111561087057600080fd5b803590602001918460018302840111600160201b8311171561089157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611439945050505050565b3480156108de57600080fd5b50610329600480360360608110156108f557600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b81111561092857600080fd5b82018360208201111561093a57600080fd5b803590602001918460018302840111600160201b8311171561095b57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119a2945050505050565b3480156109a857600080fd5b50610329600480360360c08110156109bf57600080fd5b6001600160a01b038235169160208101359161ffff604083013516916060810135916080820135919081019060c0810160a0820135600160201b811115610a0557600080fd5b820183602082011115610a1757600080fd5b803590602001918460018302840111600160201b83111715610a3857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611b15945050505050565b348015610a8557600080fd5b5061032960048036036020811015610a9c57600080fd5b50356001600160a01b0316611eb4565b348015610ab857600080fd5b5061032960048036036020811015610acf57600080fd5b50356001600160a01b031661201a565b348015610aeb57600080fd5b5061039c60048036036040811015610b0257600080fd5b506001600160a01b0381358116916020013516612186565b348015610b2657600080fd5b5061032960048036036020811015610b3d57600080fd5b50356001600160a01b0316612201565b348015610b5957600080fd5b5061039c612302565b348015610b6e57600080fd5b5061039c612311565b600760209081526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f81018890048802850188019098528784526001600160a01b0394851697929681811c9095169563ffffffff9091169490939290830182828015610c395780601f10610c0e57610100808354040283529160200191610c39565b820191906000526020600020905b815481529060010190602001808311610c1c57829003601f168201915b5050505050905085565b6000546001600160a01b0316331480610c6557506000546001600160a01b0316155b610ca4576040805162461bcd60e51b8152602060048201819052602482015260008051602061297a833981519152604482015290519081900360640190fd5b6001600160a01b038116610cb757600080fd5b6001546040516001600160a01b038084169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60005b919050565b600060068281548110610d2a57fe5b60009182526020909120600290910201546001600160a01b031692915050565b600080610d5e610d5984610fa3565b61101c565b80516020909101209050610d7b6001600160a01b03851682612320565b949350505050565b6001600160a01b039081166000908152600860205260409020541690565b60035481565b6006546000190190565b60055481565b6004546001600160a01b031681565b6001546001600160a01b0316610ddb57600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610e14573d6000803e3d6000fd5b50565b60006006610e23610da7565b81548110610e2d57fe5b60009182526020909120600290910201546001600160a01b0316905090565b6000546001600160a01b0316331480610e6e57506000546001600160a01b0316155b610ead576040805162461bcd60e51b8152602060048201819052602482015260008051602061297a833981519152604482015290519081900360640190fd5b610eb682612367565b8015610ec65750610ec681612367565b610f015760405162461bcd60e51b815260040180806020018281038252603481526020018061275d6034913960400191505060405180910390fd5b604080518082019091526001600160a01b0392831681529082166020820190815260068054600181018255600091909152915160029092027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f810180549385166001600160a01b031994851617905590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d409091018054919093169116179055565b600060068281548110610fb257fe5b60009182526020909120600290910201600101546001600160a01b031692915050565b6000546001600160a01b031690565b60006006610ff0610da7565b81548110610ffa57fe5b60009182526020909120600160029092020101546001600160a01b0316905090565b60608060405180606001604052806037815260200161289b603791399050606083901b60005b60148160ff16101561109257818160ff166014811061105d57fe5b1a60f81b838260140160ff168151811061107357fe5b60200101906001600160f81b031916908160001a905350600101611042565b50909392505050565b6000806110a9610d59610fe4565b805160209091012090506110c66001600160a01b03841682612320565b9392505050565b6110d68361236d565b6111115760405162461bcd60e51b815260040180806020018281038252602a8152602001806127ee602a913960400191505060405180910390fd5b60006111c382308686600360008154809291906001019190505560405160200180856001600160a01b031660601b8152601401846001600160a01b031660601b815260140183805190602001908083835b602083106111815780518252601f199092019160209182019101611162565b51815160209384036101000a60001901801990921691161790529201938452506040805180850381529382019052825192019190912094935061243292505050565b6001600160a01b03808616600090815260076020526040902054919250808316911614611229576040805162461bcd60e51b815260206004820152600f60248201526e77726f6e67207369676e617475726560881b604482015290519081900360640190fd5b6001600160a01b0384166000908152600760209081526040909120845161125892600390920191860190612695565b50836001600160a01b03167fd8c638c85547b8717e0d5ca292cff6dbe8fc02fa6e6863a047971c39511643c7846040518080602001828103825283818151815260200191508051906020019080838360005b838110156112c25781810151838201526020016112aa565b50505050905090810190601f1680156112ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390a250505050565b6001600160a01b03811660009081526007602090815260409182902060030180548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156113a45780601f10611379576101008083540402835291602001916113a4565b820191906000526020600020905b81548152906001019060200180831161138757829003601f168201915b50505050509050919050565b6001600160a01b0390811660009081526008602052604090205416151590565b6001600160a01b038082166000908152600760205260408120805460019091015491921690826114008383610d4a565b9050846001600160a01b0316816001600160a01b0316146114275760009350505050610d16565b61143081612367565b95945050505050565b6114428561236d565b61147d5760405162461bcd60e51b815260040180806020018281038252602b815260200180612a36602b913960400191505060405180910390fd5b6040805130606090811b6020808401919091526001600160601b031989831b8116603485015260488401899052606884018890529186901b90911660888301528251607c818403018152609c90920190925280519101206000906114e19083612432565b90506001600160a01b0381166115285760405162461bcd60e51b8152600401808060200182810382526022815260200180612a146022913960400191505060405180910390fd5b6000611534868661261d565b6002549091506001600160a01b03166370a08231611552848a612186565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561158f57600080fd5b505afa1580156115a3573d6000803e3d6000fd5b505050506040513d60208110156115b957600080fd5b50518111156115f95760405162461bcd60e51b81526004018080602001828103825260348152602001806129466034913960400191505060405180910390fd5b604080516001600160601b0319606085811b82166020808501919091528b821b909216603484015283516028818503018152604890930184528251928201929092206001600160a01b038b16600090815260079092529290206001015461166390610d5990610d1b565b905060006116718383612677565b6002546004805460408051637b809f7b60e11b81526001600160a01b0394851693810193909352908316602483015288831660448301528d8316606483015260848201889052519293509083169163f7013ef69160a48082019260009290919082900301818387803b1580156116e657600080fd5b505af11580156116fa573d6000803e3d6000fd5b5050505060008911801561171657506001600160a01b03871615155b15611848576002546040805163095ea7b360e01b81526001600160a01b038d81166004830152602482018d90529151919092169163095ea7b39160448083019260209291908290030181600087803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b505050506040513d602081101561179b57600080fd5b50516117d85760405162461bcd60e51b81526004018080602001828103825260378152602001806127916037913960400191505060405180910390fd5b896001600160a01b03166324f453d1868b6040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561182f57600080fd5b505af1158015611843573d6000803e3d6000fd5b505050505b87156118cf576002546040805163a9059cbb60e01b8152336004820152602481018b905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156118a257600080fd5b505af11580156118b6573d6000803e3d6000fd5b505050506040513d60208110156118cc57600080fd5b50505b896001600160a01b0316856001600160a01b03167f2ed7bcf2ff03098102c7003d7ce2a633e4b49b8198b07de5383cdf4c0ab9228b8360405180826001600160a01b0316815260200191505060405180910390a361192c856113b0565b611996576001600160a01b0385811660008181526008602090815260409182902080546001600160a01b031916948c1694851790558151938452905191927fefaf768237c22e140a862d5d375ad5c153479fac3f8bcf8b580a1651fd62c3ef929081900390910190a25b50505050505050505050565b6001600160a01b0382166119e75760405162461bcd60e51b815260040180806020018281038252602b815260200180612a61602b913960400191505060405180910390fd5b6003805460010190556000611a58826119fe612691565b6003546040805160208082019490945230606090811b828401526001600160601b03198b821b81166054840152908a901b166068820152607c8082019390935281518082039093018352609c019052805191012090612432565b9050836001600160a01b0316816001600160a01b031614611aaa5760405162461bcd60e51b815260040180806020018281038252602d81526020018061299a602d913960400191505060405180910390fd5b6001600160a01b0384811660008181526008602090815260409182902080546001600160a01b03191694881694851790558151938452905191927f768099735d1c322a05a5b9d7b76d99682a1833d3f7055e5ede25e0f2eeaa8c6d929081900390910190a250505050565b6001600160a01b038616611b5a5760405162461bcd60e51b815260040180806020018281038252602f8152602001806128d2602f913960400191505060405180910390fd5b600554851015611b9b5760405162461bcd60e51b815260040180806020018281038252603c81526020018061283d603c913960400191505060405180910390fd5b6000611ba68761109b565b9050611bb1816113d0565b15611bed5760405162461bcd60e51b81526004018080602001828103825260238152602001806129016023913960400191505060405180910390fd5b6000611c0c886001600160a01b0316611c07610d59610fe4565b612677565b600254604080516323b872dd60e01b81523360048201526001600160a01b038085166024830152604482018c905291519394509116916323b872dd916064808201926020929091908290030181600087803b158015611c6a57600080fd5b505af1158015611c7e573d6000803e3d6000fd5b505050506040513d6020811015611c9457600080fd5b5050600254600480546040805163699a088560e01b81526001600160a01b03948516938101939093528b8416602484015261ffff8a166044840152606483018990526084830188905290831660a4830152519183169163699a08859160c48082019260009290919082900301818387803b158015611d1157600080fd5b505af1158015611d25573d6000803e3d6000fd5b505050506040518060800160405280896001600160a01b03168152602001611d4b610da7565b815263fc0e3d90602084811b640100000000600160c01b0390811692909217604090811b828501529283018790526001600160a01b03808616600090815260078352849020855181546001600160a01b0319169216919091178155848201516001820155848401516002820180546001600160c01b03191663ffffffff9290961c91821691909416179390931790915560608301518051611df29260038501920190612695565b50905050806001600160a01b03167ff06d60cc2f463635fd237ad87f1d007af54840b82e7e4561707b1be63d91c260898560405180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611e6f578181015183820152602001611e57565b50505050905090810190601f168015611e9c5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25050505050505050565b6001546001600160a01b0316611ec957600080fd5b6002546001600160a01b0382811691161415611f165760405162461bcd60e51b81526004018080602001828103825260258152602001806128186025913960400191505060405180910390fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015611f6557600080fd5b505afa158015611f79573d6000803e3d6000fd5b505050506040513d6020811015611f8f57600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015611fea57600080fd5b505af1158015611ffe573d6000803e3d6000fd5b505050506040513d602081101561201457600080fd5b50505050565b6000546001600160a01b031633148061203c57506000546001600160a01b0316155b61207b576040805162461bcd60e51b8152602060048201819052602482015260008051602061297a833981519152604482015290519081900360640190fd5b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156120c657600080fd5b505afa1580156120da573d6000803e3d6000fd5b505050506040513d60208110156120f057600080fd5b50519050806121305760405162461bcd60e51b81526004018080602001828103825260268152602001806129ee6026913960400191505060405180910390fd5b6002546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015611fea57600080fd5b6001600160a01b03811660009081526007602052604081206001015481906121b190610d5990610d1b565b8051602091820120604080516001600160601b0319606089811b82168387015288901b16603482015281516028818303018152604890910190915280519201919091209091506114308183612320565b6000546001600160a01b031633148061222357506000546001600160a01b0316155b612262576040805162461bcd60e51b8152602060048201819052602482015260008051602061297a833981519152604482015290519081900360640190fd5b6001600160a01b0381166122a75760405162461bcd60e51b81526004018080602001828103825260268152602001806127c86026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031690565b6002546001600160a01b031681565b604080516001600160f81b03196020808301919091523060601b60218301526035820194909452605580820193909352815180820390930183526075019052805191012090565b3b151590565b6000612378826113d0565b6123b35760405162461bcd60e51b81526004018080602001828103825260268152602001806127376026913960400191505060405180910390fd5b6000826001600160a01b0316634e69d5606040518163ffffffff1660e01b815260040160206040518083038186803b1580156123ee57600080fd5b505afa158015612402573d6000803e3d6000fd5b505050506040513d602081101561241857600080fd5b50519050600081600381111561242a57fe5b149392505050565b6000815160411461248a576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156124fb5760405162461bcd60e51b81526004018080602001828103825260228152602001806128796022913960400191505060405180910390fd5b8060ff16601b1415801561251357508060ff16601c14155b1561254f5760405162461bcd60e51b81526004018080602001828103825260228152602001806129246022913960400191505060405180910390fd5b600060018783868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156125ab573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612613576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9695505050505050565b6000828201838110156110c6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080838351602085016000f59050803b6110c657600080fd5b4690565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826126cb5760008555612711565b82601f106126e457805160ff1916838001178555612711565b82800160010185558215612711579182015b828111156127115782518255916020019190600101906126f6565b5061271d929150612721565b5090565b5b8082111561271d576000815560010161272256fe52656769737472793a206865726d6573206861766520746f206265207265676973746572656452656769737472793a20696d706c656d656e746174696f6e73206861766520746f20626520736d61727420636f6e74726163747352656769737472793a206865726d65732073686f756c642067657420617070726f76616c20746f207472616e7366657220746f6b656e734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737352656769737472793a2070726f7669646564206865726d65732068617320746f206265206163746976656e617469766520746f6b656e2066756e64732063616e2774206265207265636f766572656452656769737472793a206865726d6573206861766520746f207374616b65206174206c65617374206d696e696d616c207374616b6520616d6f756e7445434453413a20696e76616c6964207369676e6174757265202773272076616c75653d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf352656769737472793a206865726d6573206f70657261746f722063616e2774206265207a65726f206164647265737352656769737472793a206865726d657320616c7265616479207265676973746572656445434453413a20696e76616c6964207369676e6174757265202776272076616c756552656769737472793a206e6f7420656e6f756768742066756e647320696e206368616e6e656c20746f20636f76657220666565734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657252656769737472793a206861766520746f206265207369676e6564206279206964656e74697479206f776e657252656769737472793a2052656a656374696e672074782077697468206574686572732073656e74636f6c6c6563746564206665652063616e6e6f74206265206c657373207468616e207a65726f52656769737472793a2077726f6e67206964656e74697479207369676e617475726552656769737472793a2070726f7669646564206865726d6573206861766520746f2062652061637469766552656769737472793a2062656e65666963696172792063616e2774206265207a65726f2061646472657373a264697066735822122065a56b2874985480216ee64116126f463779bf46a87647e2b6a0be53b9a4c19964736f6c6343000704003352656769737472793a20696d706c656d656e746174696f6e73206861766520746f20626520736d61727420636f6e7472616374734f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572" +var RegistryBin = "0x608060405234801561001057600080fd5b50613641806100206000396000f3fe6080604052600436106102295760003560e01c8063acc831d011610123578063d16f38c8116100ab578063e617aaac1161006f578063e617aaac14610647578063f2fde38b14610667578063f58c5b6e14610687578063fc0c546a1461069c578063ff9935cb146106b15761024f565b8063d16f38c8146105a5578063d5929fe3146105ba578063df8de3e7146105da578063e0b6c323146105fa578063e3252537146106275761024f565b8063c957543b116100f2578063c957543b14610510578063c9b84d4d14610530578063cdd596e014610545578063cf10c96914610565578063d0171d79146105855761024f565b8063acc831d014610490578063add10dda146104b0578063bf1eb88a146104d0578063c3c5a547146104f05761024f565b80636332b080116101b157806385bff3411161017557806385bff341146103f95780638cfef547146104195780638da5cb5b146104395780639936a87b1461044e578063ab867213146104635761024f565b80636332b0801461039057806366cf5875146103a5578063692058c2146103ba5780636931b550146103cf5780637c671a21146103e45761024f565b806341ca71ab116101f857806341ca71ab146102e15780634787d09c1461030e5780634b6bd6be1461032e578063505a1b311461034e57806352631ab41461036e5761024f565b806304614e0b146102545780631de9db4014610276578063238e130a146102ac578063392e53cd146102cc5761024f565b3661024f5760405162461bcd60e51b815260040161024690613214565b60405180910390fd5b600080fd5b34801561026057600080fd5b5061027461026f36600461294f565b6106d1565b005b34801561028257600080fd5b506102966102913660046127ab565b610820565b6040516102a39190612e35565b60405180910390f35b3480156102b857600080fd5b506102746102c7366004612773565b6108c5565b3480156102d857600080fd5b50610296610995565b3480156102ed57600080fd5b506103016102fc366004612b6c565b6109a6565b6040516102a39190612d0b565b34801561031a57600080fd5b506102746103293660046127ab565b6109d7565b34801561033a57600080fd5b50610301610349366004612924565b610a35565b34801561035a57600080fd5b50610301610369366004612773565b610a69565b34801561037a57600080fd5b50610383610b1e565b6040516102a39190613495565b34801561039c57600080fd5b50610383610b24565b3480156103b157600080fd5b50610383610b2e565b3480156103c657600080fd5b50610301610b34565b3480156103db57600080fd5b50610274610b43565b3480156103f057600080fd5b50610301610b94565b34801561040557600080fd5b506102746104143660046127ab565b610bc9565b34801561042557600080fd5b50610301610434366004612b6c565b610d25565b34801561044557600080fd5b50610301610d57565b34801561045a57600080fd5b50610301610d66565b34801561046f57600080fd5b5061048361047e366004612773565b610d9e565b6040516102a39190612e40565b34801561049c57600080fd5b506103016104ab366004612773565b610e1e565b3480156104bc57600080fd5b506102746104cb3660046128bb565b610e49565b3480156104dc57600080fd5b506104836104eb366004612773565b610f4e565b3480156104fc57600080fd5b5061029661050b366004612773565b610ffc565b34801561051c57600080fd5b5061027461052b366004612b6c565b6110ac565b34801561053c57600080fd5b50610301611171565b34801561055157600080fd5b50610296610560366004612773565b611180565b34801561057157600080fd5b50610274610580366004612a12565b61126f565b34801561059157600080fd5b506102746105a036600461285b565b6114a2565b3480156105b157600080fd5b50610296611635565b3480156105c657600080fd5b506102746105d5366004612990565b611646565b3480156105e657600080fd5b506102746105f5366004612773565b61199f565b34801561060657600080fd5b5061061a610615366004612773565b611b05565b6040516102a39190613449565b34801561063357600080fd5b50610274610642366004612773565b611ca6565b34801561065357600080fd5b506103016106623660046127ab565b611e2e565b34801561067357600080fd5b50610274610682366004612773565b611e99565b34801561069357600080fd5b50610301611f9a565b3480156106a857600080fd5b50610301611fa9565b3480156106bd57600080fd5b506102746106cc3660046127e3565b611fb8565b6106da836120d6565b6106f65760405162461bcd60e51b81526004016102469061338a565b600061073e82610704612188565b30878760405160200161071a9493929190612c6b565b6040516020818303038152906040528051906020012061218c90919063ffffffff16565b90506001600160a01b0381166107665760405162461bcd60e51b81526004016102469061325b565b6002546001600160a01b03166370a082316107818387611e2e565b6040518263ffffffff1660e01b815260040161079d9190612d0b565b60206040518083038186803b1580156107b557600080fd5b505afa1580156107c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ed9190612b84565b83111561080c5760405162461bcd60e51b815260040161024690613116565b610819818560008661220c565b5050505050565b600061083461082f8484611e2e565b6123cf565b806108be5750600654604051633985eaab60e21b81526108be916001600160a01b03169063e617aaac9061086e9087908790600401612d5c565b60206040518083038186803b15801561088657600080fd5b505afa15801561089a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082f919061278f565b9392505050565b6000546001600160a01b03163314806108e757506000546001600160a01b0316155b610926576040805162461bcd60e51b815260206004820181905260248201526000805160206135ec833981519152604482015290519081900360640190fd5b6001600160a01b03811661093957600080fd5b6001546040516001600160a01b038084169216907fe1a66d77649cf0a57b9937073549f30f1c82bb865aaf066d2f299e37a62c6aad90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b0316151590565b6000600782815481106109b557fe5b60009182526020909120600290910201546001600160a01b031690505b919050565b6109e0816120d6565b6109fc5760405162461bcd60e51b81526004016102469061338a565b610a068282610820565b15610a235760405162461bcd60e51b815260040161024690612eed565b610a30828260008061220c565b505050565b600080610a4461047e84610d25565b80516020909101209050610a616001600160a01b038516826123d5565b949350505050565b6000610a73611635565b15610aff5760065460405163505a1b3160e01b81526001600160a01b039091169063505a1b3190610aa8908590600401612d0b565b60206040518083038186803b158015610ac057600080fd5b505afa158015610ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af8919061278f565b90506109d2565b506001600160a01b039081166000908152600960205260409020541690565b60035481565b6007546000190190565b60055481565b6004546001600160a01b031681565b6001546001600160a01b0316610b5857600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610b91573d6000803e3d6000fd5b50565b60006007610ba0610b24565b81548110610baa57fe5b60009182526020909120600290910201546001600160a01b0316905090565b6000546001600160a01b0316331480610beb57506000546001600160a01b0316155b610c2a576040805162461bcd60e51b815260206004820181905260248201526000805160206135ec833981519152604482015290519081900360640190fd5b610c32610995565b610c4e5760405162461bcd60e51b81526004016102469061316a565b610c57826123cf565b8015610c675750610c67816123cf565b610c835760405162461bcd60e51b815260040161024690612e99565b604080518082019091526001600160a01b0392831681529082166020820190815260078054600181018255600091909152915160029092027fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688810180549385166001600160a01b031994851617905590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6899091018054919093169116179055565b600060078281548110610d3457fe5b60009182526020909120600290910201600101546001600160a01b031692915050565b6000546001600160a01b031690565b60006007610d72610b24565b81548110610d7c57fe5b60009182526020909120600160029092020101546001600160a01b0316905090565b60606000604051806060016040528060378152602001613593603791399050606083901b60005b60148160ff161015610e1557818160ff1660148110610de057fe5b1a60f81b838260140160ff1681518110610df657fe5b60200101906001600160f81b031916908160001a905350600101610dc5565b50909392505050565b600080610e2c61047e610d66565b805160209091012090506108be6001600160a01b038416826123d5565b610e52836120d6565b610e6e5760405162461bcd60e51b815260040161024690612fa8565b6003805460018101909155604051600091610e9891849161071a9130918991899190602001612bc8565b6001600160a01b03808616600090815260086020526040902054919250808316911614610ed75760405162461bcd60e51b8152600401610246906133d5565b6001600160a01b03841660009081526008602090815260409091208451610f06926003909201918601906125ff565b50836001600160a01b03167fd8c638c85547b8717e0d5ca292cff6dbe8fc02fa6e6863a047971c39511643c784604051610f409190612e40565b60405180910390a250505050565b6001600160a01b03811660009081526008602090815260409182902060030180548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845260609392830182828015610ff05780601f10610fc557610100808354040283529160200191610ff0565b820191906000526020600020905b815481529060010190602001808311610fd357829003601f168201915b50505050509050919050565b6000611006611635565b1561108b5760065460405163c3c5a54760e01b81526001600160a01b039091169063c3c5a5479061103b908590600401612d0b565b60206040518083038186803b15801561105357600080fd5b505afa158015611067573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af89190612a86565b506001600160a01b0390811660009081526009602052604090205416151590565b6000546001600160a01b03163314806110ce57506000546001600160a01b0316155b61110d576040805162461bcd60e51b815260206004820181905260248201526000805160206135ec833981519152604482015290519081900360640190fd5b611115610995565b6111315760405162461bcd60e51b815260040161024690612f3e565b60058190556040517f645a9c74d34a0b1095b113252ad5e9afa0373f15b4b21760fb3a24b4b9d1ec3090611166908390613495565b60405180910390a150565b6006546001600160a01b031681565b6001600160a01b038082166000908152600860205260408120805460019091015491921690826111b08383610a35565b9050846001600160a01b0316816001600160a01b0316146111d757600093505050506109d2565b6111e0816123cf565b80611266575060065460405163066eacb760e51b81526001600160a01b039091169063cdd596e090611216908890600401612d0b565b60206040518083038186803b15801561122e57600080fd5b505afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112669190612a86565b95945050505050565b611278856120d6565b6112945760405162461bcd60e51b81526004016102469061338a565b60006112bc826112a2612188565b308989898960405160200161071a96959493929190612c98565b90506001600160a01b0381166112e45760405162461bcd60e51b815260040161024690613348565b60006112f08686612416565b6002549091506001600160a01b03166370a0823161130e848a611e2e565b6040518263ffffffff1660e01b815260040161132a9190612d0b565b60206040518083038186803b15801561134257600080fd5b505afa158015611356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137a9190612b84565b8111156113995760405162461bcd60e51b815260040161024690613116565b6113a58288868461220c565b50851561140d576040516324f453d160e01b81526001600160a01b038816906324f453d1906113da9085908a90600401612d43565b600060405180830381600087803b1580156113f457600080fd5b505af1158015611408573d6000803e3d6000fd5b505050505b84156114995760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906114459033908990600401612d43565b602060405180830381600087803b15801561145f57600080fd5b505af1158015611473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114979190612a86565b505b50505050505050565b6001600160a01b0382166114c85760405162461bcd60e51b8152600401610246906133fe565b6114d0611635565b156115405760065460405163d0171d7960e01b81526001600160a01b039091169063d0171d799061150990869086908690600401612da9565b600060405180830381600087803b15801561152357600080fd5b505af1158015611537573d6000803e3d6000fd5b50505050610a30565b6003805460010190556000611553611635565b61155d573061156a565b6006546001600160a01b03165b905060006115938361157a612188565b60035460405161071a929187918b918b91602001612cd6565b9050846001600160a01b0316816001600160a01b0316146115c65760405162461bcd60e51b8152600401610246906131c7565b6001600160a01b038581166000818152600960205260409081902080546001600160a01b0319169388169390931790925590517f768099735d1c322a05a5b9d7b76d99682a1833d3f7055e5ede25e0f2eeaa8c6d90611626908790612d0b565b60405180910390a25050505050565b6006546001600160a01b0316151590565b61164e610995565b61166a5760405162461bcd60e51b8152600401610246906132a5565b6001600160a01b0386166116905760405162461bcd60e51b81526004016102469061304f565b6005548510156116b25760405162461bcd60e51b815260040161024690612ff2565b60006116bd87610e1e565b90506116c881611180565b156116e55760405162461bcd60e51b81526004016102469061309e565b6000611704886001600160a01b03166116ff61047e610d66565b612470565b6002546040516323b872dd60e01b81529192506001600160a01b0316906323b872dd9061173990339085908c90600401612d1f565b602060405180830381600087803b15801561175357600080fd5b505af1158015611767573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178b9190612a86565b506002546004805460405163699a088560e01b81526001600160a01b038086169463699a0885946117cd94918316938f938e938e938e93919092169101612dd5565b600060405180830381600087803b1580156117e757600080fd5b505af11580156117fb573d6000803e3d6000fd5b505050506040518060800160405280896001600160a01b03168152602001611821610b24565b815263fc0e3d90602084811b640100000000600160c01b0390811692909217604090811b828501529283018790526001600160a01b03868116600090815260088352849020855181546001600160a01b0319169216919091178155848201516001820155848401516002820180546001600160c01b03191663ffffffff9290961c918216919094161793909317909155606083015180516118c892600385019201906125ff565b505060025460405163095ea7b360e01b81526001600160a01b03909116915063095ea7b3906118ff90859060001990600401612d43565b602060405180830381600087803b15801561191957600080fd5b505af115801561192d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119519190612a86565b50816001600160a01b03167ff06d60cc2f463635fd237ad87f1d007af54840b82e7e4561707b1be63d91c260898560405161198d929190612e11565b60405180910390a25050505050505050565b6001546001600160a01b03166119b457600080fd5b6002546001600160a01b0382811691161415611a015760405162461bcd60e51b815260040180806020018281038252602581526020018061354c6025913960400191505060405180910390fd5b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015611a5057600080fd5b505afa158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015611ad557600080fd5b505af1158015611ae9573d6000803e3d6000fd5b505050506040513d6020811015611aff57600080fd5b50505050565b611b0d61268b565b611b1682611180565b80611b265750611b24611635565b155b611bb35760065460405163e0b6c32360e01b81526001600160a01b039091169063e0b6c32390611b5a908590600401612d0b565b60006040518083038186803b158015611b7257600080fd5b505afa158015611b86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611bae9190810190612ac5565b611ca0565b6001600160a01b038281166000908152600860209081526040918290208251608081018452815490941684526001808201548584015260028083015463ffffffff8116640100000000600160c01b0390911617851b8686015260038301805486516101009482161594909402600019011691909104601f810185900485028301850190955284825291936060860193919291830182828015611c965780601f10611c6b57610100808354040283529160200191611c96565b820191906000526020600020905b815481529060010190602001808311611c7957829003601f168201915b5050505050815250505b92915050565b6000546001600160a01b0316331480611cc857506000546001600160a01b0316155b611d07576040805162461bcd60e51b815260206004820181905260248201526000805160206135ec833981519152604482015290519081900360640190fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d38903090600401612d0b565b60206040518083038186803b158015611d5057600080fd5b505afa158015611d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d889190612b84565b905060008111611daa5760405162461bcd60e51b815260040161024690613302565b60025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611ddc9085908590600401612d43565b602060405180830381600087803b158015611df657600080fd5b505af1158015611e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a309190612a86565b6001600160a01b0381166000908152600860205260408120600101548190611e599061047e906109a6565b80519060200120905060008484604051602001611e77929190612c15565b60405160208183030381529060405280519060200120905061126681836123d5565b6000546001600160a01b0316331480611ebb57506000546001600160a01b0316155b611efa576040805162461bcd60e51b815260206004820181905260248201526000805160206135ec833981519152604482015290519081900360640190fd5b6001600160a01b038116611f3f5760405162461bcd60e51b81526004018080602001828103825260268152602001806135266026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031690565b6002546001600160a01b031681565b6000546001600160a01b0316331480611fda57506000546001600160a01b0316155b612019576040805162461bcd60e51b815260206004820181905260248201526000805160206135ec833981519152604482015290519081900360640190fd5b612021610995565b1561203e5760405162461bcd60e51b8152600401610246906130e1565b60058490556001600160a01b03861661205657600080fd5b600280546001600160a01b0319166001600160a01b0388811691909117909155851661208157600080fd5b600480546001600160a01b0319166001600160a01b0387161790556120a68383610bc9565b6120af33611e99565b600680546001600160a01b0319166001600160a01b03929092169190911790555050505050565b60006120e182611180565b6120fd5760405162461bcd60e51b815260040161024690612e53565b6000826001600160a01b0316634e69d5606040518163ffffffff1660e01b815260040160206040518083038186803b15801561213857600080fd5b505afa15801561214c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121709190612aa6565b9050600081600381111561218057fe5b149392505050565b4690565b600081516041146121e4576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a6122028682858561248a565b9695505050505050565b6000808585604051602001612222929190612c15565b604051602081830303815290604052805190602001209050600061227061047e60086000896001600160a01b03166001600160a01b03168152602001908152602001600020600101546109a6565b9050600061227e8383612470565b60025460048054604051637b809f7b60e11b81529394506001600160a01b038086169463f7013ef6946122bf9490831693909216918e918e918d9101612d76565b600060405180830381600087803b1580156122d957600080fd5b505af11580156122ed573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b03167f2ed7bcf2ff03098102c7003d7ce2a633e4b49b8198b07de5383cdf4c0ab9228b836040516123349190612d0b565b60405180910390a36001600160a01b03861661234e578095505b61235788610ffc565b6123c4576001600160a01b038881166000818152600960205260409081902080546001600160a01b031916938a169390931790925590517fefaf768237c22e140a862d5d375ad5c153479fac3f8bcf8b580a1651fd62c3ef906123bb908990612d0b565b60405180910390a25b979650505050505050565b3b151590565b6040516000906123f7906001600160f81b031990309086908690602001612c37565b60408051601f1981840301815291905280516020909101209392505050565b6000828201838110156108be576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080838351602085016000f59050803b6108be57600080fd5b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156124eb5760405162461bcd60e51b81526004018080602001828103825260228152602001806135716022913960400191505060405180910390fd5b8360ff16601b148061250057508360ff16601c145b61253b5760405162461bcd60e51b81526004018080602001828103825260228152602001806135ca6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612597573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611266576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612635576000855561267b565b82601f1061264e57805160ff191683800117855561267b565b8280016001018555821561267b579182015b8281111561267b578251825591602001919060010190612660565b506126879291506126b1565b5090565b604080516080810182526000808252602082018190529181019190915260608082015290565b5b8082111561268757600081556001016126b2565b600082601f8301126126d6578081fd5b81356126e96126e4826134c2565b61349e565b8181528460208386010111156126fd578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112612727578081fd5b81516127356126e4826134c2565b818152846020838601011115612749578283fd5b610a618260208301602087016134e4565b805167ffffffffffffffff19811681146109d257600080fd5b600060208284031215612784578081fd5b81356108be81613510565b6000602082840312156127a0578081fd5b81516108be81613510565b600080604083850312156127bd578081fd5b82356127c881613510565b915060208301356127d881613510565b809150509250929050565b60008060008060008060c087890312156127fb578182fd5b863561280681613510565b9550602087013561281681613510565b945060408701359350606087013561282d81613510565b9250608087013561283d81613510565b915060a087013561284d81613510565b809150509295509295509295565b60008060006060848603121561286f578283fd5b833561287a81613510565b9250602084013561288a81613510565b9150604084013567ffffffffffffffff8111156128a5578182fd5b6128b1868287016126c6565b9150509250925092565b6000806000606084860312156128cf578283fd5b83356128da81613510565b9250602084013567ffffffffffffffff808211156128f6578384fd5b612902878388016126c6565b93506040860135915080821115612917578283fd5b506128b1868287016126c6565b60008060408385031215612936578182fd5b823561294181613510565b946020939093013593505050565b600080600060608486031215612963578283fd5b833561296e81613510565b925060208401359150604084013567ffffffffffffffff8111156128a5578182fd5b60008060008060008060c087890312156129a8578384fd5b86356129b381613510565b955060208701359450604087013561ffff811681146129d0578485fd5b9350606087013592506080870135915060a087013567ffffffffffffffff8111156129f9578182fd5b612a0589828a016126c6565b9150509295509295509295565b600080600080600060a08688031215612a29578283fd5b8535612a3481613510565b945060208601359350604086013592506060860135612a5281613510565b9150608086013567ffffffffffffffff811115612a6d578182fd5b612a79888289016126c6565b9150509295509295909350565b600060208284031215612a97578081fd5b815180151581146108be578182fd5b600060208284031215612ab7578081fd5b8151600481106108be578182fd5b600060208284031215612ad6578081fd5b815167ffffffffffffffff80821115612aed578283fd5b9083019060808286031215612b00578283fd5b604051608081018181108382111715612b1557fe5b6040528251612b2381613510565b815260208381015190820152612b3b6040840161275a565b6040820152606083015182811115612b51578485fd5b612b5d87828601612717565b60608301525095945050505050565b600060208284031215612b7d578081fd5b5035919050565b600060208284031215612b95578081fd5b5051919050565b60008151808452612bb48160208601602086016134e4565b601f01601f19169290920160200192915050565b60006bffffffffffffffffffffffff19808760601b168352808660601b166014840152508351612bff8160288501602088016134e4565b6028920191820192909252604801949350505050565b6001600160601b0319606093841b811682529190921b16601482015260280190565b6001600160f81b031994909416845260609290921b6001600160601b03191660018401526015830152603582015260550190565b9384526001600160601b0319606093841b811660208601529190921b166034830152604882015260680190565b9586526001600160601b0319606095861b8116602088015293851b841660348701526048860192909252606885015290911b166088820152609c0190565b9485526001600160601b0319606094851b8116602087015292841b83166034860152921b166048830152605c820152607c0190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039586168152938516602085015291841660408401529092166060820152608081019190915260a00190565b6001600160a01b0384811682528316602082015260606040820181905260009061126690830184612b9c565b6001600160a01b039687168152948616602086015261ffff9390931660408501526060840191909152608083015290911660a082015260c00190565b6001600160a01b0383168152604060208201819052600090610a6190830184612b9c565b901515815260200190565b6000602082526108be6020830184612b9c565b60208082526026908201527f52656769737472793a206865726d6573206861766520746f20626520726567696040820152651cdd195c995960d21b606082015260800190565b60208082526034908201527f52656769737472793a20696d706c656d656e746174696f6e73206861766520746040820152736f20626520736d61727420636f6e74726163747360601b606082015260800190565b60208082526031908201527f52656769737472793a207375636820636f6e73756d6572206368616e6e656c206040820152701a5cc8185b1c9958591e481bdc195b9959607a1b606082015260800190565b60208082526044908201527f52656769737472793a206f6e6c7920696e697469616c697a656420726567697360408201527f7472792063616e20736574206e6577206d696e696d616c206865726d6573207360608201526374616b6560e01b608082015260a00190565b6020808252602a908201527f52656769737472793a2070726f7669646564206865726d65732068617320746f6040820152692062652061637469766560b01b606082015260800190565b6020808252603c908201527f52656769737472793a206865726d6573206861766520746f207374616b65206160408201527f74206c65617374206d696e696d616c207374616b6520616d6f756e7400000000606082015260800190565b6020808252602f908201527f52656769737472793a206865726d6573206f70657261746f722063616e27742060408201526e6265207a65726f206164647265737360881b606082015260800190565b60208082526023908201527f52656769737472793a206865726d657320616c726561647920726567697374656040820152621c995960ea1b606082015260800190565b6020808252818101527f52656769737472793a20697320616c726561647920696e697469616c697a6564604082015260600190565b60208082526034908201527f52656769737472793a206e6f7420656e6f756768742066756e647320696e206360408201527368616e6e656c20746f20636f766572206665657360601b606082015260800190565b6020808252603f908201527f52656769737472793a206f6e6c7920696e697469616c697a656420726567697360408201527f7472792063616e20736574206e657720696d706c656d656e746174696f6e7300606082015260800190565b6020808252602d908201527f52656769737472793a206861766520746f206265207369676e6564206279206960408201526c3232b73a34ba3c9037bbb732b960991b606082015260800190565b60208082526027908201527f52656769737472793a2052656a656374696e67207478207769746820657468656040820152661c9cc81cd95b9d60ca1b606082015260800190565b6020808252602a908201527f52656769737472793a2077726f6e67206368616e6e656c206f70656e696e6967604082015269207369676e617475726560b01b606082015260800190565b60208082526039908201527f52656769737472793a206f6e6c7920696e697469616c697a656420726567697360408201527f7472792063616e207265676973746572206865726d6573657300000000000000606082015260800190565b60208082526026908201527f636f6c6c6563746564206665652063616e6e6f74206265206c657373207468616040820152656e207a65726f60d01b606082015260800190565b60208082526022908201527f52656769737472793a2077726f6e67206964656e74697479207369676e617475604082015261726560f01b606082015260800190565b6020808252602b908201527f52656769737472793a2070726f7669646564206865726d65732068617665207460408201526a6f2062652061637469766560a81b606082015260800190565b6020808252600f908201526e77726f6e67207369676e617475726560881b604082015260600190565b6020808252602b908201527f52656769737472793a2062656e65666963696172792063616e2774206265207a60408201526a65726f206164647265737360a81b606082015260800190565b60006020825260018060a01b0383511660208301526020830151604083015267ffffffffffffffff1960408401511660608301526060830151608080840152610a6160a0840182612b9c565b90815260200190565b60405181810167ffffffffffffffff811182821017156134ba57fe5b604052919050565b600067ffffffffffffffff8211156134d657fe5b50601f01601f191660200190565b60005b838110156134ff5781810151838201526020016134e7565b83811115611aff5750506000910152565b6001600160a01b0381168114610b9157600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573736e617469766520746f6b656e2066756e64732063616e2774206265207265636f766572656445434453413a20696e76616c6964207369676e6174757265202773272076616c75653d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf345434453413a20696e76616c6964207369676e6174757265202776272076616c75654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220d6b6fd7b89342653d4f0a5398ac841d8882a51fe12ceecdf5947ca1665af609764736f6c63430007060033" // DeployRegistry deploys a new Ethereum contract, binding an instance of Registry to it. -func DeployRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, _tokenAddress common.Address, _dexAddress common.Address, _minimalHermesStake *big.Int, _channelImplementation common.Address, _hermesImplementation common.Address) (common.Address, *types.Transaction, *Registry, error) { +func DeployRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Registry, error) { parsed, err := abi.JSON(strings.NewReader(RegistryABI)) if err != nil { return common.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(RegistryBin), backend, _tokenAddress, _dexAddress, _minimalHermesStake, _channelImplementation, _hermesImplementation) + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(RegistryBin), backend) if err != nil { return common.Address{}, nil, nil, err } @@ -360,6 +368,32 @@ func (_Registry *RegistryCallerSession) GetFundsDestination() (common.Address, e return _Registry.Contract.GetFundsDestination(&_Registry.CallOpts) } +// GetHermes is a free data retrieval call binding the contract method 0xe0b6c323. +// +// Solidity: function getHermes(address _hermesId) view returns((address,uint256,function,bytes)) +func (_Registry *RegistryCaller) GetHermes(opts *bind.CallOpts, _hermesId common.Address) (RegistryHermes, error) { + var ( + ret0 = new(RegistryHermes) + ) + out := ret0 + err := _Registry.contract.Call(opts, out, "getHermes", _hermesId) + return *ret0, err +} + +// GetHermes is a free data retrieval call binding the contract method 0xe0b6c323. +// +// Solidity: function getHermes(address _hermesId) view returns((address,uint256,function,bytes)) +func (_Registry *RegistrySession) GetHermes(_hermesId common.Address) (RegistryHermes, error) { + return _Registry.Contract.GetHermes(&_Registry.CallOpts, _hermesId) +} + +// GetHermes is a free data retrieval call binding the contract method 0xe0b6c323. +// +// Solidity: function getHermes(address _hermesId) view returns((address,uint256,function,bytes)) +func (_Registry *RegistryCallerSession) GetHermes(_hermesId common.Address) (RegistryHermes, error) { + return _Registry.Contract.GetHermes(&_Registry.CallOpts, _hermesId) +} + // GetHermesAddress is a free data retrieval call binding the contract method 0x4b6bd6be. // // Solidity: function getHermesAddress(address _hermesOperator, uint256 _implVer) view returns(address) @@ -542,74 +576,56 @@ func (_Registry *RegistryCallerSession) GetProxyCode(_implementation common.Addr return _Registry.Contract.GetProxyCode(&_Registry.CallOpts, _implementation) } -// HasParentRegistry is a free data retrieval call binding the contract method 0x332ff7bd. +// HasParentRegistry is a free data retrieval call binding the contract method 0xd16f38c8. // -// Solidity: function hasParentRegistry(address ) pure returns(bool) -func (_Registry *RegistryCaller) HasParentRegistry(opts *bind.CallOpts, arg0 common.Address) (bool, error) { +// Solidity: function hasParentRegistry() view returns(bool) +func (_Registry *RegistryCaller) HasParentRegistry(opts *bind.CallOpts) (bool, error) { var ( ret0 = new(bool) ) out := ret0 - err := _Registry.contract.Call(opts, out, "hasParentRegistry", arg0) + err := _Registry.contract.Call(opts, out, "hasParentRegistry") return *ret0, err } -// HasParentRegistry is a free data retrieval call binding the contract method 0x332ff7bd. +// HasParentRegistry is a free data retrieval call binding the contract method 0xd16f38c8. // -// Solidity: function hasParentRegistry(address ) pure returns(bool) -func (_Registry *RegistrySession) HasParentRegistry(arg0 common.Address) (bool, error) { - return _Registry.Contract.HasParentRegistry(&_Registry.CallOpts, arg0) +// Solidity: function hasParentRegistry() view returns(bool) +func (_Registry *RegistrySession) HasParentRegistry() (bool, error) { + return _Registry.Contract.HasParentRegistry(&_Registry.CallOpts) } -// HasParentRegistry is a free data retrieval call binding the contract method 0x332ff7bd. +// HasParentRegistry is a free data retrieval call binding the contract method 0xd16f38c8. // -// Solidity: function hasParentRegistry(address ) pure returns(bool) -func (_Registry *RegistryCallerSession) HasParentRegistry(arg0 common.Address) (bool, error) { - return _Registry.Contract.HasParentRegistry(&_Registry.CallOpts, arg0) +// Solidity: function hasParentRegistry() view returns(bool) +func (_Registry *RegistryCallerSession) HasParentRegistry() (bool, error) { + return _Registry.Contract.HasParentRegistry(&_Registry.CallOpts) } -// Hermeses is a free data retrieval call binding the contract method 0x03fb422f. +// IsChannelOpened is a free data retrieval call binding the contract method 0x1de9db40. // -// Solidity: function hermeses(address ) view returns(address operator, uint256 implVer, function stake, bytes url) -func (_Registry *RegistryCaller) Hermeses(opts *bind.CallOpts, arg0 common.Address) (struct { - Operator common.Address - ImplVer *big.Int - Stake [24]byte - Url []byte -}, error) { - ret := new(struct { - Operator common.Address - ImplVer *big.Int - Stake [24]byte - Url []byte - }) - out := ret - err := _Registry.contract.Call(opts, out, "hermeses", arg0) - return *ret, err -} - -// Hermeses is a free data retrieval call binding the contract method 0x03fb422f. -// -// Solidity: function hermeses(address ) view returns(address operator, uint256 implVer, function stake, bytes url) -func (_Registry *RegistrySession) Hermeses(arg0 common.Address) (struct { - Operator common.Address - ImplVer *big.Int - Stake [24]byte - Url []byte -}, error) { - return _Registry.Contract.Hermeses(&_Registry.CallOpts, arg0) +// Solidity: function isChannelOpened(address _identity, address _hermesId) view returns(bool) +func (_Registry *RegistryCaller) IsChannelOpened(opts *bind.CallOpts, _identity common.Address, _hermesId common.Address) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Registry.contract.Call(opts, out, "isChannelOpened", _identity, _hermesId) + return *ret0, err } -// Hermeses is a free data retrieval call binding the contract method 0x03fb422f. +// IsChannelOpened is a free data retrieval call binding the contract method 0x1de9db40. // -// Solidity: function hermeses(address ) view returns(address operator, uint256 implVer, function stake, bytes url) -func (_Registry *RegistryCallerSession) Hermeses(arg0 common.Address) (struct { - Operator common.Address - ImplVer *big.Int - Stake [24]byte - Url []byte -}, error) { - return _Registry.Contract.Hermeses(&_Registry.CallOpts, arg0) +// Solidity: function isChannelOpened(address _identity, address _hermesId) view returns(bool) +func (_Registry *RegistrySession) IsChannelOpened(_identity common.Address, _hermesId common.Address) (bool, error) { + return _Registry.Contract.IsChannelOpened(&_Registry.CallOpts, _identity, _hermesId) +} + +// IsChannelOpened is a free data retrieval call binding the contract method 0x1de9db40. +// +// Solidity: function isChannelOpened(address _identity, address _hermesId) view returns(bool) +func (_Registry *RegistryCallerSession) IsChannelOpened(_identity common.Address, _hermesId common.Address) (bool, error) { + return _Registry.Contract.IsChannelOpened(&_Registry.CallOpts, _identity, _hermesId) } // IsHermes is a free data retrieval call binding the contract method 0xcdd596e0. @@ -638,6 +654,32 @@ func (_Registry *RegistryCallerSession) IsHermes(_hermesId common.Address) (bool return _Registry.Contract.IsHermes(&_Registry.CallOpts, _hermesId) } +// IsInitialized is a free data retrieval call binding the contract method 0x392e53cd. +// +// Solidity: function isInitialized() view returns(bool) +func (_Registry *RegistryCaller) IsInitialized(opts *bind.CallOpts) (bool, error) { + var ( + ret0 = new(bool) + ) + out := ret0 + err := _Registry.contract.Call(opts, out, "isInitialized") + return *ret0, err +} + +// IsInitialized is a free data retrieval call binding the contract method 0x392e53cd. +// +// Solidity: function isInitialized() view returns(bool) +func (_Registry *RegistrySession) IsInitialized() (bool, error) { + return _Registry.Contract.IsInitialized(&_Registry.CallOpts) +} + +// IsInitialized is a free data retrieval call binding the contract method 0x392e53cd. +// +// Solidity: function isInitialized() view returns(bool) +func (_Registry *RegistryCallerSession) IsInitialized() (bool, error) { + return _Registry.Contract.IsInitialized(&_Registry.CallOpts) +} + // IsRegistered is a free data retrieval call binding the contract method 0xc3c5a547. // // Solidity: function isRegistered(address _identity) view returns(bool) @@ -742,6 +784,32 @@ func (_Registry *RegistryCallerSession) Owner() (common.Address, error) { return _Registry.Contract.Owner(&_Registry.CallOpts) } +// ParentRegistry is a free data retrieval call binding the contract method 0xc9b84d4d. +// +// Solidity: function parentRegistry() view returns(address) +func (_Registry *RegistryCaller) ParentRegistry(opts *bind.CallOpts) (common.Address, error) { + var ( + ret0 = new(common.Address) + ) + out := ret0 + err := _Registry.contract.Call(opts, out, "parentRegistry") + return *ret0, err +} + +// ParentRegistry is a free data retrieval call binding the contract method 0xc9b84d4d. +// +// Solidity: function parentRegistry() view returns(address) +func (_Registry *RegistrySession) ParentRegistry() (common.Address, error) { + return _Registry.Contract.ParentRegistry(&_Registry.CallOpts) +} + +// ParentRegistry is a free data retrieval call binding the contract method 0xc9b84d4d. +// +// Solidity: function parentRegistry() view returns(address) +func (_Registry *RegistryCallerSession) ParentRegistry() (common.Address, error) { + return _Registry.Contract.ParentRegistry(&_Registry.CallOpts) +} + // Token is a free data retrieval call binding the contract method 0xfc0c546a. // // Solidity: function token() view returns(address) @@ -810,6 +878,69 @@ func (_Registry *RegistryTransactorSession) ClaimTokens(_token common.Address) ( return _Registry.Contract.ClaimTokens(&_Registry.TransactOpts, _token) } +// Initialize is a paid mutator transaction binding the contract method 0xff9935cb. +// +// Solidity: function initialize(address _tokenAddress, address _dexAddress, uint256 _minimalHermesStake, address _channelImplementation, address _hermesImplementation, address _parentRegistry) returns() +func (_Registry *RegistryTransactor) Initialize(opts *bind.TransactOpts, _tokenAddress common.Address, _dexAddress common.Address, _minimalHermesStake *big.Int, _channelImplementation common.Address, _hermesImplementation common.Address, _parentRegistry common.Address) (*types.Transaction, error) { + return _Registry.contract.Transact(opts, "initialize", _tokenAddress, _dexAddress, _minimalHermesStake, _channelImplementation, _hermesImplementation, _parentRegistry) +} + +// Initialize is a paid mutator transaction binding the contract method 0xff9935cb. +// +// Solidity: function initialize(address _tokenAddress, address _dexAddress, uint256 _minimalHermesStake, address _channelImplementation, address _hermesImplementation, address _parentRegistry) returns() +func (_Registry *RegistrySession) Initialize(_tokenAddress common.Address, _dexAddress common.Address, _minimalHermesStake *big.Int, _channelImplementation common.Address, _hermesImplementation common.Address, _parentRegistry common.Address) (*types.Transaction, error) { + return _Registry.Contract.Initialize(&_Registry.TransactOpts, _tokenAddress, _dexAddress, _minimalHermesStake, _channelImplementation, _hermesImplementation, _parentRegistry) +} + +// Initialize is a paid mutator transaction binding the contract method 0xff9935cb. +// +// Solidity: function initialize(address _tokenAddress, address _dexAddress, uint256 _minimalHermesStake, address _channelImplementation, address _hermesImplementation, address _parentRegistry) returns() +func (_Registry *RegistryTransactorSession) Initialize(_tokenAddress common.Address, _dexAddress common.Address, _minimalHermesStake *big.Int, _channelImplementation common.Address, _hermesImplementation common.Address, _parentRegistry common.Address) (*types.Transaction, error) { + return _Registry.Contract.Initialize(&_Registry.TransactOpts, _tokenAddress, _dexAddress, _minimalHermesStake, _channelImplementation, _hermesImplementation, _parentRegistry) +} + +// OpenConsumerChannel is a paid mutator transaction binding the contract method 0x04614e0b. +// +// Solidity: function openConsumerChannel(address _hermesId, uint256 _transactorFee, bytes _signature) returns() +func (_Registry *RegistryTransactor) OpenConsumerChannel(opts *bind.TransactOpts, _hermesId common.Address, _transactorFee *big.Int, _signature []byte) (*types.Transaction, error) { + return _Registry.contract.Transact(opts, "openConsumerChannel", _hermesId, _transactorFee, _signature) +} + +// OpenConsumerChannel is a paid mutator transaction binding the contract method 0x04614e0b. +// +// Solidity: function openConsumerChannel(address _hermesId, uint256 _transactorFee, bytes _signature) returns() +func (_Registry *RegistrySession) OpenConsumerChannel(_hermesId common.Address, _transactorFee *big.Int, _signature []byte) (*types.Transaction, error) { + return _Registry.Contract.OpenConsumerChannel(&_Registry.TransactOpts, _hermesId, _transactorFee, _signature) +} + +// OpenConsumerChannel is a paid mutator transaction binding the contract method 0x04614e0b. +// +// Solidity: function openConsumerChannel(address _hermesId, uint256 _transactorFee, bytes _signature) returns() +func (_Registry *RegistryTransactorSession) OpenConsumerChannel(_hermesId common.Address, _transactorFee *big.Int, _signature []byte) (*types.Transaction, error) { + return _Registry.Contract.OpenConsumerChannel(&_Registry.TransactOpts, _hermesId, _transactorFee, _signature) +} + +// OpenConsumerChannel0 is a paid mutator transaction binding the contract method 0x4787d09c. +// +// Solidity: function openConsumerChannel(address _identity, address _hermesId) returns() +func (_Registry *RegistryTransactor) OpenConsumerChannel0(opts *bind.TransactOpts, _identity common.Address, _hermesId common.Address) (*types.Transaction, error) { + return _Registry.contract.Transact(opts, "openConsumerChannel0", _identity, _hermesId) +} + +// OpenConsumerChannel0 is a paid mutator transaction binding the contract method 0x4787d09c. +// +// Solidity: function openConsumerChannel(address _identity, address _hermesId) returns() +func (_Registry *RegistrySession) OpenConsumerChannel0(_identity common.Address, _hermesId common.Address) (*types.Transaction, error) { + return _Registry.Contract.OpenConsumerChannel0(&_Registry.TransactOpts, _identity, _hermesId) +} + +// OpenConsumerChannel0 is a paid mutator transaction binding the contract method 0x4787d09c. +// +// Solidity: function openConsumerChannel(address _identity, address _hermesId) returns() +func (_Registry *RegistryTransactorSession) OpenConsumerChannel0(_identity common.Address, _hermesId common.Address) (*types.Transaction, error) { + return _Registry.Contract.OpenConsumerChannel0(&_Registry.TransactOpts, _identity, _hermesId) +} + // RegisterHermes is a paid mutator transaction binding the contract method 0xd5929fe3. // // Solidity: function registerHermes(address _hermesOperator, uint256 _hermesStake, uint16 _hermesFee, uint256 _minChannelStake, uint256 _maxChannelStake, bytes _url) returns() @@ -915,6 +1046,27 @@ func (_Registry *RegistryTransactorSession) SetImplementations(_newChannelImplAd return _Registry.Contract.SetImplementations(&_Registry.TransactOpts, _newChannelImplAddress, _newHermesImplAddress) } +// SetMinimalHermesStake is a paid mutator transaction binding the contract method 0xc957543b. +// +// Solidity: function setMinimalHermesStake(uint256 _newMinimalStake) returns() +func (_Registry *RegistryTransactor) SetMinimalHermesStake(opts *bind.TransactOpts, _newMinimalStake *big.Int) (*types.Transaction, error) { + return _Registry.contract.Transact(opts, "setMinimalHermesStake", _newMinimalStake) +} + +// SetMinimalHermesStake is a paid mutator transaction binding the contract method 0xc957543b. +// +// Solidity: function setMinimalHermesStake(uint256 _newMinimalStake) returns() +func (_Registry *RegistrySession) SetMinimalHermesStake(_newMinimalStake *big.Int) (*types.Transaction, error) { + return _Registry.Contract.SetMinimalHermesStake(&_Registry.TransactOpts, _newMinimalStake) +} + +// SetMinimalHermesStake is a paid mutator transaction binding the contract method 0xc957543b. +// +// Solidity: function setMinimalHermesStake(uint256 _newMinimalStake) returns() +func (_Registry *RegistryTransactorSession) SetMinimalHermesStake(_newMinimalStake *big.Int) (*types.Transaction, error) { + return _Registry.Contract.SetMinimalHermesStake(&_Registry.TransactOpts, _newMinimalStake) +} + // TransferCollectedFeeTo is a paid mutator transaction binding the contract method 0xe3252537. // // Solidity: function transferCollectedFeeTo(address _beneficiary) returns() @@ -1592,6 +1744,139 @@ func (_Registry *RegistryFilterer) ParseHermesURLUpdated(log types.Log) (*Regist return event, nil } +// RegistryMinimalHermesStakeChangedIterator is returned from FilterMinimalHermesStakeChanged and is used to iterate over the raw logs and unpacked data for MinimalHermesStakeChanged events raised by the Registry contract. +type RegistryMinimalHermesStakeChangedIterator struct { + Event *RegistryMinimalHermesStakeChanged // 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 *RegistryMinimalHermesStakeChangedIterator) 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(RegistryMinimalHermesStakeChanged) + 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(RegistryMinimalHermesStakeChanged) + 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 *RegistryMinimalHermesStakeChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RegistryMinimalHermesStakeChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RegistryMinimalHermesStakeChanged represents a MinimalHermesStakeChanged event raised by the Registry contract. +type RegistryMinimalHermesStakeChanged struct { + NewMinimalStake *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMinimalHermesStakeChanged is a free log retrieval operation binding the contract event 0x645a9c74d34a0b1095b113252ad5e9afa0373f15b4b21760fb3a24b4b9d1ec30. +// +// Solidity: event MinimalHermesStakeChanged(uint256 newMinimalStake) +func (_Registry *RegistryFilterer) FilterMinimalHermesStakeChanged(opts *bind.FilterOpts) (*RegistryMinimalHermesStakeChangedIterator, error) { + + logs, sub, err := _Registry.contract.FilterLogs(opts, "MinimalHermesStakeChanged") + if err != nil { + return nil, err + } + return &RegistryMinimalHermesStakeChangedIterator{contract: _Registry.contract, event: "MinimalHermesStakeChanged", logs: logs, sub: sub}, nil +} + +// WatchMinimalHermesStakeChanged is a free log subscription operation binding the contract event 0x645a9c74d34a0b1095b113252ad5e9afa0373f15b4b21760fb3a24b4b9d1ec30. +// +// Solidity: event MinimalHermesStakeChanged(uint256 newMinimalStake) +func (_Registry *RegistryFilterer) WatchMinimalHermesStakeChanged(opts *bind.WatchOpts, sink chan<- *RegistryMinimalHermesStakeChanged) (event.Subscription, error) { + + logs, sub, err := _Registry.contract.WatchLogs(opts, "MinimalHermesStakeChanged") + 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(RegistryMinimalHermesStakeChanged) + if err := _Registry.contract.UnpackLog(event, "MinimalHermesStakeChanged", 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 +} + +// ParseMinimalHermesStakeChanged is a log parse operation binding the contract event 0x645a9c74d34a0b1095b113252ad5e9afa0373f15b4b21760fb3a24b4b9d1ec30. +// +// Solidity: event MinimalHermesStakeChanged(uint256 newMinimalStake) +func (_Registry *RegistryFilterer) ParseMinimalHermesStakeChanged(log types.Log) (*RegistryMinimalHermesStakeChanged, error) { + event := new(RegistryMinimalHermesStakeChanged) + if err := _Registry.contract.UnpackLog(event, "MinimalHermesStakeChanged", log); err != nil { + return nil, err + } + return event, nil +} + // RegistryOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Registry contract. type RegistryOwnershipTransferredIterator struct { Event *RegistryOwnershipTransferred // Event containing the contract specifics and raw log diff --git a/client/client.go b/client/client.go index cc2284d..2ef8676 100644 --- a/client/client.go +++ b/client/client.go @@ -850,7 +850,7 @@ func (bc *Blockchain) GetHermes(registryID, hermesID common.Address) (Hermes, er ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout) defer cancel() - status, err := caller.Hermeses(&bind.CallOpts{ + status, err := caller.GetHermes(&bind.CallOpts{ Context: ctx, }, hermesID) if err != nil { diff --git a/gen.go b/gen.go index 6d2e4f8..c41194f 100644 --- a/gen.go +++ b/gen.go @@ -23,4 +23,4 @@ package bindings * looked up in migration script here: https://github.com/mysteriumnetwork/payments-smart-contracts/blob/master/migrations/2_deploy_contracts.js */ -//go:generate go run bindings/abi/abigen.go --githubrepo=mysteriumnetwork/payments-smart-contracts -githubrelease=v1.0.0 --contracts=MystToken.json,ChannelImplementation.json,Registry.json,HermesImplementation.json --out=bindings --pkg=bindings +//go:generate go run bindings/abi/abigen.go --githubrepo=mysteriumnetwork/payments-smart-contracts -githubrelease=v2.0.0 --contracts=MystToken.json,ChannelImplementation.json,Registry.json,HermesImplementation.json --out=bindings --pkg=bindings From 34cd65a08c922cd7357e17d7be849654383ec567 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Wed, 31 Mar 2021 14:15:04 +0300 Subject: [PATCH 02/14] Add IsChannelOpened to client, remove retryable client --- client/client.go | 60 ++++ client/multichain_client.go | 9 + client/retryable_client.go | 687 ------------------------------------ client/with_dry_runs.go | 4 + 4 files changed, 73 insertions(+), 687 deletions(-) delete mode 100644 client/retryable_client.go diff --git a/client/client.go b/client/client.go index 2ef8676..8800341 100644 --- a/client/client.go +++ b/client/client.go @@ -79,6 +79,52 @@ func NewBlockchainWithCustomNonceTracker(ethClient ethClientGetter, timeout time } } +type BC interface { + GetHermesFee(hermesAddress common.Address) (uint16, error) + CalculateHermesFee(hermesAddress common.Address, value *big.Int) (*big.Int, error) + IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck common.Address) (bool, error) + GetProviderChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) + IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) + SubscribeToPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) + GetMystBalance(mystSCAddress, address common.Address) (*big.Int, error) + SubscribeToConsumerBalanceEvent(channel, mystSCAddress common.Address, timeout time.Duration) (chan *bindings.MystTokenTransfer, func(), error) + RegisterIdentity(rr RegistrationRequest) (*types.Transaction, error) + TransferMyst(req TransferRequest) (tx *types.Transaction, err error) + IsHermesRegistered(registryAddress, acccountantID common.Address) (bool, error) + GetHermesOperator(hermesID common.Address) (common.Address, error) + SettleAndRebalance(req SettleAndRebalanceRequest) (*types.Transaction, error) + SettleWithBeneficiary(req SettleWithBeneficiaryRequest) (*types.Transaction, error) + GetConsumerChannelsHermes(channelAddress common.Address) (ConsumersHermes, error) + GetConsumerChannelOperator(channelAddress common.Address) (common.Address, error) + GetProviderChannelByID(acc common.Address, chID []byte) (ProviderChannel, error) + SubscribeToIdentityRegistrationEvents(registryAddress common.Address) (sink chan *bindings.RegistryRegisteredIdentity, cancel func(), err error) + SubscribeToConsumerChannelBalanceUpdate(mystSCAddress common.Address, channelAddresses []common.Address) (sink chan *bindings.MystTokenTransfer, cancel func(), err error) + SettlePromise(req SettleRequest) (*types.Transaction, error) + SubscribeToPromiseSettledEventByChannelID(hermesID common.Address, providerAddresses [][32]byte) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) + SubscribeToMystTokenTransfers(mystSCAddress common.Address) (chan *bindings.MystTokenTransfer, func(), error) + NetworkID() (*big.Int, error) + GetConsumerChannel(addr common.Address, mystSCAddress common.Address) (ConsumerChannel, error) + GetEthBalance(address common.Address) (*big.Int, error) + TransferEth(etr EthTransferRequest) (*types.Transaction, error) + GetHermessAvailableBalance(hermesAddress common.Address) (*big.Int, error) + DecreaseProviderStake(req DecreaseProviderStakeRequest) (*types.Transaction, error) + SettleIntoStake(req SettleIntoStakeRequest) (*types.Transaction, error) + IncreaseProviderStake(req ProviderStakeIncreaseRequest) (*types.Transaction, error) + TransactionReceipt(hash common.Hash) (*types.Receipt, error) + GetHermesURL(registryID, hermesID common.Address) (string, error) + GetStakeThresholds(hermesID common.Address) (min, max *big.Int, err error) + GetBeneficiary(registryAddress, identity common.Address) (common.Address, error) + SuggestGasPrice() (*big.Int, error) + FilterLogs(q ethereum.FilterQuery) ([]types.Log, error) + HeaderByNumber(number *big.Int) (*types.Header, error) + GetLastRegistryNonce(registry common.Address) (*big.Int, error) + SendTransaction(tx *types.Transaction) error + IsHermesActive(hermesID common.Address) (bool, error) + GetHermes(registryID, hermesID common.Address) (Hermes, error) + GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) + IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) +} + // GetHermesFee fetches the hermes fee from blockchain func (bc *Blockchain) GetHermesFee(hermesAddress common.Address) (uint16, error) { caller, err := bindings.NewHermesImplementationCaller(hermesAddress, bc.ethClient.Client()) @@ -880,6 +926,20 @@ func (bc *Blockchain) GetChannelImplementationByVersion(registryID common.Addres }, version) } +func (bc *Blockchain) IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) { + caller, err := bindings.NewRegistryCaller(registryID, bc.ethClient.Client()) + if err != nil { + return false, fmt.Errorf("could not create new registry caller %w", err) + } + + ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout) + defer cancel() + + return caller.IsChannelOpened(&bind.CallOpts{ + Context: ctx, + }, identity, hermesID) +} + // SubscribeToPromiseSettledEventByChannelID subscribes to promise settled events func (bc *Blockchain) SubscribeToPromiseSettledEventByChannelID(hermesID common.Address, providerAddresses [][32]byte) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) { caller, err := bindings.NewHermesImplementationFilterer(hermesID, bc.ethClient.Client()) diff --git a/client/multichain_client.go b/client/multichain_client.go index 80c91e6..93e2e4a 100644 --- a/client/multichain_client.go +++ b/client/multichain_client.go @@ -386,6 +386,15 @@ func (mbc *MultichainBlockchainClient) GetChannelImplementationByVersion(chainID return bc.GetChannelImplementationByVersion(registryID, version) } +func (mbc *MultichainBlockchainClient) IsChannelOpened(chainID int64, registryID, identity, hermesID common.Address) (bool, error) { + bc, err := mbc.getClientByChain(chainID) + if err != nil { + return false, err + } + + return bc.IsChannelOpened(registryID, identity, hermesID) +} + // FilterLogs executes a filter query. func (mbc *MultichainBlockchainClient) FilterLogs(chainID int64, q ethereum.FilterQuery) ([]types.Log, error) { bc, err := mbc.getClientByChain(chainID) diff --git a/client/retryable_client.go b/client/retryable_client.go deleted file mode 100644 index 7a6fcb3..0000000 --- a/client/retryable_client.go +++ /dev/null @@ -1,687 +0,0 @@ -/* Mysterium network payment library. - * - * Copyright (C) 2020 BlockDev AG - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package client - -import ( - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/mysteriumnetwork/payments/bindings" - "github.com/pkg/errors" - "github.com/rs/zerolog/log" -) - -type BC interface { - GetHermesFee(hermesAddress common.Address) (uint16, error) - CalculateHermesFee(hermesAddress common.Address, value *big.Int) (*big.Int, error) - IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck common.Address) (bool, error) - GetProviderChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) - IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) - SubscribeToPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) - GetMystBalance(mystSCAddress, address common.Address) (*big.Int, error) - SubscribeToConsumerBalanceEvent(channel, mystSCAddress common.Address, timeout time.Duration) (chan *bindings.MystTokenTransfer, func(), error) - RegisterIdentity(rr RegistrationRequest) (*types.Transaction, error) - TransferMyst(req TransferRequest) (tx *types.Transaction, err error) - IsHermesRegistered(registryAddress, acccountantID common.Address) (bool, error) - GetHermesOperator(hermesID common.Address) (common.Address, error) - SettleAndRebalance(req SettleAndRebalanceRequest) (*types.Transaction, error) - SettleWithBeneficiary(req SettleWithBeneficiaryRequest) (*types.Transaction, error) - GetConsumerChannelsHermes(channelAddress common.Address) (ConsumersHermes, error) - GetConsumerChannelOperator(channelAddress common.Address) (common.Address, error) - GetProviderChannelByID(acc common.Address, chID []byte) (ProviderChannel, error) - SubscribeToIdentityRegistrationEvents(registryAddress common.Address) (sink chan *bindings.RegistryRegisteredIdentity, cancel func(), err error) - SubscribeToConsumerChannelBalanceUpdate(mystSCAddress common.Address, channelAddresses []common.Address) (sink chan *bindings.MystTokenTransfer, cancel func(), err error) - SettlePromise(req SettleRequest) (*types.Transaction, error) - SubscribeToPromiseSettledEventByChannelID(hermesID common.Address, providerAddresses [][32]byte) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) - SubscribeToMystTokenTransfers(mystSCAddress common.Address) (chan *bindings.MystTokenTransfer, func(), error) - NetworkID() (*big.Int, error) - GetConsumerChannel(addr common.Address, mystSCAddress common.Address) (ConsumerChannel, error) - GetEthBalance(address common.Address) (*big.Int, error) - TransferEth(etr EthTransferRequest) (*types.Transaction, error) - GetHermessAvailableBalance(hermesAddress common.Address) (*big.Int, error) - DecreaseProviderStake(req DecreaseProviderStakeRequest) (*types.Transaction, error) - SettleIntoStake(req SettleIntoStakeRequest) (*types.Transaction, error) - IncreaseProviderStake(req ProviderStakeIncreaseRequest) (*types.Transaction, error) - TransactionReceipt(hash common.Hash) (*types.Receipt, error) - GetHermesURL(registryID, hermesID common.Address) (string, error) - GetStakeThresholds(hermesID common.Address) (min, max *big.Int, err error) - GetBeneficiary(registryAddress, identity common.Address) (common.Address, error) - SuggestGasPrice() (*big.Int, error) - FilterLogs(q ethereum.FilterQuery) ([]types.Log, error) - HeaderByNumber(number *big.Int) (*types.Header, error) - GetLastRegistryNonce(registry common.Address) (*big.Int, error) - SendTransaction(tx *types.Transaction) error - IsHermesActive(hermesID common.Address) (bool, error) - GetHermes(registryID, hermesID common.Address) (Hermes, error) - GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) -} - -// BlockchainWithRetries takes in the plain blockchain implementation and exposes methods that will retry the underlying bc methods before giving up. -// This is required as the ethereum client will occasionally spit a TLS error if running for prolonged periods of time. -type BlockchainWithRetries struct { - delay time.Duration - maxRetries int - bc BC - stop chan struct{} - once sync.Once -} - -// ErrStopped represents an error when a call is interrupted -var ErrStopped = errors.New("call stopped") - -// NewBlockchainWithRetries returns a new instance of blockchain with retries -func NewBlockchainWithRetries(bc BC, delay time.Duration, maxRetries int) *BlockchainWithRetries { - return &BlockchainWithRetries{ - bc: bc, - delay: delay, - maxRetries: maxRetries, - } -} - -// FilterLogs executes a filter query. -func (bwr *BlockchainWithRetries) FilterLogs(q ethereum.FilterQuery) ([]types.Log, error) { - var res []types.Log - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.FilterLogs(q) - if err != nil { - return errors.Wrap(err, "could not filter logs") - } - res = r - return nil - }) - return res, err -} - -func (bwr *BlockchainWithRetries) GetLastRegistryNonce(registry common.Address) (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.GetLastRegistryNonce(registry) - if err != nil { - return errors.Wrap(err, "could not get registry nonce") - } - res = r - return nil - }) - return res, err -} - -// HeaderByNumber returns a block header from the current canonical chain. If number is -// nil, the latest known header is returned. -func (bwr *BlockchainWithRetries) HeaderByNumber(number *big.Int) (*types.Header, error) { - var res *types.Header - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.HeaderByNumber(number) - if err != nil { - return errors.Wrap(err, "could not get header by number") - } - res = r - return nil - }) - return res, err -} - -func (bwr *BlockchainWithRetries) SuggestGasPrice() (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.SuggestGasPrice() - if err != nil { - return errors.Wrap(err, "could not get gas price") - } - res = r - return nil - }) - return res, err -} - -func (bwr *BlockchainWithRetries) callWithRetry(f func() error) error { - for i := 1; i <= bwr.maxRetries; i++ { - err := f() - if err == nil { - return nil - } - if i == bwr.maxRetries { - return err - } - - log.Warn().Err(err).Msgf("retry %v of %v", i+1, bwr.maxRetries) - select { - case <-bwr.stop: - return ErrStopped - case <-time.After(bwr.delay): - } - } - return nil -} - -// SubscribeToMystTokenTransfers subscribes to myst token transfer events -func (bwr *BlockchainWithRetries) SubscribeToMystTokenTransfers(mystSCAddress common.Address) (chan *bindings.MystTokenTransfer, func(), error) { - var sink chan *bindings.MystTokenTransfer - var cancel func() - err := bwr.callWithRetry(func() error { - s, c, err := bwr.bc.SubscribeToMystTokenTransfers(mystSCAddress) - if err != nil { - return errors.Wrap(err, "could not subscribe to settlement events") - } - sink = s - cancel = c - return nil - }) - return sink, cancel, err -} - -// GetHermesFee fetches the hermes fee from blockchain -func (bwr *BlockchainWithRetries) GetHermesFee(hermesAddress common.Address) (uint16, error) { - var res uint16 - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.GetHermesFee(hermesAddress) - if err != nil { - return errors.Wrap(err, "could not get hermes fee") - } - res = r - return nil - }) - return res, err -} - -func (bwr *BlockchainWithRetries) GetBeneficiary(registryAddress, identity common.Address) (common.Address, error) { - var res common.Address - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.GetBeneficiary(registryAddress, identity) - if err != nil { - return errors.Wrap(err, "could not get beneficiary") - } - res = r - return nil - }) - return res, err -} - -// CalculateHermesFee fetches the hermes fee from blockchain -func (bwr *BlockchainWithRetries) CalculateHermesFee(hermesAddress common.Address, value *big.Int) (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.CalculateHermesFee(hermesAddress, value) - if err != nil { - return errors.Wrap(err, "could not calculate hermes fee") - } - res = r - return nil - }) - return res, err -} - -// IsRegisteredAsProvider checks if the provider is registered with the hermes properly -func (bwr *BlockchainWithRetries) IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck common.Address) (bool, error) { - var res bool - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck) - if err != nil { - return errors.Wrap(err, "could not check if registered as provider") - } - res = r - return nil - }) - return res, err -} - -// GetProviderChannel returns the provider channel -func (bwr *BlockchainWithRetries) GetProviderChannel(hermesAddress, addressToCheck common.Address, pending bool) (ProviderChannel, error) { - var res ProviderChannel - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.GetProviderChannel(hermesAddress, addressToCheck, pending) - if err != nil { - return errors.Wrap(err, "could not get provider channel") - } - res = r - return nil - }) - - return res, err -} - -// SubscribeToPromiseSettledEvent subscribes to promise settled events -func (bwr *BlockchainWithRetries) SubscribeToPromiseSettledEvent(providerID, hermesID common.Address) (chan *bindings.HermesImplementationPromiseSettled, func(), error) { - var sink chan *bindings.HermesImplementationPromiseSettled - var cancel func() - err := bwr.callWithRetry(func() error { - s, c, err := bwr.bc.SubscribeToPromiseSettledEvent(providerID, hermesID) - if err != nil { - return errors.Wrap(err, "could not subscribe to settlement events") - } - sink = s - cancel = c - return nil - }) - return sink, cancel, err -} - -// SubscribeToConsumerBalanceEvent subscribes to the consumer balance change events -func (bwr *BlockchainWithRetries) SubscribeToConsumerBalanceEvent(channel, mystSCAddress common.Address, timeout time.Duration) (chan *bindings.MystTokenTransfer, func(), error) { - var sink chan *bindings.MystTokenTransfer - var cancel func() - err := bwr.callWithRetry(func() error { - s, c, err := bwr.bc.SubscribeToConsumerBalanceEvent(channel, mystSCAddress, timeout) - if err != nil { - return errors.Wrap(err, "could not subscribe to settlement events") - } - sink = s - cancel = c - return nil - }) - return sink, cancel, err -} - -// IsRegistered checks wether the given identity is registered or not -func (bwr *BlockchainWithRetries) IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) { - var res bool - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.IsRegistered(registryAddress, addressToCheck) - if err != nil { - return errors.Wrap(err, "check registration status") - } - res = r - return nil - }) - return res, err -} - -// GetMystBalance returns the balance in myst -func (bwr *BlockchainWithRetries) GetMystBalance(mystSCAddress, channel common.Address) (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetMystBalance(mystSCAddress, channel) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get myst balance") - } - res = result - return nil - }) - return res, err -} - -// RegisterIdentity registers the given identity on blockchain -func (bwr *BlockchainWithRetries) RegisterIdentity(rr RegistrationRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.RegisterIdentity(rr) - if bcErr != nil { - return errors.Wrap(bcErr, "could not register identity") - } - res = result - return nil - }) - return res, err -} - -// TransferMyst transfers myst to the provided address -func (bwr *BlockchainWithRetries) TransferMyst(req TransferRequest) (tx *types.Transaction, err error) { - err = bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.TransferMyst(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not transfer myst") - } - tx = result - return nil - }) - return tx, err -} - -// IsHermesRegistered checks if given hermes is registered and returns true or false. -func (bwr *BlockchainWithRetries) IsHermesRegistered(registryAddress, acccountantID common.Address) (bool, error) { - var res bool - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.IsHermesRegistered(registryAddress, acccountantID) - if bcErr != nil { - return errors.Wrap(bcErr, "could not check if hermes is registered") - } - res = result - return nil - }) - return res, err -} - -// GetHermesOperator returns operator address of given hermes -func (bwr *BlockchainWithRetries) GetHermesOperator(hermesID common.Address) (common.Address, error) { - var res common.Address - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetHermesOperator(hermesID) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get hermes operator") - } - res = result - return nil - }) - return res, err -} - -// SettleAndRebalance is settling given hermes issued promise -func (bwr *BlockchainWithRetries) SettleAndRebalance(req SettleAndRebalanceRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.SettleAndRebalance(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not settle and rebalance") - } - res = result - return nil - }) - return res, err -} - -// GetProviderChannelByID returns the given channel information -func (bwr *BlockchainWithRetries) GetProviderChannelByID(acc common.Address, chID []byte) (ProviderChannel, error) { - var res ProviderChannel - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetProviderChannelByID(acc, chID) - if bcErr != nil { - return errors.Wrap(bcErr, "could not register identity") - } - res = result - return nil - }) - return res, err -} - -// GetConsumerChannelsHermes returns the consumer channels hermes -func (bwr *BlockchainWithRetries) GetConsumerChannelsHermes(channelAddress common.Address) (ConsumersHermes, error) { - var res ConsumersHermes - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetConsumerChannelsHermes(channelAddress) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get consumers hermes") - } - res = result - return nil - }) - return res, err -} - -// GetConsumerChannelOperator returns the consumer channel operator/identity -func (bwr *BlockchainWithRetries) GetConsumerChannelOperator(channelAddress common.Address) (common.Address, error) { - var res common.Address - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetConsumerChannelOperator(channelAddress) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get consumer's operator") - } - res = result - return nil - }) - return res, err -} - -func (bwr *BlockchainWithRetries) TransactionReceipt(hash common.Hash) (*types.Receipt, error) { - var res *types.Receipt - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.TransactionReceipt(hash) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get transaction receipt") - } - res = result - return nil - }) - return res, err -} - -// SubscribeToIdentityRegistrationEvents subscribes to identity registration events -func (bwr *BlockchainWithRetries) SubscribeToIdentityRegistrationEvents(registryAddress common.Address) (chan *bindings.RegistryRegisteredIdentity, func(), error) { - var sink chan *bindings.RegistryRegisteredIdentity - var cancel func() - err := bwr.callWithRetry(func() error { - s, c, err := bwr.bc.SubscribeToIdentityRegistrationEvents(registryAddress) - if err != nil { - return errors.Wrap(err, "could not subscribe to registration events") - } - sink = s - cancel = c - return nil - }) - return sink, cancel, err -} - -// SubscribeToConsumerChannelBalanceUpdate subscribes to consumer channel balance update events -func (bwr *BlockchainWithRetries) SubscribeToConsumerChannelBalanceUpdate(mystSCAddress common.Address, channelAddresses []common.Address) (chan *bindings.MystTokenTransfer, func(), error) { - var sink chan *bindings.MystTokenTransfer - var cancel func() - err := bwr.callWithRetry(func() error { - s, c, err := bwr.bc.SubscribeToConsumerChannelBalanceUpdate(mystSCAddress, channelAddresses) - if err != nil { - return errors.Wrap(err, "could not subscribe to channel balance events") - } - sink = s - cancel = c - return nil - }) - return sink, cancel, err -} - -// SettlePromise is settling the given consumer issued promise -func (bwr *BlockchainWithRetries) SettlePromise(req SettleRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.SettlePromise(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not settle promise") - } - res = result - return nil - }) - return res, err -} - -// GetHermessAvailableBalance returns the balance that is available for hermes. -func (bwr *BlockchainWithRetries) GetHermessAvailableBalance(hermesAddress common.Address) (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetHermessAvailableBalance(hermesAddress) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get balance") - } - res = result - return nil - }) - return res, err -} - -// GetEthBalance gets the current ethereum balance for the address. -func (bwr *BlockchainWithRetries) GetEthBalance(address common.Address) (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetEthBalance(address) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get balance") - } - res = result - return nil - }) - return res, err -} - -// GetHermesURL returns the hermes URL. -func (bwr *BlockchainWithRetries) GetHermesURL(registryID, hermesID common.Address) (string, error) { - var res string - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetHermesURL(registryID, hermesID) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get hermes url") - } - res = result - return nil - }) - return res, err -} - -// TransferEth transfers ethereum to the given address. -func (bwr *BlockchainWithRetries) TransferEth(etr EthTransferRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.TransferEth(etr) - if bcErr != nil { - return errors.Wrap(bcErr, "could not transfer ethereum") - } - res = result - return nil - }) - return res, err -} - -// SubscribeToPromiseSettledEventByChannelID subscribes to promise settled events -func (bwr *BlockchainWithRetries) SubscribeToPromiseSettledEventByChannelID(hermesID common.Address, providerAddresses [][32]byte) (chan *bindings.HermesImplementationPromiseSettled, func(), error) { - var sink chan *bindings.HermesImplementationPromiseSettled - var cancel func() - err := bwr.callWithRetry(func() error { - s, c, err := bwr.bc.SubscribeToPromiseSettledEventByChannelID(hermesID, providerAddresses) - if err != nil { - return errors.Wrap(err, "could not subscribe to settlement events") - } - sink = s - cancel = c - return nil - }) - return sink, cancel, err -} - -// GetConsumerChannel returns the consumer channel -func (bwr *BlockchainWithRetries) GetConsumerChannel(addr common.Address, mystSCAddress common.Address) (ConsumerChannel, error) { - var res ConsumerChannel - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.GetConsumerChannel(addr, mystSCAddress) - if bcErr != nil { - return errors.Wrap(bcErr, "could not get consumers channel") - } - res = result - return nil - }) - return res, err -} - -// NetworkID returns the network id -func (bwr *BlockchainWithRetries) NetworkID() (*big.Int, error) { - var res *big.Int - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.NetworkID() - if bcErr != nil { - return errors.Wrap(bcErr, "could not get network ID") - } - res = result - return nil - }) - return res, err -} - -// Stop stops the blockchain with retries aborting any waits for retries -func (bwr *BlockchainWithRetries) Stop() { - bwr.once.Do(func() { - close(bwr.stop) - }) -} - -// SettleWithBeneficiary is setting new beneficiary and settling latest promise balance into new beneficiary address. -func (bwr *BlockchainWithRetries) SettleWithBeneficiary(req SettleWithBeneficiaryRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.SettleWithBeneficiary(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not set beneficiary") - } - res = result - return nil - }) - return res, err -} - -// DecreaseProviderStake decreases provider stake. -func (bwr *BlockchainWithRetries) DecreaseProviderStake(req DecreaseProviderStakeRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.DecreaseProviderStake(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not set beneficiary") - } - res = result - return nil - }) - return res, err -} - -// SettleIntoStake settles the hermes promise into stake increase. -func (bwr *BlockchainWithRetries) SettleIntoStake(req SettleIntoStakeRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.SettleIntoStake(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not set beneficiary") - } - res = result - return nil - }) - return res, err -} - -// IncreaseProviderStake increases the provider stake. -func (bwr *BlockchainWithRetries) IncreaseProviderStake(req ProviderStakeIncreaseRequest) (*types.Transaction, error) { - var res *types.Transaction - err := bwr.callWithRetry(func() error { - result, bcErr := bwr.bc.IncreaseProviderStake(req) - if bcErr != nil { - return errors.Wrap(bcErr, "could not set beneficiary") - } - res = result - return nil - }) - return res, err -} - -// GetStakeThresholds returns the stake tresholds for the given hermes. -func (bwr *BlockchainWithRetries) GetStakeThresholds(hermesID common.Address) (min, max *big.Int, err error) { - err = bwr.callWithRetry(func() error { - m, ma, bcErr := bwr.bc.GetStakeThresholds(hermesID) - if bcErr != nil { - return errors.Wrap(bcErr, "could not set beneficiary") - } - min = m - max = ma - return nil - }) - return min, max, err -} - -func (bwr *BlockchainWithRetries) SendTransaction(tx *types.Transaction) error { - return bwr.callWithRetry(func() error { - if err := bwr.bc.SendTransaction(tx); err != nil { - return errors.Wrap(err, "could not send transaction to bc") - } - return nil - }) -} - -func (bwr *BlockchainWithRetries) IsHermesActive(hermesID common.Address) (bool, error) { - res := false - err := bwr.callWithRetry(func() error { - r, err := bwr.bc.IsHermesActive(hermesID) - if err != nil { - return err - } - res = r - return nil - }) - return res, err -} diff --git a/client/with_dry_runs.go b/client/with_dry_runs.go index c341e44..1f258fd 100644 --- a/client/with_dry_runs.go +++ b/client/with_dry_runs.go @@ -333,3 +333,7 @@ func (cwdr *WithDryRuns) GetHermes(registryID, hermesID common.Address) (Hermes, func (cwdr *WithDryRuns) GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) { return cwdr.bc.GetChannelImplementationByVersion(registryID, version) } + +func (cwdr *WithDryRuns) IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) { + return cwdr.bc.IsChannelOpened(registryID, identity, hermesID) +} From a1e448876e3d254a7d2a8f6988b33eb70e09d2a3 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Fri, 2 Apr 2021 09:25:00 +0300 Subject: [PATCH 03/14] Added utils for l2 -> l1 exit --- crypto/crypto.go | 32 ++++++++++++------ crypto/crypto_test.go | 11 ------ crypto/payandsettle.go | 77 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 crypto/payandsettle.go diff --git a/crypto/crypto.go b/crypto/crypto.go index 9aaaf18..abd9e48 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -73,24 +73,36 @@ func GenerateChannelAddress(identity, hermes, registry, channelImplementation st // GenerateProviderChannelID generated channelID for provider channels from given identity hash func GenerateProviderChannelID(providerIdentity, hermesAddress string) (string, error) { + return generateProviderChannelID(providerIdentity, hermesAddress, ProviderChannelTypeDefault) +} + +// GenerateProviderChannelIDForPayAndSettle generated channelID for provider channels from given identity hash +func GenerateProviderChannelIDForPayAndSettle(providerIdentity, hermesAddress string) (string, error) { + return generateProviderChannelID(providerIdentity, hermesAddress, ProviderChannelTypePayAndSettle) +} + +type ProviderChannelType string + +const ( + ProviderChannelTypeDefault ProviderChannelType = "" + ProviderChannelTypePayAndSettle ProviderChannelType = "withdrawal" +) + +func generateProviderChannelID(providerIdentity, hermesAddress string, channelType ProviderChannelType) (string, error) { if !isHexAddress(providerIdentity) || !isHexAddress(hermesAddress) { return "", errors.New("given providerIdentity and hermesAddress params have to be hex addresses") } - channelID := crypto.Keccak256(append( + input := append( common.HexToAddress(providerIdentity).Bytes(), common.HexToAddress(hermesAddress).Bytes()..., - )) + ) - return "0x" + common.Bytes2Hex(channelID), nil -} + if channelType == ProviderChannelTypePayAndSettle { + input = append(input, []byte(string(ProviderChannelTypePayAndSettle))...) + } -// GenerateProviderChannelIDBytes received provider and accountnat Address -func GenerateProviderChannelIDBytes(providerIdentity, hermesAddress common.Address) []byte { - return crypto.Keccak256(append( - providerIdentity.Bytes(), - hermesAddress.Bytes()..., - )) + return "0x" + common.Bytes2Hex(crypto.Keccak256(input)), nil } // GenerateHermesAddress generate hermes address from given hermes operator address diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 88aa1e4..48adbf2 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -19,8 +19,6 @@ package crypto import ( "testing" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" ) @@ -65,12 +63,3 @@ func TestGenerateProviderChannelID(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedChannelID, channelID) } - -func TestGenerateProviderChannelIDBytes(t *testing.T) { - providerIdentity := common.HexToAddress("0x761f2bb3e7AD6385a4c7833c5a26a8Ddfdabf9f3") - hermesAddress := common.HexToAddress("0x676b9a084aC11CEeF680AF6FFbE99b24106F47e7") - expectedChannelID := []byte{0xfe, 0xbe, 0xba, 0x54, 0xc5, 0x66, 0x10, 0x47, 0x5a, 0xe3, 0x43, 0x21, 0x99, 0x51, 0x51, 0x46, 0x9, 0x6e, 0x2d, 0x9c, 0x5b, 0x7b, 0xc2, 0xb3, 0x86, 0x5c, 0x4b, 0x19, 0x67, 0xcf, 0x1, 0xcc} - - channelID := GenerateProviderChannelIDBytes(providerIdentity, hermesAddress) - assert.Equal(t, expectedChannelID, channelID) -} diff --git a/crypto/payandsettle.go b/crypto/payandsettle.go new file mode 100644 index 0000000..7056be5 --- /dev/null +++ b/crypto/payandsettle.go @@ -0,0 +1,77 @@ +package crypto + +import ( + "encoding/binary" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" +) + +type PayAndSettleBeneficiaryPayload struct { + Beneficiary common.Address + Signature []byte + ChainID int64 + ProviderChannelIDForWithdrawal string + Amount *big.Int + R [32]byte +} + +func NewPayAndSettleBeneficiaryPayload(beneficiary common.Address, chainID int64, providerChannelIDForWithdrawal string, amount *big.Int, r [32]byte) *PayAndSettleBeneficiaryPayload { + if hasHexPrefix(providerChannelIDForWithdrawal) { + providerChannelIDForWithdrawal = providerChannelIDForWithdrawal[2:] + } + + return &PayAndSettleBeneficiaryPayload{ + Beneficiary: beneficiary, + ChainID: chainID, + ProviderChannelIDForWithdrawal: providerChannelIDForWithdrawal, + Amount: amount, + R: r, + } +} + +func (pasp *PayAndSettleBeneficiaryPayload) getMessage() []byte { + message := []byte{} + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(pasp.ChainID)) + message = append(message, Pad(b, 32)...) + message = append(message, Pad(common.Hex2Bytes(pasp.ProviderChannelIDForWithdrawal), 32)...) + message = append(message, Pad(math.U256(pasp.Amount).Bytes(), 32)...) + message = append(message, pasp.R[:]...) + message = append(message, pasp.Beneficiary.Bytes()...) + return message +} + +func (pasp *PayAndSettleBeneficiaryPayload) Sign(ks hashSigner, signer common.Address) error { + message := pasp.getMessage() + hash := crypto.Keccak256(message) + + signature, err := ks.SignHash( + accounts.Account{Address: signer}, + hash, + ) + if err != nil { + return err + } + + ReformatSignatureVForBC(signature) + + pasp.Signature = signature + return nil +} + +// RecoverSigner recovers signer address out of promise signature +func (pasp *PayAndSettleBeneficiaryPayload) RecoverSigner() (common.Address, error) { + sig := make([]byte, 65) + copy(sig, pasp.Signature) + + err := ReformatSignatureVForRecovery(sig) + if err != nil { + return common.Address{}, err + } + + return RecoverAddress(pasp.getMessage(), sig) +} From 7e4ab29c20a28ee41065ae509d2425d7c5533b1c Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Tue, 20 Apr 2021 15:24:22 +0300 Subject: [PATCH 04/14] Add missing methods for pay and settle --- client/client.go | 61 ++++++++++++++++++++++++++++++++++++ client/multichain_client.go | 8 +++++ client/with_dry_runs.go | 8 +++++ crypto/helpers.go | 10 ++++++ registration/registration.go | 2 ++ 5 files changed, 89 insertions(+) diff --git a/client/client.go b/client/client.go index 8800341..ec74f34 100644 --- a/client/client.go +++ b/client/client.go @@ -122,6 +122,7 @@ type BC interface { IsHermesActive(hermesID common.Address) (bool, error) GetHermes(registryID, hermesID common.Address) (Hermes, error) GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) + PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, error) IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) } @@ -319,6 +320,7 @@ func (bc *Blockchain) GetMystBalance(mystAddress, identity common.Address) (*big // RegistrationRequest contains all the parameters for the registration request type RegistrationRequest struct { WriteRequest + ChainID int64 HermesID common.Address Stake *big.Int TransactorFee *big.Int @@ -389,6 +391,65 @@ func (bc *Blockchain) RegisterIdentity(rr RegistrationRequest) (*types.Transacti return tx, err } +// PayAndSettleRequest allows to pay and settle and exit to l1 via this. +type PayAndSettleRequest struct { + WriteRequest + Beneficiary common.Address + HermesID common.Address + ProviderID common.Address + Promise crypto.Promise + BeneficiarySignature []byte +} + +func (psr PayAndSettleRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { + return bindings.NewContractEstimator(psr.HermesID, bindings.HermesImplementationABI, ethClient.Client()) +} + +func (psr PayAndSettleRequest) toEstimateOps() *bindings.EstimateOpts { + return &bindings.EstimateOpts{ + From: psr.Identity, + Method: "payAndSettle", + Params: []interface{}{psr.ProviderID, psr.Promise.Amount, psr.Promise.Fee, toBytes32(psr.Promise.R), psr.Promise.Signature, psr.Beneficiary, psr.BeneficiarySignature}, + } +} + +// PayAndSettle registers the given identity on blockchain. +func (bc *Blockchain) PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, error) { + transactor, err := bindings.NewHermesImplementationTransactor(psr.HermesID, bc.ethClient.Client()) + if err != nil { + return nil, err + } + parent := context.Background() + ctx, cancel := context.WithTimeout(parent, bc.bcTimeout) + defer cancel() + + nonce := psr.Nonce + if nonce == nil { + nonceUint, err := bc.getNonce(psr.Identity) + if err != nil { + return nil, errors.Wrap(err, "could not get nonce") + } + nonce = big.NewInt(0).SetUint64(nonceUint) + } + tx, err := transactor.PayAndSettle(&bind.TransactOpts{ + From: psr.Identity, + Signer: psr.Signer, + Context: ctx, + GasLimit: psr.GasLimit, + GasPrice: psr.GasPrice, + Nonce: nonce, + }, + psr.ProviderID, + psr.Promise.Amount, + psr.Promise.Fee, + toBytes32(psr.Promise.R), + psr.Promise.Signature, + psr.Beneficiary, + psr.BeneficiarySignature, + ) + return tx, err +} + // TransferRequest contains all the parameters for a transfer request type TransferRequest struct { MystAddress common.Address diff --git a/client/multichain_client.go b/client/multichain_client.go index 93e2e4a..3925a0f 100644 --- a/client/multichain_client.go +++ b/client/multichain_client.go @@ -429,3 +429,11 @@ func (mbc *MultichainBlockchainClient) IsHermesActive(chainID int64, hermesID co } return bc.IsHermesActive(hermesID) } + +func (mbc *MultichainBlockchainClient) PayAndSettle(chainID int64, psr PayAndSettleRequest) (*types.Transaction, error) { + bc, err := mbc.getClientByChain(chainID) + if err != nil { + return nil, err + } + return bc.PayAndSettle(psr) +} diff --git a/client/with_dry_runs.go b/client/with_dry_runs.go index 1f258fd..f74c489 100644 --- a/client/with_dry_runs.go +++ b/client/with_dry_runs.go @@ -276,6 +276,14 @@ func (cwdr *WithDryRuns) DecreaseProviderStake(req DecreaseProviderStakeRequest) return cwdr.bc.DecreaseProviderStake(req) } +func (cwdr *WithDryRuns) PayAndSettle(req PayAndSettleRequest) (*types.Transaction, error) { + if _, err := cwdr.Estimate(req); err != nil { + return nil, err + } + + return cwdr.bc.PayAndSettle(req) +} + func (cwdr *WithDryRuns) GetBeneficiary(registryAddress, identity common.Address) (common.Address, error) { return cwdr.bc.GetBeneficiary(registryAddress, identity) } diff --git a/crypto/helpers.go b/crypto/helpers.go index 33276fe..4befb95 100644 --- a/crypto/helpers.go +++ b/crypto/helpers.go @@ -20,6 +20,8 @@ import ( "errors" "math/big" "strings" + + "github.com/ethereum/go-ethereum/common" ) // Myst represents a single myst ERC 777 token. @@ -43,6 +45,14 @@ func FloatToBigMyst(input float64) *big.Int { return res } +func HexToBytes(str string) []byte { + if hasHexPrefix(str) { + return common.Hex2Bytes(str[2:]) + } + + return common.Hex2Bytes(str) +} + func hasHexPrefix(str string) bool { return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') } diff --git a/registration/registration.go b/registration/registration.go index 1c5b322..2759852 100644 --- a/registration/registration.go +++ b/registration/registration.go @@ -27,6 +27,7 @@ import ( // Request represent a request to register type Request struct { + ChainID int64 `json:"chainID"` HermesID string `json:"hermesID"` Stake *big.Int `json:"stake"` Fee *big.Int `json:"fee"` @@ -55,6 +56,7 @@ func (r Request) GetSignatureBytesRaw() []byte { // GetMessage forms the message payload given the registration request func (r Request) GetMessage() []byte { message := []byte{} + message = append(message, crypto.Pad(math.U256Bytes(big.NewInt(r.ChainID)), 32)...) message = append(message, common.HexToAddress(r.RegistryAddress).Bytes()...) message = append(message, common.HexToAddress(r.HermesID).Bytes()...) message = append(message, crypto.Pad(math.U256(r.Stake).Bytes(), 32)...) From e04586424ad724e1b7468da092039cce76c67935 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Thu, 22 Apr 2021 15:34:28 +0300 Subject: [PATCH 05/14] Export ToBytes32 --- client/client.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/client.go b/client/client.go index ec74f34..a79c565 100644 --- a/client/client.go +++ b/client/client.go @@ -409,7 +409,7 @@ func (psr PayAndSettleRequest) toEstimateOps() *bindings.EstimateOpts { return &bindings.EstimateOpts{ From: psr.Identity, Method: "payAndSettle", - Params: []interface{}{psr.ProviderID, psr.Promise.Amount, psr.Promise.Fee, toBytes32(psr.Promise.R), psr.Promise.Signature, psr.Beneficiary, psr.BeneficiarySignature}, + Params: []interface{}{psr.ProviderID, psr.Promise.Amount, psr.Promise.Fee, ToBytes32(psr.Promise.R), psr.Promise.Signature, psr.Beneficiary, psr.BeneficiarySignature}, } } @@ -442,7 +442,7 @@ func (bc *Blockchain) PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, psr.ProviderID, psr.Promise.Amount, psr.Promise.Fee, - toBytes32(psr.Promise.R), + ToBytes32(psr.Promise.R), psr.Promise.Signature, psr.Beneficiary, psr.BeneficiarySignature, @@ -562,7 +562,7 @@ func (r SettleIntoStakeRequest) toEstimateOps() *bindings.EstimateOpts { r.ProviderID, r.Promise.Amount, r.Promise.Fee, - toBytes32(r.Promise.R), + ToBytes32(r.Promise.R), r.Promise.Signature, }, } @@ -712,7 +712,7 @@ func (r SettleAndRebalanceRequest) toEstimateOps() *bindings.EstimateOpts { return &bindings.EstimateOpts{ From: r.Identity, Method: "settlePromise", - Params: []interface{}{r.ProviderID, r.Promise.Amount, r.Promise.Fee, toBytes32(r.Promise.R), r.Promise.Signature}, + Params: []interface{}{r.ProviderID, r.Promise.Amount, r.Promise.Fee, ToBytes32(r.Promise.R), r.Promise.Signature}, } } @@ -741,12 +741,12 @@ func (bc *Blockchain) SettleAndRebalance(req SettleAndRebalanceRequest) (*types. req.ProviderID, req.Promise.Amount, req.Promise.Fee, - toBytes32(req.Promise.R), + ToBytes32(req.Promise.R), req.Promise.Signature, ) } -func toBytes32(arr []byte) (res [32]byte) { +func ToBytes32(arr []byte) (res [32]byte) { copy(res[:], arr) return res } @@ -780,7 +780,7 @@ func (bc *Blockchain) GetProviderChannelByID(acc common.Address, chID []byte) (P return caller.Channels(&bind.CallOpts{ Pending: false, Context: ctx, - }, toBytes32(chID)) + }, ToBytes32(chID)) } // ConsumersHermes represents the consumers hermes @@ -1140,7 +1140,7 @@ func (r SettleWithBeneficiaryRequest) toEstimateOps() *bindings.EstimateOpts { r.ProviderID, r.Promise.Amount, r.Promise.Fee, - toBytes32(r.Promise.R), + ToBytes32(r.Promise.R), r.Promise.Signature, r.Beneficiary, r.Signature, @@ -1194,7 +1194,7 @@ func (bc *Blockchain) SettleWithBeneficiary(req SettleWithBeneficiaryRequest) (* req.ProviderID, req.Promise.Amount, req.Promise.Fee, - toBytes32(req.Promise.R), + ToBytes32(req.Promise.R), req.Promise.Signature, req.Beneficiary, req.Signature, From a09899b6655470f6075d6fa4ab8dfe2d7435470d Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Wed, 26 May 2021 11:48:43 +0300 Subject: [PATCH 06/14] add gecko and coinranking --- fees/price/coinranking.go | 156 ++++++++++++++++++++++++++++++++++++++ fees/price/gecko.go | 112 +++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 fees/price/coinranking.go create mode 100644 fees/price/gecko.go diff --git a/fees/price/coinranking.go b/fees/price/coinranking.go new file mode 100644 index 0000000..9a04c96 --- /dev/null +++ b/fees/price/coinranking.go @@ -0,0 +1,156 @@ +/* Mysterium network payment library. + * + * Copyright (C) 2021 BlockDev AG + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package price + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net" + "net/http" + "strconv" + "strings" + "time" +) + +// CoinRanking represents a CoinRanking REST API client. +type CoinRanking struct { + baseURI string + client *http.Client + accessToken *string +} + +// DefaultCoinRankingURI points to default CoinRanking api. +const DefaultCoinRankingURI = "https://api.coinranking.com/v2/" + +// NewCoinRanking returns a new CoinRanking API client. +func NewCoinRanking(baseURI string, coinRankingAccessToken *string) *CoinRanking { + if !strings.HasSuffix(baseURI, "/") { + baseURI += "/" + } + return &CoinRanking{ + baseURI: baseURI, + accessToken: coinRankingAccessToken, + + client: &http.Client{ + Transport: &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 10 * time.Second, + KeepAlive: 10 * time.Second, + }).DialContext, + TLSHandshakeTimeout: 5 * time.Second, + ExpectContinueTimeout: 4 * time.Second, + ResponseHeaderTimeout: 3 * time.Second, + }, + Timeout: 10 * time.Second, + }, + } +} + +type coinsPricesResponse struct { + Status string `json:"status"` + Data struct { + Coins []struct { + UUID string `json:"uuid"` + Price string `json:"price"` + } `json:"coins"` + } `json:"data"` +} + +var currencyToUuid = map[currency]string{ + ETH: "razxDUgYGNAdQ", + MYST: "C5Hx25DA3vp8h", + MATIC: "uW2tk-ILY0ii", + USD: "yhjMzLPhuIDl", + EUR: "5k-_VTxqtCEI", +} +var uuidToCurrency = map[string]currency{} + +func init() { + for k, v := range currencyToUuid { + uuidToCurrency[v] = k + } +} + +func coinToUUID(coin currency) (string, bool) { + u, ok := currencyToUuid[coin] + return u, ok +} + +func uuidToCoin(uuid string) (currency, bool) { + c, ok := uuidToCurrency[uuid] + return c, ok +} + +// GetCoinPrice returns the coin price in the given currencies for given coins. +func (g *CoinRanking) GetCoinPrice(coins []string, vsCurrencies []string) (PriceResponse, error) { + r := make(PriceResponse) + for _, cur := range vsCurrencies { + r[cur] = make(Prices) + + url := g.baseURI + "coins" + req, _ := http.NewRequest(http.MethodGet, url, nil) + if g.accessToken != nil && *g.accessToken != "" { + req.Header.Add("x-access-token", *g.accessToken) + } + q := req.URL.Query() + for _, co := range coins { + u, ok := coinToUUID(currency(co)) + if !ok { + return PriceResponse{}, errors.New("unknown coin: " + co) + } + q.Add("uuids[]", u) + } + + curUuid, ok := coinToUUID(currency(cur)) + if !ok { + return PriceResponse{}, errors.New("unknown currency") + } + q.Add("referenceCurrencyUuid", curUuid) + req.URL.RawQuery = q.Encode() + + resp, err := g.client.Do(req) + if err != nil { + return PriceResponse{}, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := ioutil.ReadAll(resp.Body) + return PriceResponse{}, fmt.Errorf("got an unexpected error code %v, body: %v", resp.StatusCode, string(body)) + } + var res coinsPricesResponse + if err = json.NewDecoder(resp.Body).Decode(&res); err != nil { + return PriceResponse{}, err + } + + for _, v := range res.Data.Coins { + price, err := strconv.ParseFloat(v.Price, 64) + if err != nil { + return PriceResponse{}, err + } + + coin, ok := uuidToCoin(v.UUID) + if !ok { + return PriceResponse{}, errors.New("unknown coin: " + v.UUID) + } + r[cur][string(coin)] = price + } + } + return r, nil +} diff --git a/fees/price/gecko.go b/fees/price/gecko.go new file mode 100644 index 0000000..3c77696 --- /dev/null +++ b/fees/price/gecko.go @@ -0,0 +1,112 @@ +/* Mysterium network payment library. + * + * Copyright (C) 2021 BlockDev AG + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package price + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "strings" + "time" +) + +type currency string + +const ( + // ETH - the ethereum currency. + ETH currency = "ethereum" + // MYST - the mysterium coin. + MYST currency = "mysterium" + // MATIC - the matic coin. + MATIC currency = "matic-network" + // USD - the good old dollar. + USD currency = "usd" + // EUR - the official currency of the European Union + EUR currency = "eur" +) + +// Gecko represents a gecko REST API client. +type Gecko struct { + baseURI string + client *http.Client +} + +// DefaultGeckoURI points to default coingecko api. +const DefaultGeckoURI = "https://api.coingecko.com/api/v3" + +// NewGecko returns a new gecko API client. +func NewGecko(baseURI string) *Gecko { + if !strings.HasSuffix(baseURI, "/") { + baseURI += "/" + } + return &Gecko{ + baseURI: baseURI, + client: &http.Client{ + Transport: &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 10 * time.Second, + KeepAlive: 10 * time.Second, + }).DialContext, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 4 * time.Second, + ResponseHeaderTimeout: 3 * time.Second, + }, + Timeout: 30 * time.Second, + }, + } +} + +// Prices represents a single coin pricing information. +type Prices map[string]float64 + +// PriceResponse represents the gecko price response. +type PriceResponse map[string]Prices + +// GetPriceInUSD returns the price in USD. +func (pr PriceResponse) GetPriceInUSD(c currency) (float64, bool) { + v, ok := pr[string(c)] + if !ok { + return 0, false + } + p, ok := v[string(USD)] + return p, ok +} + +// GetCoinPrice returns the coin price in the given currencies for given coins. +func (g *Gecko) GetCoinPrice(coins []string, vsCurrencies []string) (PriceResponse, error) { + path := fmt.Sprintf("simple/price?ids=%v&vs_currencies=%v", strings.Join(coins, ","), strings.Join(vsCurrencies, ",")) + url := fmt.Sprintf("%v%v", g.baseURI, path) + resp, err := g.client.Get(url) + if err != nil { + return PriceResponse{}, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := ioutil.ReadAll(resp.Body) + return PriceResponse{}, fmt.Errorf("got an unexpected error code %v, body: %v", resp.StatusCode, string(body)) + } + + var res PriceResponse + if err = json.NewDecoder(resp.Body).Decode(&res); err != nil { + return PriceResponse{}, err + } + + return res, nil +} From d3905343a05fdd584965dd41b0e721f72ec869ad Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Thu, 3 Jun 2021 14:33:13 +0300 Subject: [PATCH 07/14] Fix --- client/bc.go | 3 +++ client/client.go | 52 ------------------------------------------------ 2 files changed, 3 insertions(+), 52 deletions(-) diff --git a/client/bc.go b/client/bc.go index b6c2a65..b0db542 100644 --- a/client/bc.go +++ b/client/bc.go @@ -67,4 +67,7 @@ type BC interface { RewarderUpdateRoot(req RewarderUpdateRoot) (*types.Transaction, error) RewarderTotalClaimed(rewarderAddress common.Address) (*big.Int, error) CustodyTransferTokens(req CustodyTokensTransfer) (*types.Transaction, error) + + PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, error) + IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) } diff --git a/client/client.go b/client/client.go index f9eb034..0de0971 100644 --- a/client/client.go +++ b/client/client.go @@ -80,58 +80,6 @@ func NewBlockchainWithCustomNonceTracker(ethClient ethClientGetter, timeout time } } -type BC interface { - GetHermesFee(hermesAddress common.Address) (uint16, error) - CalculateHermesFee(hermesAddress common.Address, value *big.Int) (*big.Int, error) - IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck common.Address) (bool, error) - GetProviderChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) - IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) - SubscribeToPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) - GetMystBalance(mystSCAddress, address common.Address) (*big.Int, error) - SubscribeToConsumerBalanceEvent(channel, mystSCAddress common.Address, timeout time.Duration) (chan *bindings.MystTokenTransfer, func(), error) - RegisterIdentity(rr RegistrationRequest) (*types.Transaction, error) - TransferMyst(req TransferRequest) (tx *types.Transaction, err error) - IsHermesRegistered(registryAddress, acccountantID common.Address) (bool, error) - GetHermesOperator(hermesID common.Address) (common.Address, error) - SettleAndRebalance(req SettleAndRebalanceRequest) (*types.Transaction, error) - SettleWithBeneficiary(req SettleWithBeneficiaryRequest) (*types.Transaction, error) - GetConsumerChannelsHermes(channelAddress common.Address) (ConsumersHermes, error) - GetConsumerChannelOperator(channelAddress common.Address) (common.Address, error) - GetProviderChannelByID(acc common.Address, chID []byte) (ProviderChannel, error) - SubscribeToIdentityRegistrationEvents(registryAddress common.Address) (sink chan *bindings.RegistryRegisteredIdentity, cancel func(), err error) - SubscribeToConsumerChannelBalanceUpdate(mystSCAddress common.Address, channelAddresses []common.Address) (sink chan *bindings.MystTokenTransfer, cancel func(), err error) - SettlePromise(req SettleRequest) (*types.Transaction, error) - SubscribeToPromiseSettledEventByChannelID(hermesID common.Address, providerAddresses [][32]byte) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) - SubscribeToMystTokenTransfers(mystSCAddress common.Address) (chan *bindings.MystTokenTransfer, func(), error) - NetworkID() (*big.Int, error) - GetConsumerChannel(addr common.Address, mystSCAddress common.Address) (ConsumerChannel, error) - GetEthBalance(address common.Address) (*big.Int, error) - TransferEth(etr EthTransferRequest) (*types.Transaction, error) - GetHermessAvailableBalance(hermesAddress common.Address) (*big.Int, error) - DecreaseProviderStake(req DecreaseProviderStakeRequest) (*types.Transaction, error) - SettleIntoStake(req SettleIntoStakeRequest) (*types.Transaction, error) - IncreaseProviderStake(req ProviderStakeIncreaseRequest) (*types.Transaction, error) - TransactionReceipt(hash common.Hash) (*types.Receipt, error) - GetHermesURL(registryID, hermesID common.Address) (string, error) - GetStakeThresholds(hermesID common.Address) (min, max *big.Int, err error) - GetBeneficiary(registryAddress, identity common.Address) (common.Address, error) - SuggestGasPrice() (*big.Int, error) - FilterLogs(q ethereum.FilterQuery) ([]types.Log, error) - HeaderByNumber(number *big.Int) (*types.Header, error) - GetLastRegistryNonce(registry common.Address) (*big.Int, error) - SendTransaction(tx *types.Transaction) error - IsHermesActive(hermesID common.Address) (bool, error) - GetHermes(registryID, hermesID common.Address) (Hermes, error) - GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) - PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, error) - IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) - TransactionByHash(hash common.Hash) (*types.Transaction, bool, error) - RewarderTotalPayoutsFor(rewarderAddress common.Address, payoutsFor common.Address) (*big.Int, error) - RewarderAirDrop(req RewarderAirDrop) (*types.Transaction, error) - RewarderUpdateRoot(req RewarderUpdateRoot) (*types.Transaction, error) - RewarderTotalClaimed(rewarderAddress common.Address) (*big.Int, error) -} - // GetHermesFee fetches the hermes fee from blockchain func (bc *Blockchain) GetHermesFee(hermesAddress common.Address) (uint16, error) { caller, err := bindings.NewHermesImplementationCaller(hermesAddress, bc.ethClient.Client()) From ac12ee179311a5d3704a275d84b92f2425a415f0 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Thu, 3 Jun 2021 15:04:58 +0300 Subject: [PATCH 08/14] Nonce tracker test added --- client/nonce_tracker.go | 9 ++++-- client/nonce_tracker_test.go | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 client/nonce_tracker_test.go diff --git a/client/nonce_tracker.go b/client/nonce_tracker.go index cc81a0e..b56ed05 100644 --- a/client/nonce_tracker.go +++ b/client/nonce_tracker.go @@ -21,18 +21,21 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" ) // NonceTracker keeps track of nonces atomically. type NonceTracker struct { - client *ethclient.Client + client client nonces map[common.Address]uint64 nonceLock sync.Mutex } +type client interface { + PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) +} + // NewNonceTracker returns a new nonce tracker. -func NewNonceTracker(client *ethclient.Client) *NonceTracker { +func NewNonceTracker(client client) *NonceTracker { return &NonceTracker{ client: client, nonces: make(map[common.Address]uint64), diff --git a/client/nonce_tracker_test.go b/client/nonce_tracker_test.go new file mode 100644 index 0000000..fa5a704 --- /dev/null +++ b/client/nonce_tracker_test.go @@ -0,0 +1,54 @@ +package client + +import ( + "context" + "fmt" + "sync" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func Test_NonceTracker(t *testing.T) { + trck := NewNonceTracker(&mockClient{}) + addr := common.HexToAddress("0x0") + wg := sync.WaitGroup{} + + size := 1000 + nonces := make(chan uint64, size) + for i := 0; i < size; i++ { + wg.Add(1) + go func() { + defer wg.Done() + + nonce, err := trck.GetNonce(context.Background(), addr) + assert.NoError(t, err) + nonces <- nonce + }() + } + + wg.Wait() + close(nonces) + results := make(map[uint64]int) + + for v := range nonces { + if prev, ok := results[v]; ok { + results[v] = prev + 1 + } else { + results[v] = 1 + } + } + + for k, v := range results { + assert.Equal(t, 1, v, fmt.Sprintf("%v is bad", k)) + } + +} + +type mockClient struct { +} + +func (mc *mockClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + return 1, nil +} From d5ad53907244c5bcc525d61270a99d3b65cac97c Mon Sep 17 00:00:00 2001 From: tomasmik Date: Wed, 9 Jun 2021 16:25:46 +0300 Subject: [PATCH 09/14] Incrementor should only pick transaction it can actually sign --- fees/incrementor.go | 74 ++++++++++++++++++++++++++-------------- fees/incrementor_test.go | 8 ++--- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/fees/incrementor.go b/fees/incrementor.go index b6ae9fb..98bc317 100644 --- a/fees/incrementor.go +++ b/fees/incrementor.go @@ -36,7 +36,7 @@ type GasPriceIncremenetor struct { storage Storage bc MultichainClient - signers Signers + signers safeSigners logFn LogFunc syncer *syncer @@ -53,7 +53,10 @@ type Storage interface { UpsertIncrementorTransaction(tx Transaction) error // GetIncrementorTransactionsToCheck returns all transaction that need to rechecked. - GetIncrementorTransactionsToCheck() (tx []Transaction, err error) + // + // Entries should be filtered by possible signers. If incrementor cannot sign the transaction + // it should not received it. + GetIncrementorTransactionsToCheck(possibleSigners []string) (tx []Transaction, err error) } // MultichainClient handles calls to BC. @@ -63,12 +66,6 @@ type MultichainClient interface { TransactionByHash(chainID int64, hash common.Hash) (*types.Transaction, bool, error) } -// SignatureFunc is used to sign transactions when resubmitting them. -type SignatureFunc func(tx *types.Transaction, chainID int64) (*types.Transaction, error) - -// Signers is a map that holds all possible signers to sign transactions when resending to the blockchain. -type Signers map[common.Address]SignatureFunc - // LogFunc can be attacheched to Incrementer to enable logging. type LogFunc func(Transaction, error) @@ -79,7 +76,9 @@ func NewGasPriceIncremenetor(pullInterval time.Duration, storage Storage, cl Mul storage: storage, bc: cl, - signers: signers, + signers: safeSigners{ + signers: signers, + }, syncer: newSyncer(), stop: make(chan struct{}, 0), @@ -108,7 +107,7 @@ func (i *GasPriceIncremenetor) Run() { return case <-time.After(i.pullInterval): - txs, err := i.storage.GetIncrementorTransactionsToCheck() + txs, err := i.storage.GetIncrementorTransactionsToCheck(i.signers.getSigners()) if err != nil { continue } @@ -317,22 +316,8 @@ func (i *GasPriceIncremenetor) bcTxStatusFromReceipt(tx Transaction, rcp *types. } } -func (i *GasPriceIncremenetor) getSigner(senderAddressHex string) (SignatureFunc, bool) { - // TODO: Remove later. Left for backwards compatability. - // If only one signer is present and senderAddress is `""` return first signer. - if len(i.signers) == 1 && senderAddressHex == "" { - for _, v := range i.signers { - return v, true - } - } - - addr := common.HexToAddress(senderAddressHex) - signer, ok := i.signers[addr] - return signer, ok -} - func (i *GasPriceIncremenetor) signAndSend(tx *types.Transaction, chainID int64, senderAddrHex string) (*types.Transaction, error) { - signer, ok := i.getSigner(senderAddrHex) + signer, ok := i.signers.getSignerFunc(senderAddrHex) if !ok { return nil, fmt.Errorf("can't retry, no signer for address: %s", senderAddrHex) } @@ -416,3 +401,42 @@ func (s *syncer) txRemoveWatched(tx Transaction) { defer s.m.Unlock() delete(s.txs, tx.UniqueID) } + +// SignatureFunc is used to sign transactions when resubmitting them. +type SignatureFunc func(tx *types.Transaction, chainID int64) (*types.Transaction, error) + +// Signers is a map that holds all possible signers to sign transactions when resending to the blockchain. +type Signers map[common.Address]SignatureFunc + +type safeSigners struct { + signers map[common.Address]SignatureFunc + m sync.Mutex +} + +func (s *safeSigners) getSignerFunc(senderAddressHex string) (SignatureFunc, bool) { + s.m.Lock() + defer s.m.Unlock() + + // TODO: Remove later. Left for backwards compatability. + // If only one signer is present and senderAddress is `""` return first signer. + if len(s.signers) == 1 && senderAddressHex == "" { + for _, v := range s.signers { + return v, true + } + } + + addr := common.HexToAddress(senderAddressHex) + signer, ok := s.signers[addr] + return signer, ok +} + +func (s *safeSigners) getSigners() []string { + s.m.Lock() + defer s.m.Unlock() + + signers := make([]string, 0) + for signer := range s.signers { + signers = append(signers, signer.Hex()) + } + return signers +} diff --git a/fees/incrementor_test.go b/fees/incrementor_test.go index 3ef43cf..545a266 100644 --- a/fees/incrementor_test.go +++ b/fees/incrementor_test.go @@ -48,7 +48,7 @@ func TestGasPriceIncrementor(t *testing.T) { go inc.Run() inc.InsertInitial(org, opts, sender) assert.Eventually(t, func() bool { - txs, _ := st.GetIncrementorTransactionsToCheck() + txs, _ := st.GetIncrementorTransactionsToCheck([]string{sender.Hex()}) if len(txs) == 0 { return false } @@ -88,7 +88,7 @@ func TestGasPriceIncrementor(t *testing.T) { go inc.Run() inc.InsertInitial(org, opts, sender) assert.Eventually(t, func() bool { - txs, _ := st.GetIncrementorTransactionsToCheck() + txs, _ := st.GetIncrementorTransactionsToCheck([]string{sender.Hex()}) if len(txs) == 0 { return false } @@ -129,7 +129,7 @@ func TestGasPriceIncrementor(t *testing.T) { go inc.Run() inc.InsertInitial(org, opts, sender) assert.Eventually(t, func() bool { - txs, _ := st.GetIncrementorTransactionsToCheck() + txs, _ := st.GetIncrementorTransactionsToCheck([]string{sender.Hex()}) if len(txs) == 0 { return false } @@ -211,7 +211,7 @@ func (s *mockStorage) UpsertIncrementorTransaction(tx Transaction) error { return nil } -func (s *mockStorage) GetIncrementorTransactionsToCheck() (tx []Transaction, err error) { +func (s *mockStorage) GetIncrementorTransactionsToCheck(signers []string) (tx []Transaction, err error) { s.m.Lock() defer s.m.Unlock() s.pulled = true From b0edfb722e2c1957f93c081e9db0e96d6063f9fc Mon Sep 17 00:00:00 2001 From: tomasmik Date: Fri, 11 Jun 2021 12:51:42 +0300 Subject: [PATCH 10/14] Gas incrementor and transaction handler now queue * Check queue, if we have more than X amount of transactions - dont submit a new one. * Validate transaction opts before submitting a transaction. * Check if we have the sigenrs to repeat the transaction, if we dont, dont submit it. --- client/counter.go | 41 +++++++++++++++++++++++++++++ fees/handler.go | 57 +++++++++++++++++++++++++++++++++++----- fees/incrementor.go | 44 ++++++++++++++++++++++++------- fees/incrementor_test.go | 16 ++++++++--- 4 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 client/counter.go diff --git a/client/counter.go b/client/counter.go new file mode 100644 index 0000000..40efe9e --- /dev/null +++ b/client/counter.go @@ -0,0 +1,41 @@ +package client + +import ( + "runtime" + "sync" + + "github.com/davecgh/go-spew/spew" +) + +var Counter = callCounter{} + +type callCounter struct { + stats map[string]uint64 + lock sync.Mutex + once sync.Once +} + +func (cc *callCounter) print() { + spew.Dump(cc.stats) +} + +func (cc *callCounter) Count() { + cc.lock.Lock() + defer cc.lock.Unlock() + pc, _, _, ok := runtime.Caller(1) + details := runtime.FuncForPC(pc) + if ok && details != nil { + cc.once.Do(func() { + cc.stats = make(map[string]uint64) + }) + + name := details.Name() + if v, ok := cc.stats[name]; ok { + cc.stats[name] = v + 1 + } else { + cc.stats[name] = 1 + } + + cc.print() + } +} diff --git a/fees/handler.go b/fees/handler.go index cbd6332..7bee386 100644 --- a/fees/handler.go +++ b/fees/handler.go @@ -27,19 +27,21 @@ import ( // TransactionHandler wraps gas price increasers // exposing a send method which handles gas prices when sending a transaction. // -// TransactionHandler expects watchers and increasers to be -// handleded and started by the caller hitself -// as it only sends and inserts transactions. +// TransactionHandler expects the gas price increaser to be +// handleded and started by the caller himself. type TransactionHandler struct { inc GasPriceIncremenetorIface logFn func(error) } -// HandlerOpts are given when sending -// a new transaction. +// HandlerOpts are given when sending a new transaction. type HandlerOpts struct { - SenderAddress common.Address + // SenderAddress is the address of the sender who is making the trasaction. + SenderAddress common.Address + // GasPriceIncOpts will be used to increase the gas price using an incrementor. GasPriceIncOpts TransactionOpts + // Optional: ForceQueue allows to bypass the check if transaction is able to queue. + ForceQueue bool } // TransactionSendFn wraps a transaction execution which should result @@ -49,9 +51,23 @@ type HandlerOpts struct { // all result in producing a transaction. type TransactionSendFn func() (*types.Transaction, error) -// GasPriceIncremenetorIface abstracts gas pricei incrementor. +// ErrQueueFull is returned if the current queue is full and incremeting gas price will be impossible. +// Transactions which receive this error should be retried later. +var ErrQueueFull = errors.New("failed to send a transaction, queue is full") + +// ErrNoSigners is returned if there are no signers to use for incrementing this transaction. +var ErrNoSigners = errors.New("failed to send a transaction, no signers for incrementing") + +// GasPriceIncremenetorIface abstracts gas price incrementor. type GasPriceIncremenetorIface interface { + // InsertInitial inserts a new transaction to the queue. InsertInitial(tx *types.Transaction, opts TransactionOpts, senderAddress common.Address) error + + // CanQueue returns true if another transaction can be queue in to the incrementor. + CanQueue(sender common.Address) (bool, error) + + // CanSign returns if incrementor can sign this transaction when incrementing gas price. + CanSign(sender common.Address) bool } // NewTransactionhandler returns a new transaction handler @@ -77,6 +93,10 @@ func (t *TransactionHandler) SendWithGasPriceHandling(txSend TransactionSendFn, return nil, err } + if err := t.canQueue(opts); err != nil { + return nil, err + } + tx, err := txSend() if err != nil { return nil, err @@ -89,10 +109,33 @@ func (t *TransactionHandler) SendWithGasPriceHandling(txSend TransactionSendFn, return tx, nil } +func (t *TransactionHandler) canQueue(opts HandlerOpts) error { + if opts.ForceQueue { + return nil + } + + canQ, err := t.inc.CanQueue(opts.SenderAddress) + if err != nil { + return err + } + if !canQ { + return ErrQueueFull + } + + if !t.inc.CanSign(opts.SenderAddress) { + return ErrNoSigners + } + + return nil +} + func (opts *HandlerOpts) validate() error { if opts.SenderAddress == common.HexToAddress("") { return errors.New("sender address must be specified") } + if err := opts.GasPriceIncOpts.validate(); err != nil { + return err + } return nil } diff --git a/fees/incrementor.go b/fees/incrementor.go index 98bc317..2934166 100644 --- a/fees/incrementor.go +++ b/fees/incrementor.go @@ -32,17 +32,22 @@ import ( // GasPriceIncremenetor exposes a way automatically increment gas fees // for transactions in a preconfigured manner. type GasPriceIncremenetor struct { - pullInterval time.Duration - storage Storage bc MultichainClient + + cfg GasIncrementorConfig signers safeSigners - logFn LogFunc syncer *syncer + logFn LogFunc + stop chan struct{} + once sync.Once +} - stop chan struct{} - once sync.Once +// GasIncrementorConfig is provided to the incrementor to configure it. +type GasIncrementorConfig struct { + PullInterval time.Duration + MaxQueuePerSigner int } // Storage is given to the Incremeter to be used to @@ -57,6 +62,9 @@ type Storage interface { // Entries should be filtered by possible signers. If incrementor cannot sign the transaction // it should not received it. GetIncrementorTransactionsToCheck(possibleSigners []string) (tx []Transaction, err error) + + // GasIncrementorSenderQueue returns the length of a queue for a single sender. + GetIncrementorSenderQueue(sender string) (length int, err error) } // MultichainClient handles calls to BC. @@ -70,12 +78,12 @@ type MultichainClient interface { type LogFunc func(Transaction, error) // NewGasPriceIncremenetor returns a new incrementer instance. -func NewGasPriceIncremenetor(pullInterval time.Duration, storage Storage, cl MultichainClient, signers Signers) *GasPriceIncremenetor { +func NewGasPriceIncremenetor(cfg GasIncrementorConfig, storage Storage, cl MultichainClient, signers Signers) *GasPriceIncremenetor { return &GasPriceIncremenetor{ - pullInterval: pullInterval, - storage: storage, bc: cl, + + cfg: cfg, signers: safeSigners{ signers: signers, }, @@ -106,7 +114,7 @@ func (i *GasPriceIncremenetor) Run() { case <-i.stop: return - case <-time.After(i.pullInterval): + case <-time.After(i.cfg.PullInterval): txs, err := i.storage.GetIncrementorTransactionsToCheck(i.signers.getSigners()) if err != nil { continue @@ -147,6 +155,22 @@ func (i *GasPriceIncremenetor) InsertInitial(tx *types.Transaction, opts Transac return i.storage.UpsertIncrementorTransaction(*newTx) } +// CanSign returns if incrementor is able to sign transactions for the given sender. +func (i *GasPriceIncremenetor) CanSign(sender common.Address) bool { + _, ok := i.signers.getSignerFunc(sender.Hex()) + return ok +} + +// CanQueue returns if incrementor is able to queue a transaction +func (i *GasPriceIncremenetor) CanQueue(sender common.Address) (bool, error) { + length, err := i.storage.GetIncrementorSenderQueue(sender.Hex()) + if err != nil { + return false, err + } + + return length < i.cfg.MaxQueuePerSigner, nil +} + // tryWatch will try to watch a transaction. // If a transaction is already being watched, it will get skipped. func (i *GasPriceIncremenetor) tryWatch(tx Transaction) { @@ -419,7 +443,7 @@ func (s *safeSigners) getSignerFunc(senderAddressHex string) (SignatureFunc, boo // TODO: Remove later. Left for backwards compatability. // If only one signer is present and senderAddress is `""` return first signer. - if len(s.signers) == 1 && senderAddressHex == "" { + if len(s.signers) == 1 && (senderAddressHex == "" || senderAddressHex == common.HexToAddress("").Hex()) { for _, v := range s.signers { return v, true } diff --git a/fees/incrementor_test.go b/fees/incrementor_test.go index 545a266..e03cf51 100644 --- a/fees/incrementor_test.go +++ b/fees/incrementor_test.go @@ -33,6 +33,10 @@ import ( func TestGasPriceIncrementor(t *testing.T) { chid := int64(9223372036854775790) + cfg := GasIncrementorConfig{ + PullInterval: time.Millisecond, + MaxQueuePerSigner: 100, + } t.Run("gas price is increased and tx is successfull", func(t *testing.T) { originalGasPrice := big.NewInt(1) org := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, originalGasPrice, []byte{}) @@ -42,7 +46,7 @@ func TestGasPriceIncrementor(t *testing.T) { sender := common.HexToAddress("") sg := signer{} - inc := NewGasPriceIncremenetor(time.Millisecond, st, c, map[common.Address]SignatureFunc{ + inc := NewGasPriceIncremenetor(cfg, st, c, map[common.Address]SignatureFunc{ sender: sg.SignatureFunc, }) go inc.Run() @@ -82,7 +86,7 @@ func TestGasPriceIncrementor(t *testing.T) { sender := common.HexToAddress("") sg := signer{} - inc := NewGasPriceIncremenetor(time.Millisecond, st, c, map[common.Address]SignatureFunc{ + inc := NewGasPriceIncremenetor(cfg, st, c, map[common.Address]SignatureFunc{ sender: sg.SignatureFunc, }) go inc.Run() @@ -123,7 +127,7 @@ func TestGasPriceIncrementor(t *testing.T) { sender := common.HexToAddress("") sg := signer{} - inc := NewGasPriceIncremenetor(time.Millisecond, st, c, map[common.Address]SignatureFunc{ + inc := NewGasPriceIncremenetor(cfg, st, c, map[common.Address]SignatureFunc{ sender: sg.SignatureFunc, }) go inc.Run() @@ -161,7 +165,7 @@ func TestGasPriceIncrementor(t *testing.T) { sender := common.HexToAddress("") sg := signer{} - inc := NewGasPriceIncremenetor(time.Millisecond, st, c, map[common.Address]SignatureFunc{ + inc := NewGasPriceIncremenetor(cfg, st, c, map[common.Address]SignatureFunc{ sender: sg.SignatureFunc, }) assert.Error(t, inc.InsertInitial(org, TransactionOpts{}, sender)) @@ -219,6 +223,10 @@ func (s *mockStorage) GetIncrementorTransactionsToCheck(signers []string) (tx [] return give, nil } +func (s *mockStorage) GetIncrementorSenderQueue(sender string) (length int, err error) { + return 0, nil +} + type mockClient struct { gasTreshold *big.Int currentGas *big.Int From da8307ace98ce5c305349c17863605bbadccfec6 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Wed, 23 Jun 2021 12:22:19 +0300 Subject: [PATCH 11/14] Add provider channel for withdrawal to client --- client/bc.go | 1 + client/client.go | 34 ++++++++++++++++++++++++++++++++++ client/multichain_client.go | 8 ++++++++ client/with_dry_runs.go | 4 ++++ 4 files changed, 47 insertions(+) diff --git a/client/bc.go b/client/bc.go index b0db542..5a2879e 100644 --- a/client/bc.go +++ b/client/bc.go @@ -31,6 +31,7 @@ type BC interface { GetBeneficiary(registryAddress, identity common.Address) (common.Address, error) GetLastRegistryNonce(registry common.Address) (*big.Int, error) GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) + GetProvidersWithdrawalChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck common.Address) (bool, error) IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) diff --git a/client/client.go b/client/client.go index 0de0971..2fbe067 100644 --- a/client/client.go +++ b/client/client.go @@ -208,6 +208,27 @@ func (bc *Blockchain) GetProviderChannel(hermesAddress common.Address, addressTo return ch, errors.Wrap(err, "could not get provider channel from bc") } +// GetProviderChannel returns the provider channel +func (bc *Blockchain) GetProvidersWithdrawalChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) { + addressBytes, err := bc.getProviderChannelAddressForWithdrawalBytes(hermesAddress, addressToCheck) + if err != nil { + return ProviderChannel{}, errors.Wrap(err, "could not calculate provider channel address") + } + caller, err := bindings.NewHermesImplementationCaller(hermesAddress, bc.ethClient.Client()) + if err != nil { + return ProviderChannel{}, errors.Wrap(err, "could not create hermes caller") + } + + ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout) + defer cancel() + + ch, err := caller.Channels(&bind.CallOpts{ + Pending: pending, + Context: ctx, + }, addressBytes) + return ch, errors.Wrap(err, "could not get provider channel from bc") +} + func (bc *Blockchain) getProviderChannelStake(hermesAddress common.Address, addressToCheck common.Address) (*big.Int, error) { ch, err := bc.GetProviderChannel(hermesAddress, addressToCheck, false) return ch.Stake, errors.Wrap(err, "could not get provider channel from bc") @@ -238,6 +259,19 @@ func (bc *Blockchain) getProviderChannelAddressBytes(hermesAddress, addressToChe return addressBytes, nil } +func (bc *Blockchain) getProviderChannelAddressForWithdrawalBytes(hermesAddress, addressToCheck common.Address) ([32]byte, error) { + addressBytes := [32]byte{} + + addr, err := crypto.GenerateProviderChannelIDForPayAndSettle(addressToCheck.Hex(), hermesAddress.Hex()) + if err != nil { + return addressBytes, errors.Wrap(err, "could not generate channel address") + } + + copy(addressBytes[:], crypto.Pad(common.Hex2Bytes(strings.TrimPrefix(addr, "0x")), 32)) + + return addressBytes, nil +} + // SubscribeToPromiseSettledEvent subscribes to promise settled events func (bc *Blockchain) SubscribeToPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) { addr, err := bc.getProviderChannelAddressBytes(hermesID, providerID) diff --git a/client/multichain_client.go b/client/multichain_client.go index 32dc5c6..6282bf9 100644 --- a/client/multichain_client.go +++ b/client/multichain_client.go @@ -486,3 +486,11 @@ func (mbc *MultichainBlockchainClient) CustodyTransferTokens(chainID int64, req } return bc.CustodyTransferTokens(req) } + +func (mbc *MultichainBlockchainClient) GetProvidersWithdrawalChannel(chainID int64, hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) { + bc, err := mbc.getClientByChain(chainID) + if err != nil { + return ProviderChannel{}, err + } + return bc.GetProvidersWithdrawalChannel(hermesAddress, addressToCheck, pending) +} diff --git a/client/with_dry_runs.go b/client/with_dry_runs.go index 326ca23..aa7efc0 100644 --- a/client/with_dry_runs.go +++ b/client/with_dry_runs.go @@ -370,3 +370,7 @@ func (cwdr *WithDryRuns) RewarderTotalClaimed(rewarderAddress common.Address) (* func (cwdr *WithDryRuns) CustodyTransferTokens(req CustodyTokensTransfer) (*types.Transaction, error) { return cwdr.bc.CustodyTransferTokens(req) } + +func (cwdr *WithDryRuns) GetProvidersWithdrawalChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) { + return cwdr.bc.GetProvidersWithdrawalChannel(hermesAddress, addressToCheck, pending) +} From 6713a728aea080507b77ca484654238d79af64fb Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Wed, 23 Jun 2021 12:50:35 +0300 Subject: [PATCH 12/14] Add ability to subscribe to settlements of withdrawal --- client/bc.go | 1 + client/client.go | 9 +++++++++ client/multichain_client.go | 8 ++++++++ client/with_dry_runs.go | 4 ++++ 4 files changed, 22 insertions(+) diff --git a/client/bc.go b/client/bc.go index 5a2879e..be09915 100644 --- a/client/bc.go +++ b/client/bc.go @@ -32,6 +32,7 @@ type BC interface { GetLastRegistryNonce(registry common.Address) (*big.Int, error) GetChannelImplementationByVersion(registryID common.Address, version *big.Int) (common.Address, error) GetProvidersWithdrawalChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) + SubscribeToWithdrawalPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) IsRegisteredAsProvider(hermesAddress, registryAddress, addressToCheck common.Address) (bool, error) IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) diff --git a/client/client.go b/client/client.go index 2fbe067..fdaf71f 100644 --- a/client/client.go +++ b/client/client.go @@ -281,6 +281,15 @@ func (bc *Blockchain) SubscribeToPromiseSettledEvent(providerID, hermesID common return bc.SubscribeToPromiseSettledEventByChannelID(hermesID, [][32]byte{addr}) } +// SubscribeToWithdrawalPromiseSettledEvent subscribes to withdrawal promise settled events +func (bc *Blockchain) SubscribeToWithdrawalPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) { + addr, err := bc.getProviderChannelAddressForWithdrawalBytes(hermesID, providerID) + if err != nil { + return sink, cancel, errors.Wrap(err, "could not get provider channel address") + } + return bc.SubscribeToPromiseSettledEventByChannelID(hermesID, [][32]byte{addr}) +} + // IsRegistered checks wether the given identity is registered or not func (bc *Blockchain) IsRegistered(registryAddress, addressToCheck common.Address) (bool, error) { caller, err := bindings.NewRegistryCaller(registryAddress, bc.ethClient.Client()) diff --git a/client/multichain_client.go b/client/multichain_client.go index 6282bf9..dc69c45 100644 --- a/client/multichain_client.go +++ b/client/multichain_client.go @@ -494,3 +494,11 @@ func (mbc *MultichainBlockchainClient) GetProvidersWithdrawalChannel(chainID int } return bc.GetProvidersWithdrawalChannel(hermesAddress, addressToCheck, pending) } + +func (mbc *MultichainBlockchainClient) SubscribeToWithdrawalPromiseSettledEvent(chainID int64, providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) { + bc, err := mbc.getClientByChain(chainID) + if err != nil { + return nil, func() {}, err + } + return bc.SubscribeToWithdrawalPromiseSettledEvent(providerID, hermesID) +} diff --git a/client/with_dry_runs.go b/client/with_dry_runs.go index aa7efc0..94a54c3 100644 --- a/client/with_dry_runs.go +++ b/client/with_dry_runs.go @@ -374,3 +374,7 @@ func (cwdr *WithDryRuns) CustodyTransferTokens(req CustodyTokensTransfer) (*type func (cwdr *WithDryRuns) GetProvidersWithdrawalChannel(hermesAddress common.Address, addressToCheck common.Address, pending bool) (ProviderChannel, error) { return cwdr.bc.GetProvidersWithdrawalChannel(hermesAddress, addressToCheck, pending) } + +func (cwdr *WithDryRuns) SubscribeToWithdrawalPromiseSettledEvent(providerID, hermesID common.Address) (sink chan *bindings.HermesImplementationPromiseSettled, cancel func(), err error) { + return cwdr.bc.SubscribeToWithdrawalPromiseSettledEvent(providerID, hermesID) +} From 5c61879c24d0a977623a02b890bcb1abb3082e08 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Mon, 12 Jul 2021 14:36:24 +0300 Subject: [PATCH 13/14] Merge mater --- .gitlab-ci.yml | 7 +- Gopkg.lock | 469 ------ Gopkg.toml | 46 - client/bc.go | 146 ++ client/bc_test.go | 1572 ++++++++++++++++++ client/client.go | 29 +- client/counter.go | 41 - client/ethclient.go | 26 +- client/ethclient_test.go | 5 +- client/ethmulticlient.go | 710 ++++++++ client/ethmulticlient_test.go | 220 +++ client/with_dry_runs.go | 6 +- magefile.go | 4 + {fees => transfer}/gas/eth.go | 12 +- {fees => transfer}/gas/matic.go | 0 {fees => transfer}/gas/multichain_station.go | 0 {fees => transfer}/gas/static.go | 0 {fees => transfer}/gas/station.go | 0 {fees => transfer}/handler.go | 8 +- {fees => transfer}/incrementor.go | 2 +- {fees => transfer}/incrementor_test.go | 2 +- {fees => transfer}/price/coinranking.go | 0 {fees => transfer}/price/gecko.go | 0 transfer/queue.go | 120 ++ transfer/queue_test.go | 56 + {fees => transfer}/transaction.go | 2 +- 26 files changed, 2884 insertions(+), 599 deletions(-) delete mode 100644 Gopkg.lock delete mode 100644 Gopkg.toml create mode 100644 client/bc_test.go delete mode 100644 client/counter.go create mode 100644 client/ethmulticlient.go create mode 100644 client/ethmulticlient_test.go rename {fees => transfer}/gas/eth.go (94%) rename {fees => transfer}/gas/matic.go (100%) rename {fees => transfer}/gas/multichain_station.go (100%) rename {fees => transfer}/gas/static.go (100%) rename {fees => transfer}/gas/station.go (100%) rename {fees => transfer}/handler.go (94%) rename {fees => transfer}/incrementor.go (99%) rename {fees => transfer}/incrementor_test.go (99%) rename {fees => transfer}/price/coinranking.go (100%) rename {fees => transfer}/price/gecko.go (100%) create mode 100644 transfer/queue.go create mode 100644 transfer/queue_test.go rename {fees => transfer}/transaction.go (99%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c61e3a1..151da21 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,6 @@ stages: - check + - test variables: BUILD_COMMIT: $CI_COMMIT_SHORT_SHA @@ -23,7 +24,7 @@ generate: tags: [go] script: go run mage.go -v generate -copyright: - stage: check +test: + stage: test tags: [go] - script: go run mage.go -v checkCopyright + script: go run mage.go -v test diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index e6ae9fb..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,469 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - digest = "1:f96ba6ecca7ba87b1dddd70ae38cfc4ce5ea844f58d1f728e121d2e29cdfb8a2" - name = "github.com/allegro/bigcache" - packages = [ - ".", - "queue", - ] - pruneopts = "UT" - revision = "84a0ff3f153cbd7e280a19029a864bb04b504e62" - version = "v1.2.0" - -[[projects]] - branch = "master" - digest = "1:7d191fd0c54ff370eaf6116a14dafe2a328df487baea280699f597aae858d00d" - name = "github.com/aristanetworks/goarista" - packages = ["monotime"] - pruneopts = "UT" - revision = "b9cf994f4e477e9851834c5a9f05dd96df7439d8" - -[[projects]] - branch = "master" - digest = "1:1f119122026d2fc746c30ff1fc564c6074b2f0e4449d4230146a3deec986bf43" - name = "github.com/btcsuite/btcd" - packages = ["btcec"] - pruneopts = "UT" - revision = "1432d294a5b055c297457c25434efbf13384cc46" - -[[projects]] - digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" - name = "github.com/davecgh/go-spew" - packages = ["spew"] - pruneopts = "UT" - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" - -[[projects]] - digest = "1:c166378e8ab0f794f293dfb941d250dd70b035b05dec58879f717621d0fe1714" - name = "github.com/deckarep/golang-set" - packages = ["."] - pruneopts = "UT" - revision = "1d4478f51bed434f1dadf96dcd9b43aabac66795" - version = "v1.7" - -[[projects]] - digest = "1:edb569dd02419a41ddd98768cc0e7aec922ef19dae139731e5ca750afcf6f4c5" - name = "github.com/edsrzf/mmap-go" - packages = ["."] - pruneopts = "UT" - revision = "188cc3b666ba704534fa4f96e9e61f21f1e1ba7c" - version = "v1.0.0" - -[[projects]] - digest = "1:2b2daa41f40acd66f4aa0ae213bfd286096663c999a26deb773127b7864c6bd0" - name = "github.com/elastic/gosigar" - packages = [ - ".", - "sys/windows", - ] - pruneopts = "UT" - revision = "7aef3366157f2bfdf3e068f73ce7193573e88e0c" - version = "v0.10.5" - -[[projects]] - digest = "1:ed15e40a1eed1b01ada3afb803c5a29f9c3c9b4a275c9d834e1268756664ce7d" - name = "github.com/ethereum/go-ethereum" - packages = [ - ".", - "accounts", - "accounts/abi", - "accounts/abi/bind", - "accounts/abi/bind/backends", - "accounts/external", - "accounts/keystore", - "accounts/scwallet", - "accounts/usbwallet", - "accounts/usbwallet/trezor", - "common", - "common/bitutil", - "common/hexutil", - "common/math", - "common/mclock", - "common/prque", - "consensus", - "consensus/clique", - "consensus/ethash", - "consensus/misc", - "core", - "core/bloombits", - "core/rawdb", - "core/state", - "core/types", - "core/vm", - "crypto", - "crypto/blake2b", - "crypto/bn256", - "crypto/bn256/cloudflare", - "crypto/bn256/google", - "crypto/ecies", - "crypto/secp256k1", - "eth/downloader", - "eth/filters", - "ethclient", - "ethdb", - "ethdb/leveldb", - "ethdb/memorydb", - "event", - "internal/ethapi", - "log", - "metrics", - "p2p", - "p2p/discover", - "p2p/discv5", - "p2p/enode", - "p2p/enr", - "p2p/nat", - "p2p/netutil", - "params", - "rlp", - "rpc", - "signer/core", - "signer/storage", - "trie", - ] - pruneopts = "T" - revision = "bd05968077f27f7eb083404dd8448157996a8788" - version = "v1.9.6" - -[[projects]] - branch = "master" - digest = "1:a7e69236b403d78ca6a00e15a4030e34f99ffdb8be8dc71611361bf8f3d0e8a4" - name = "github.com/gballet/go-libpcsclite" - packages = ["."] - pruneopts = "UT" - revision = "2772fd86a8ff4306d2749f610a386bfee9e0d727" - -[[projects]] - digest = "1:c4a2528ccbcabf90f9f3c464a5fc9e302d592861bbfd0b7135a7de8a943d0406" - name = "github.com/go-stack/stack" - packages = ["."] - pruneopts = "UT" - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" - -[[projects]] - branch = "master" - digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467" - name = "github.com/golang/glog" - packages = ["."] - pruneopts = "UT" - revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" - -[[projects]] - digest = "1:500eb6e1e42991b51d2cc0c5bc9e47043f7eec8fe4a9b100b85abf49cfb910db" - name = "github.com/golang/protobuf" - packages = [ - "proto", - "protoc-gen-go/descriptor", - ] - pruneopts = "UT" - revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7" - version = "v1.3.2" - -[[projects]] - branch = "master" - digest = "1:4a0c6bb4805508a6287675fac876be2ac1182539ca8a32468d8128882e9d5009" - name = "github.com/golang/snappy" - packages = ["."] - pruneopts = "UT" - revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" - -[[projects]] - digest = "1:e62657cca9badaa308d86e7716083e4c5933bb78e30a17743fc67f50be26f6f4" - name = "github.com/gorilla/websocket" - packages = ["."] - pruneopts = "UT" - revision = "c3e18be99d19e6b3e8f1559eea2c161a665c4b6b" - version = "v1.4.1" - -[[projects]] - digest = "1:c77361e611524ec8f2ad37c408c3c916111a70b6acf806a1200855696bf8fa4d" - name = "github.com/hashicorp/golang-lru" - packages = [ - ".", - "simplelru", - ] - pruneopts = "UT" - revision = "7f827b33c0f158ec5dfbba01bb0b14a4541fd81d" - version = "v0.5.3" - -[[projects]] - digest = "1:c00cc6d95a674b4b923ac069d364445043bc67836e9bd8aeff8440cfbe6a2cc7" - name = "github.com/huin/goupnp" - packages = [ - ".", - "dcps/internetgateway1", - "dcps/internetgateway2", - "httpu", - "scpd", - "soap", - "ssdp", - ] - pruneopts = "UT" - revision = "656e61dfadd241c7cbdd22a023fa81ecb6860ea8" - version = "v1.0.0" - -[[projects]] - digest = "1:32b82e71cf24f8b78323e0d7903c4b90278486283965aa2a19b1ea13763b8f34" - name = "github.com/jackpal/go-nat-pmp" - packages = ["."] - pruneopts = "UT" - revision = "c9cfead9f2a36ddf3daa40ba269aa7f4bbba6b62" - version = "v1.0.1" - -[[projects]] - branch = "master" - digest = "1:a70b77747a648d33962db2393796a89708af3b98f5710e15063e7547e0e32dba" - name = "github.com/joincivil/go-common" - packages = [ - "pkg/eth", - "pkg/generated/contract", - "pkg/jobs", - "pkg/time", - ] - pruneopts = "UT" - revision = "88ecdf41b6b6318c12974c020b6bf6a3ec602d6b" - -[[projects]] - branch = "master" - digest = "1:4f3063f3c9d368995cb36f702d0505a3a8eac0812629eefad8e45a69aef32a52" - name = "github.com/karalabe/usb" - packages = ["."] - pruneopts = "UT" - revision = "51dc0efba3568b598359930901dc6647e9b2c6a1" - -[[projects]] - digest = "1:0356f3312c9bd1cbeda81505b7fd437501d8e778ab66998ef69f00d7f9b3a0d7" - name = "github.com/mattn/go-runewidth" - packages = ["."] - pruneopts = "UT" - revision = "3ee7d812e62a0804a7d0a324e0249ca2db3476d3" - version = "v0.0.4" - -[[projects]] - digest = "1:abcdbf03ca6ca13d3697e2186edc1f33863bbdac2b3a44dfa39015e8903f7409" - name = "github.com/olekukonko/tablewriter" - packages = ["."] - pruneopts = "UT" - revision = "e6d60cf7ba1f42d86d54cdf5508611c4aafb3970" - version = "v0.0.1" - -[[projects]] - digest = "1:361de06aa7ae272616cbe71c3994a654cc6316324e30998e650f7765b20c5b33" - name = "github.com/pborman/uuid" - packages = ["."] - pruneopts = "UT" - revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53" - version = "v1.1" - -[[projects]] - digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b" - name = "github.com/pkg/errors" - packages = ["."] - pruneopts = "UT" - revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" - version = "v0.8.1" - -[[projects]] - digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - pruneopts = "UT" - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - digest = "1:19a227084137c73d7a519ff90acc9fa69855c2ba134bb9c7dfe94e9ad2949c64" - name = "github.com/prometheus/tsdb" - packages = ["fileutil"] - pruneopts = "UT" - revision = "7762249358193da791ec62e72b080d908f96e776" - version = "v0.10.0" - -[[projects]] - digest = "1:31d83d1b1c288073c91abadee3caec87de2a1fb5dbe589039264a802e67a26b8" - name = "github.com/rjeczalik/notify" - packages = ["."] - pruneopts = "UT" - revision = "69d839f37b13a8cb7a78366f7633a4071cb43be7" - version = "v0.9.2" - -[[projects]] - digest = "1:c5dfe46811af7e2eff7c11fc84b6c841520338613c056f659f262d5a4fb42fa8" - name = "github.com/rs/cors" - packages = ["."] - pruneopts = "UT" - revision = "db0fe48135e83b5812a5a31be0eea66984b1b521" - version = "v1.7.0" - -[[projects]] - branch = "develop" - digest = "1:6deccaba5762377091f2e5b26dba70e630e01edb3f95d1a6a59d9b098bd4358f" - name = "github.com/status-im/keycard-go" - packages = ["derivationpath"] - pruneopts = "UT" - revision = "d95853db0f480b9d6379009500acf44b21dc0be6" - -[[projects]] - digest = "1:266e2f508feb9a9a765bfeb74d116a88514248b2f8428788dcce574bd026b9c0" - name = "github.com/steakknife/bloomfilter" - packages = ["."] - pruneopts = "UT" - revision = "99ee86d9200fcc2ffde62f508329bd6627c0a307" - version = "1.0.4" - -[[projects]] - digest = "1:5ca4bdccd72e66aaba5b52f9c4a21f1021102f0919432fe138ad5d48abf06833" - name = "github.com/steakknife/hamming" - packages = ["."] - pruneopts = "UT" - revision = "003c143a81c25ea5e263d692919c611c7122ae6b" - version = "0.2.5" - -[[projects]] - digest = "1:f85e109eda8f6080877185d1c39e98dd8795e1780c08beca28304b87fd855a1c" - name = "github.com/stretchr/testify" - packages = ["assert"] - pruneopts = "UT" - revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" - version = "v1.2.1" - -[[projects]] - digest = "1:c345767003e0d53971e0f409a42b875dab3fee7ec269557c863ebbb194341420" - name = "github.com/syndtr/goleveldb" - packages = [ - "leveldb", - "leveldb/cache", - "leveldb/comparer", - "leveldb/errors", - "leveldb/filter", - "leveldb/iterator", - "leveldb/journal", - "leveldb/memdb", - "leveldb/opt", - "leveldb/storage", - "leveldb/table", - "leveldb/util", - ] - pruneopts = "UT" - revision = "758128399b1df3a87e92df6c26c1d2063da8fabe" - -[[projects]] - digest = "1:91b40a2adb6b4ccd51b1dfb306edfa76139e1599b01666346085472b386f5447" - name = "github.com/tyler-smith/go-bip39" - packages = [ - ".", - "wordlists", - ] - pruneopts = "UT" - revision = "5e3853c3f4e1a44df487c7efeb064ee8b43755de" - version = "1.0.2" - -[[projects]] - branch = "master" - digest = "1:7dca0da64f5937af74f21618cdb812c8f16a7d042316dd5bf2f1dfd086be3fc6" - name = "github.com/wsddn/go-ecdh" - packages = ["."] - pruneopts = "UT" - revision = "48726bab92085232373de4ec5c51ce7b441c63a0" - -[[projects]] - branch = "master" - digest = "1:253f46fe0c82ccea63f1b93731ad3112d6112ea5bbce019bd8461c082742ccd0" - name = "golang.org/x/crypto" - packages = [ - "curve25519", - "pbkdf2", - "ripemd160", - "scrypt", - "sha3", - "ssh/terminal", - ] - pruneopts = "UT" - revision = "7f87c0fbb88b590338857bcb720678c2583d4dea" - -[[projects]] - branch = "master" - digest = "1:94002ae1eb37d085f9aca990b3246b0cf6f0d114b5c0924aedd8eaf2a912143f" - name = "golang.org/x/net" - packages = [ - "html", - "html/atom", - "html/charset", - ] - pruneopts = "UT" - revision = "ec77196f6094c3492a8b61f2c11cf937f78992ae" - -[[projects]] - branch = "master" - digest = "1:13459f490b4962ca181f4a9a92e54bbb6061273e32bcea54f2588ecbb38b765a" - name = "golang.org/x/sys" - packages = [ - "cpu", - "unix", - "windows", - ] - pruneopts = "UT" - revision = "7c87d13f8e835d2fb3a70a2912c811ed0c1d241b" - -[[projects]] - digest = "1:7570a3e4daa14b7627089e77ad8c714f5f36b4cf1b7dfd8510df7d6935dc42a0" - name = "golang.org/x/text" - packages = [ - "encoding", - "encoding/charmap", - "encoding/htmlindex", - "encoding/internal", - "encoding/internal/identifier", - "encoding/japanese", - "encoding/korean", - "encoding/simplifiedchinese", - "encoding/traditionalchinese", - "encoding/unicode", - "internal/gen", - "internal/language", - "internal/language/compact", - "internal/tag", - "internal/triegen", - "internal/ucd", - "internal/utf8internal", - "language", - "runes", - "transform", - "unicode/cldr", - "unicode/norm", - ] - pruneopts = "UT" - revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475" - version = "v0.3.2" - -[[projects]] - branch = "v2" - digest = "1:3d3f9391ab615be8655ae0d686a1564f3fec413979bb1aaf018bac1ec1bb1cc7" - name = "gopkg.in/natefinch/npipe.v2" - packages = ["."] - pruneopts = "UT" - revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/ethereum/go-ethereum", - "github.com/ethereum/go-ethereum/accounts", - "github.com/ethereum/go-ethereum/accounts/abi", - "github.com/ethereum/go-ethereum/accounts/abi/bind", - "github.com/ethereum/go-ethereum/accounts/keystore", - "github.com/ethereum/go-ethereum/common", - "github.com/ethereum/go-ethereum/core/types", - "github.com/ethereum/go-ethereum/crypto", - "github.com/ethereum/go-ethereum/event", - "github.com/joincivil/go-common/pkg/eth", - "github.com/pkg/errors", - "github.com/stretchr/testify/assert", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index 8996f26..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,46 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - -[[constraint]] - name = "github.com/ethereum/go-ethereum" - version = "=1.9.6" - -[[constraint]] - name = "github.com/stretchr/testify" - version = "1.2.1" - -[[override]] - name = "github.com/syndtr/goleveldb" - revision = "758128399b1df3a87e92df6c26c1d2063da8fabe" - -[prune] - go-tests = true - unused-packages = true - - [[prune.project]] - name = "github.com/ethereum/go-ethereum" - unused-packages = false - diff --git a/client/bc.go b/client/bc.go index be09915..fd3d952 100644 --- a/client/bc.go +++ b/client/bc.go @@ -1,6 +1,24 @@ +/* + * Copyright (C) 2021 The "MysteriumNetwork/payments" Authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package client import ( + "context" "math/big" "time" @@ -73,3 +91,131 @@ type BC interface { PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, error) IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) } + +// EtherClient interface implements all methods required for a EtherClient to work +type EtherClient interface { + Close() + // ChainId retrieves the current chain ID for transaction replay protection. + ChainID(ctx context.Context) (*big.Int, error) + // BlockByHash returns the given full block. + // + // Note that loading full blocks requires two requests. Use HeaderByHash + // if you don't need all transactions or uncle headers. + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) + // BlockByNumber returns a block from the current canonical chain. If number is nil, the + // latest known block is returned. + // + // Note that loading full blocks requires two requests. Use HeaderByNumber + // if you don't need all transactions or uncle headers. + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + // BlockNumber returns the most recent block number + BlockNumber(ctx context.Context) (uint64, error) + // HeaderByHash returns the block header with the given hash. + HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) + // HeaderByNumber returns a block header from the current canonical chain. If number is + // nil, the latest known header is returned. + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) + // TransactionByHash returns the transaction with the given hash. + TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) + // TransactionSender returns the sender address of the given transaction. The transaction + // must be known to the remote node and included in the blockchain at the given block and + // index. The sender is the one derived by the protocol at the time of inclusion. + // + // There is a fast-path for transactions retrieved by TransactionByHash and + // TransactionInBlock. Getting their sender address can be done without an RPC interaction. + TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) + // TransactionCount returns the total number of transactions in the given block. + TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) + // TransactionInBlock returns a single transaction at index in the given block. + TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) + // TransactionReceipt returns the receipt of a transaction by transaction hash. + // Note that the receipt is not available for pending transactions. + TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + // SyncProgress retrieves the current progress of the sync algorithm. If there's + // no sync currently running, it returns nil. + SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) + // SubscribeNewHead subscribes to notifications about the current blockchain head + // on the given channel. + SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) + // NetworkID returns the network ID (also known as the chain ID) for this chain. + NetworkID(ctx context.Context) (*big.Int, error) + // BalanceAt returns the wei balance of the given account. + // The block number can be nil, in which case the balance is taken from the latest known block. + BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) + // StorageAt returns the value of key in the contract storage of the given account. + // The block number can be nil, in which case the value is taken from the latest known block. + StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) + // CodeAt returns the contract code of the given account. + // The block number can be nil, in which case the code is taken from the latest known block. + CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) + // NonceAt returns the account nonce of the given account. + // The block number can be nil, in which case the nonce is taken from the latest known block. + NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) + // FilterLogs executes a filter query. + FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) + // SubscribeFilterLogs subscribes to the results of a streaming filter query. + SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) + // PendingBalanceAt returns the wei balance of the given account in the pending state. + PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) + // PendingStorageAt returns the value of key in the contract storage of the given account in the pending state. + PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) + // PendingCodeAt returns the contract code of the given account in the pending state. + PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) + // PendingNonceAt returns the account nonce of the given account in the pending state. + // This is the nonce that should be used for the next transaction. + PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) + // PendingTransactionCount returns the total number of transactions in the pending state. + PendingTransactionCount(ctx context.Context) (uint, error) + // CallContract executes a message call transaction, which is directly executed in the VM + // of the node, but never mined into the blockchain. + // + // blockNumber selects the block height at which the call runs. It can be nil, in which + // case the code is taken from the latest known block. Note that state from very old + // blocks might not be available. + CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) + // PendingCallContract executes a message call transaction using the EVM. + // The state seen by the contract call is the pending state. + PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) + // SuggestGasPrice retrieves the currently suggested gas price to allow a timely + // execution of a transaction. + SuggestGasPrice(ctx context.Context) (*big.Int, error) + // EstimateGas tries to estimate the gas needed to execute a specific transaction based on + // the current pending state of the backend blockchain. There is no guarantee that this is + // the true gas limit requirement as other transactions may be added or removed by miners, + // but it should provide a basis for setting a reasonable default. + EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) + // SendTransaction injects a signed transaction into the pending pool for execution. + // + // If the transaction was a contract creation use the TransactionReceipt method to get the + // contract address after the transaction has been mined. + SendTransaction(ctx context.Context, tx *types.Transaction) error +} + +// EthClientGetter wraps any eth clients. +type EthClientGetter interface { + // Client returns a client to use for making call to the eth blockchain. + Client() EtherClient + + // Address returns an address which was used to create a particular client + Address() string +} + +type DefaultEthClientGetter struct { + client EtherClient + address string +} + +func NewDefaultEthClientGetter(address string, cl EtherClient) EthClientGetter { + return &DefaultEthClientGetter{ + client: cl, + address: address, + } +} + +func (eth *DefaultEthClientGetter) Client() EtherClient { + return eth.client +} + +func (eth *DefaultEthClientGetter) Address() string { + return eth.address +} diff --git a/client/bc_test.go b/client/bc_test.go new file mode 100644 index 0000000..5480b59 --- /dev/null +++ b/client/bc_test.go @@ -0,0 +1,1572 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package client + +import ( + "context" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// Ensure, that EtherClientMock does implement EtherClient. +// If this is not the case, regenerate this file with moq. +var _ EtherClient = &EtherClientMock{} + +// EtherClientMock is a mock implementation of EtherClient. +// +// func TestSomethingThatUsesEtherClient(t *testing.T) { +// +// // make and configure a mocked EtherClient +// mockedEtherClient := &EtherClientMock{ +// BalanceAtFunc: func(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { +// panic("mock out the BalanceAt method") +// }, +// BlockByHashFunc: func(ctx context.Context, hash common.Hash) (*types.Block, error) { +// panic("mock out the BlockByHash method") +// }, +// BlockByNumberFunc: func(ctx context.Context, number *big.Int) (*types.Block, error) { +// panic("mock out the BlockByNumber method") +// }, +// BlockNumberFunc: func(ctx context.Context) (uint64, error) { +// panic("mock out the BlockNumber method") +// }, +// CallContractFunc: func(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { +// panic("mock out the CallContract method") +// }, +// ChainIDFunc: func(ctx context.Context) (*big.Int, error) { +// panic("mock out the ChainID method") +// }, +// CloseFunc: func() { +// panic("mock out the Close method") +// }, +// CodeAtFunc: func(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { +// panic("mock out the CodeAt method") +// }, +// EstimateGasFunc: func(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { +// panic("mock out the EstimateGas method") +// }, +// FilterLogsFunc: func(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { +// panic("mock out the FilterLogs method") +// }, +// HeaderByHashFunc: func(ctx context.Context, hash common.Hash) (*types.Header, error) { +// panic("mock out the HeaderByHash method") +// }, +// HeaderByNumberFunc: func(ctx context.Context, number *big.Int) (*types.Header, error) { +// panic("mock out the HeaderByNumber method") +// }, +// NetworkIDFunc: func(ctx context.Context) (*big.Int, error) { +// panic("mock out the NetworkID method") +// }, +// NonceAtFunc: func(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { +// panic("mock out the NonceAt method") +// }, +// PendingBalanceAtFunc: func(ctx context.Context, account common.Address) (*big.Int, error) { +// panic("mock out the PendingBalanceAt method") +// }, +// PendingCallContractFunc: func(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { +// panic("mock out the PendingCallContract method") +// }, +// PendingCodeAtFunc: func(ctx context.Context, account common.Address) ([]byte, error) { +// panic("mock out the PendingCodeAt method") +// }, +// PendingNonceAtFunc: func(ctx context.Context, account common.Address) (uint64, error) { +// panic("mock out the PendingNonceAt method") +// }, +// PendingStorageAtFunc: func(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { +// panic("mock out the PendingStorageAt method") +// }, +// PendingTransactionCountFunc: func(ctx context.Context) (uint, error) { +// panic("mock out the PendingTransactionCount method") +// }, +// SendTransactionFunc: func(ctx context.Context, tx *types.Transaction) error { +// panic("mock out the SendTransaction method") +// }, +// StorageAtFunc: func(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { +// panic("mock out the StorageAt method") +// }, +// SubscribeFilterLogsFunc: func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { +// panic("mock out the SubscribeFilterLogs method") +// }, +// SubscribeNewHeadFunc: func(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { +// panic("mock out the SubscribeNewHead method") +// }, +// SuggestGasPriceFunc: func(ctx context.Context) (*big.Int, error) { +// panic("mock out the SuggestGasPrice method") +// }, +// SyncProgressFunc: func(ctx context.Context) (*ethereum.SyncProgress, error) { +// panic("mock out the SyncProgress method") +// }, +// TransactionByHashFunc: func(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) { +// panic("mock out the TransactionByHash method") +// }, +// TransactionCountFunc: func(ctx context.Context, blockHash common.Hash) (uint, error) { +// panic("mock out the TransactionCount method") +// }, +// TransactionInBlockFunc: func(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { +// panic("mock out the TransactionInBlock method") +// }, +// TransactionReceiptFunc: func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { +// panic("mock out the TransactionReceipt method") +// }, +// TransactionSenderFunc: func(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { +// panic("mock out the TransactionSender method") +// }, +// } +// +// // use mockedEtherClient in code that requires EtherClient +// // and then make assertions. +// +// } +type EtherClientMock struct { + // BalanceAtFunc mocks the BalanceAt method. + BalanceAtFunc func(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) + + // BlockByHashFunc mocks the BlockByHash method. + BlockByHashFunc func(ctx context.Context, hash common.Hash) (*types.Block, error) + + // BlockByNumberFunc mocks the BlockByNumber method. + BlockByNumberFunc func(ctx context.Context, number *big.Int) (*types.Block, error) + + // BlockNumberFunc mocks the BlockNumber method. + BlockNumberFunc func(ctx context.Context) (uint64, error) + + // CallContractFunc mocks the CallContract method. + CallContractFunc func(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) + + // ChainIDFunc mocks the ChainID method. + ChainIDFunc func(ctx context.Context) (*big.Int, error) + + // CloseFunc mocks the Close method. + CloseFunc func() + + // CodeAtFunc mocks the CodeAt method. + CodeAtFunc func(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) + + // EstimateGasFunc mocks the EstimateGas method. + EstimateGasFunc func(ctx context.Context, msg ethereum.CallMsg) (uint64, error) + + // FilterLogsFunc mocks the FilterLogs method. + FilterLogsFunc func(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) + + // HeaderByHashFunc mocks the HeaderByHash method. + HeaderByHashFunc func(ctx context.Context, hash common.Hash) (*types.Header, error) + + // HeaderByNumberFunc mocks the HeaderByNumber method. + HeaderByNumberFunc func(ctx context.Context, number *big.Int) (*types.Header, error) + + // NetworkIDFunc mocks the NetworkID method. + NetworkIDFunc func(ctx context.Context) (*big.Int, error) + + // NonceAtFunc mocks the NonceAt method. + NonceAtFunc func(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) + + // PendingBalanceAtFunc mocks the PendingBalanceAt method. + PendingBalanceAtFunc func(ctx context.Context, account common.Address) (*big.Int, error) + + // PendingCallContractFunc mocks the PendingCallContract method. + PendingCallContractFunc func(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) + + // PendingCodeAtFunc mocks the PendingCodeAt method. + PendingCodeAtFunc func(ctx context.Context, account common.Address) ([]byte, error) + + // PendingNonceAtFunc mocks the PendingNonceAt method. + PendingNonceAtFunc func(ctx context.Context, account common.Address) (uint64, error) + + // PendingStorageAtFunc mocks the PendingStorageAt method. + PendingStorageAtFunc func(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) + + // PendingTransactionCountFunc mocks the PendingTransactionCount method. + PendingTransactionCountFunc func(ctx context.Context) (uint, error) + + // SendTransactionFunc mocks the SendTransaction method. + SendTransactionFunc func(ctx context.Context, tx *types.Transaction) error + + // StorageAtFunc mocks the StorageAt method. + StorageAtFunc func(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) + + // SubscribeFilterLogsFunc mocks the SubscribeFilterLogs method. + SubscribeFilterLogsFunc func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) + + // SubscribeNewHeadFunc mocks the SubscribeNewHead method. + SubscribeNewHeadFunc func(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) + + // SuggestGasPriceFunc mocks the SuggestGasPrice method. + SuggestGasPriceFunc func(ctx context.Context) (*big.Int, error) + + // SyncProgressFunc mocks the SyncProgress method. + SyncProgressFunc func(ctx context.Context) (*ethereum.SyncProgress, error) + + // TransactionByHashFunc mocks the TransactionByHash method. + TransactionByHashFunc func(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) + + // TransactionCountFunc mocks the TransactionCount method. + TransactionCountFunc func(ctx context.Context, blockHash common.Hash) (uint, error) + + // TransactionInBlockFunc mocks the TransactionInBlock method. + TransactionInBlockFunc func(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) + + // TransactionReceiptFunc mocks the TransactionReceipt method. + TransactionReceiptFunc func(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + + // TransactionSenderFunc mocks the TransactionSender method. + TransactionSenderFunc func(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) + + // calls tracks calls to the methods. + calls struct { + // BalanceAt holds details about calls to the BalanceAt method. + BalanceAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + // BlockNumber is the blockNumber argument value. + BlockNumber *big.Int + } + // BlockByHash holds details about calls to the BlockByHash method. + BlockByHash []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Hash is the hash argument value. + Hash common.Hash + } + // BlockByNumber holds details about calls to the BlockByNumber method. + BlockByNumber []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Number is the number argument value. + Number *big.Int + } + // BlockNumber holds details about calls to the BlockNumber method. + BlockNumber []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // CallContract holds details about calls to the CallContract method. + CallContract []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Msg is the msg argument value. + Msg ethereum.CallMsg + // BlockNumber is the blockNumber argument value. + BlockNumber *big.Int + } + // ChainID holds details about calls to the ChainID method. + ChainID []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // Close holds details about calls to the Close method. + Close []struct { + } + // CodeAt holds details about calls to the CodeAt method. + CodeAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + // BlockNumber is the blockNumber argument value. + BlockNumber *big.Int + } + // EstimateGas holds details about calls to the EstimateGas method. + EstimateGas []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Msg is the msg argument value. + Msg ethereum.CallMsg + } + // FilterLogs holds details about calls to the FilterLogs method. + FilterLogs []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Q is the q argument value. + Q ethereum.FilterQuery + } + // HeaderByHash holds details about calls to the HeaderByHash method. + HeaderByHash []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Hash is the hash argument value. + Hash common.Hash + } + // HeaderByNumber holds details about calls to the HeaderByNumber method. + HeaderByNumber []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Number is the number argument value. + Number *big.Int + } + // NetworkID holds details about calls to the NetworkID method. + NetworkID []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // NonceAt holds details about calls to the NonceAt method. + NonceAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + // BlockNumber is the blockNumber argument value. + BlockNumber *big.Int + } + // PendingBalanceAt holds details about calls to the PendingBalanceAt method. + PendingBalanceAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + } + // PendingCallContract holds details about calls to the PendingCallContract method. + PendingCallContract []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Msg is the msg argument value. + Msg ethereum.CallMsg + } + // PendingCodeAt holds details about calls to the PendingCodeAt method. + PendingCodeAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + } + // PendingNonceAt holds details about calls to the PendingNonceAt method. + PendingNonceAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + } + // PendingStorageAt holds details about calls to the PendingStorageAt method. + PendingStorageAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + // Key is the key argument value. + Key common.Hash + } + // PendingTransactionCount holds details about calls to the PendingTransactionCount method. + PendingTransactionCount []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // SendTransaction holds details about calls to the SendTransaction method. + SendTransaction []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Tx is the tx argument value. + Tx *types.Transaction + } + // StorageAt holds details about calls to the StorageAt method. + StorageAt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Account is the account argument value. + Account common.Address + // Key is the key argument value. + Key common.Hash + // BlockNumber is the blockNumber argument value. + BlockNumber *big.Int + } + // SubscribeFilterLogs holds details about calls to the SubscribeFilterLogs method. + SubscribeFilterLogs []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Q is the q argument value. + Q ethereum.FilterQuery + // Ch is the ch argument value. + Ch chan<- types.Log + } + // SubscribeNewHead holds details about calls to the SubscribeNewHead method. + SubscribeNewHead []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Ch is the ch argument value. + Ch chan<- *types.Header + } + // SuggestGasPrice holds details about calls to the SuggestGasPrice method. + SuggestGasPrice []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // SyncProgress holds details about calls to the SyncProgress method. + SyncProgress []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // TransactionByHash holds details about calls to the TransactionByHash method. + TransactionByHash []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Hash is the hash argument value. + Hash common.Hash + } + // TransactionCount holds details about calls to the TransactionCount method. + TransactionCount []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // BlockHash is the blockHash argument value. + BlockHash common.Hash + } + // TransactionInBlock holds details about calls to the TransactionInBlock method. + TransactionInBlock []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // BlockHash is the blockHash argument value. + BlockHash common.Hash + // Index is the index argument value. + Index uint + } + // TransactionReceipt holds details about calls to the TransactionReceipt method. + TransactionReceipt []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // TxHash is the txHash argument value. + TxHash common.Hash + } + // TransactionSender holds details about calls to the TransactionSender method. + TransactionSender []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Tx is the tx argument value. + Tx *types.Transaction + // Block is the block argument value. + Block common.Hash + // Index is the index argument value. + Index uint + } + } + lockBalanceAt sync.RWMutex + lockBlockByHash sync.RWMutex + lockBlockByNumber sync.RWMutex + lockBlockNumber sync.RWMutex + lockCallContract sync.RWMutex + lockChainID sync.RWMutex + lockClose sync.RWMutex + lockCodeAt sync.RWMutex + lockEstimateGas sync.RWMutex + lockFilterLogs sync.RWMutex + lockHeaderByHash sync.RWMutex + lockHeaderByNumber sync.RWMutex + lockNetworkID sync.RWMutex + lockNonceAt sync.RWMutex + lockPendingBalanceAt sync.RWMutex + lockPendingCallContract sync.RWMutex + lockPendingCodeAt sync.RWMutex + lockPendingNonceAt sync.RWMutex + lockPendingStorageAt sync.RWMutex + lockPendingTransactionCount sync.RWMutex + lockSendTransaction sync.RWMutex + lockStorageAt sync.RWMutex + lockSubscribeFilterLogs sync.RWMutex + lockSubscribeNewHead sync.RWMutex + lockSuggestGasPrice sync.RWMutex + lockSyncProgress sync.RWMutex + lockTransactionByHash sync.RWMutex + lockTransactionCount sync.RWMutex + lockTransactionInBlock sync.RWMutex + lockTransactionReceipt sync.RWMutex + lockTransactionSender sync.RWMutex +} + +// BalanceAt calls BalanceAtFunc. +func (mock *EtherClientMock) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { + if mock.BalanceAtFunc == nil { + panic("EtherClientMock.BalanceAtFunc: method is nil but EtherClient.BalanceAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int + }{ + Ctx: ctx, + Account: account, + BlockNumber: blockNumber, + } + mock.lockBalanceAt.Lock() + mock.calls.BalanceAt = append(mock.calls.BalanceAt, callInfo) + mock.lockBalanceAt.Unlock() + return mock.BalanceAtFunc(ctx, account, blockNumber) +} + +// BalanceAtCalls gets all the calls that were made to BalanceAt. +// Check the length with: +// len(mockedEtherClient.BalanceAtCalls()) +func (mock *EtherClientMock) BalanceAtCalls() []struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int +} { + var calls []struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int + } + mock.lockBalanceAt.RLock() + calls = mock.calls.BalanceAt + mock.lockBalanceAt.RUnlock() + return calls +} + +// BlockByHash calls BlockByHashFunc. +func (mock *EtherClientMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + if mock.BlockByHashFunc == nil { + panic("EtherClientMock.BlockByHashFunc: method is nil but EtherClient.BlockByHash was just called") + } + callInfo := struct { + Ctx context.Context + Hash common.Hash + }{ + Ctx: ctx, + Hash: hash, + } + mock.lockBlockByHash.Lock() + mock.calls.BlockByHash = append(mock.calls.BlockByHash, callInfo) + mock.lockBlockByHash.Unlock() + return mock.BlockByHashFunc(ctx, hash) +} + +// BlockByHashCalls gets all the calls that were made to BlockByHash. +// Check the length with: +// len(mockedEtherClient.BlockByHashCalls()) +func (mock *EtherClientMock) BlockByHashCalls() []struct { + Ctx context.Context + Hash common.Hash +} { + var calls []struct { + Ctx context.Context + Hash common.Hash + } + mock.lockBlockByHash.RLock() + calls = mock.calls.BlockByHash + mock.lockBlockByHash.RUnlock() + return calls +} + +// BlockByNumber calls BlockByNumberFunc. +func (mock *EtherClientMock) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + if mock.BlockByNumberFunc == nil { + panic("EtherClientMock.BlockByNumberFunc: method is nil but EtherClient.BlockByNumber was just called") + } + callInfo := struct { + Ctx context.Context + Number *big.Int + }{ + Ctx: ctx, + Number: number, + } + mock.lockBlockByNumber.Lock() + mock.calls.BlockByNumber = append(mock.calls.BlockByNumber, callInfo) + mock.lockBlockByNumber.Unlock() + return mock.BlockByNumberFunc(ctx, number) +} + +// BlockByNumberCalls gets all the calls that were made to BlockByNumber. +// Check the length with: +// len(mockedEtherClient.BlockByNumberCalls()) +func (mock *EtherClientMock) BlockByNumberCalls() []struct { + Ctx context.Context + Number *big.Int +} { + var calls []struct { + Ctx context.Context + Number *big.Int + } + mock.lockBlockByNumber.RLock() + calls = mock.calls.BlockByNumber + mock.lockBlockByNumber.RUnlock() + return calls +} + +// BlockNumber calls BlockNumberFunc. +func (mock *EtherClientMock) BlockNumber(ctx context.Context) (uint64, error) { + if mock.BlockNumberFunc == nil { + panic("EtherClientMock.BlockNumberFunc: method is nil but EtherClient.BlockNumber was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockBlockNumber.Lock() + mock.calls.BlockNumber = append(mock.calls.BlockNumber, callInfo) + mock.lockBlockNumber.Unlock() + return mock.BlockNumberFunc(ctx) +} + +// BlockNumberCalls gets all the calls that were made to BlockNumber. +// Check the length with: +// len(mockedEtherClient.BlockNumberCalls()) +func (mock *EtherClientMock) BlockNumberCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockBlockNumber.RLock() + calls = mock.calls.BlockNumber + mock.lockBlockNumber.RUnlock() + return calls +} + +// CallContract calls CallContractFunc. +func (mock *EtherClientMock) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + if mock.CallContractFunc == nil { + panic("EtherClientMock.CallContractFunc: method is nil but EtherClient.CallContract was just called") + } + callInfo := struct { + Ctx context.Context + Msg ethereum.CallMsg + BlockNumber *big.Int + }{ + Ctx: ctx, + Msg: msg, + BlockNumber: blockNumber, + } + mock.lockCallContract.Lock() + mock.calls.CallContract = append(mock.calls.CallContract, callInfo) + mock.lockCallContract.Unlock() + return mock.CallContractFunc(ctx, msg, blockNumber) +} + +// CallContractCalls gets all the calls that were made to CallContract. +// Check the length with: +// len(mockedEtherClient.CallContractCalls()) +func (mock *EtherClientMock) CallContractCalls() []struct { + Ctx context.Context + Msg ethereum.CallMsg + BlockNumber *big.Int +} { + var calls []struct { + Ctx context.Context + Msg ethereum.CallMsg + BlockNumber *big.Int + } + mock.lockCallContract.RLock() + calls = mock.calls.CallContract + mock.lockCallContract.RUnlock() + return calls +} + +// ChainID calls ChainIDFunc. +func (mock *EtherClientMock) ChainID(ctx context.Context) (*big.Int, error) { + if mock.ChainIDFunc == nil { + panic("EtherClientMock.ChainIDFunc: method is nil but EtherClient.ChainID was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockChainID.Lock() + mock.calls.ChainID = append(mock.calls.ChainID, callInfo) + mock.lockChainID.Unlock() + return mock.ChainIDFunc(ctx) +} + +// ChainIDCalls gets all the calls that were made to ChainID. +// Check the length with: +// len(mockedEtherClient.ChainIDCalls()) +func (mock *EtherClientMock) ChainIDCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockChainID.RLock() + calls = mock.calls.ChainID + mock.lockChainID.RUnlock() + return calls +} + +// Close calls CloseFunc. +func (mock *EtherClientMock) Close() { + if mock.CloseFunc == nil { + panic("EtherClientMock.CloseFunc: method is nil but EtherClient.Close was just called") + } + callInfo := struct { + }{} + mock.lockClose.Lock() + mock.calls.Close = append(mock.calls.Close, callInfo) + mock.lockClose.Unlock() + mock.CloseFunc() +} + +// CloseCalls gets all the calls that were made to Close. +// Check the length with: +// len(mockedEtherClient.CloseCalls()) +func (mock *EtherClientMock) CloseCalls() []struct { +} { + var calls []struct { + } + mock.lockClose.RLock() + calls = mock.calls.Close + mock.lockClose.RUnlock() + return calls +} + +// CodeAt calls CodeAtFunc. +func (mock *EtherClientMock) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { + if mock.CodeAtFunc == nil { + panic("EtherClientMock.CodeAtFunc: method is nil but EtherClient.CodeAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int + }{ + Ctx: ctx, + Account: account, + BlockNumber: blockNumber, + } + mock.lockCodeAt.Lock() + mock.calls.CodeAt = append(mock.calls.CodeAt, callInfo) + mock.lockCodeAt.Unlock() + return mock.CodeAtFunc(ctx, account, blockNumber) +} + +// CodeAtCalls gets all the calls that were made to CodeAt. +// Check the length with: +// len(mockedEtherClient.CodeAtCalls()) +func (mock *EtherClientMock) CodeAtCalls() []struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int +} { + var calls []struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int + } + mock.lockCodeAt.RLock() + calls = mock.calls.CodeAt + mock.lockCodeAt.RUnlock() + return calls +} + +// EstimateGas calls EstimateGasFunc. +func (mock *EtherClientMock) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { + if mock.EstimateGasFunc == nil { + panic("EtherClientMock.EstimateGasFunc: method is nil but EtherClient.EstimateGas was just called") + } + callInfo := struct { + Ctx context.Context + Msg ethereum.CallMsg + }{ + Ctx: ctx, + Msg: msg, + } + mock.lockEstimateGas.Lock() + mock.calls.EstimateGas = append(mock.calls.EstimateGas, callInfo) + mock.lockEstimateGas.Unlock() + return mock.EstimateGasFunc(ctx, msg) +} + +// EstimateGasCalls gets all the calls that were made to EstimateGas. +// Check the length with: +// len(mockedEtherClient.EstimateGasCalls()) +func (mock *EtherClientMock) EstimateGasCalls() []struct { + Ctx context.Context + Msg ethereum.CallMsg +} { + var calls []struct { + Ctx context.Context + Msg ethereum.CallMsg + } + mock.lockEstimateGas.RLock() + calls = mock.calls.EstimateGas + mock.lockEstimateGas.RUnlock() + return calls +} + +// FilterLogs calls FilterLogsFunc. +func (mock *EtherClientMock) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { + if mock.FilterLogsFunc == nil { + panic("EtherClientMock.FilterLogsFunc: method is nil but EtherClient.FilterLogs was just called") + } + callInfo := struct { + Ctx context.Context + Q ethereum.FilterQuery + }{ + Ctx: ctx, + Q: q, + } + mock.lockFilterLogs.Lock() + mock.calls.FilterLogs = append(mock.calls.FilterLogs, callInfo) + mock.lockFilterLogs.Unlock() + return mock.FilterLogsFunc(ctx, q) +} + +// FilterLogsCalls gets all the calls that were made to FilterLogs. +// Check the length with: +// len(mockedEtherClient.FilterLogsCalls()) +func (mock *EtherClientMock) FilterLogsCalls() []struct { + Ctx context.Context + Q ethereum.FilterQuery +} { + var calls []struct { + Ctx context.Context + Q ethereum.FilterQuery + } + mock.lockFilterLogs.RLock() + calls = mock.calls.FilterLogs + mock.lockFilterLogs.RUnlock() + return calls +} + +// HeaderByHash calls HeaderByHashFunc. +func (mock *EtherClientMock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + if mock.HeaderByHashFunc == nil { + panic("EtherClientMock.HeaderByHashFunc: method is nil but EtherClient.HeaderByHash was just called") + } + callInfo := struct { + Ctx context.Context + Hash common.Hash + }{ + Ctx: ctx, + Hash: hash, + } + mock.lockHeaderByHash.Lock() + mock.calls.HeaderByHash = append(mock.calls.HeaderByHash, callInfo) + mock.lockHeaderByHash.Unlock() + return mock.HeaderByHashFunc(ctx, hash) +} + +// HeaderByHashCalls gets all the calls that were made to HeaderByHash. +// Check the length with: +// len(mockedEtherClient.HeaderByHashCalls()) +func (mock *EtherClientMock) HeaderByHashCalls() []struct { + Ctx context.Context + Hash common.Hash +} { + var calls []struct { + Ctx context.Context + Hash common.Hash + } + mock.lockHeaderByHash.RLock() + calls = mock.calls.HeaderByHash + mock.lockHeaderByHash.RUnlock() + return calls +} + +// HeaderByNumber calls HeaderByNumberFunc. +func (mock *EtherClientMock) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + if mock.HeaderByNumberFunc == nil { + panic("EtherClientMock.HeaderByNumberFunc: method is nil but EtherClient.HeaderByNumber was just called") + } + callInfo := struct { + Ctx context.Context + Number *big.Int + }{ + Ctx: ctx, + Number: number, + } + mock.lockHeaderByNumber.Lock() + mock.calls.HeaderByNumber = append(mock.calls.HeaderByNumber, callInfo) + mock.lockHeaderByNumber.Unlock() + return mock.HeaderByNumberFunc(ctx, number) +} + +// HeaderByNumberCalls gets all the calls that were made to HeaderByNumber. +// Check the length with: +// len(mockedEtherClient.HeaderByNumberCalls()) +func (mock *EtherClientMock) HeaderByNumberCalls() []struct { + Ctx context.Context + Number *big.Int +} { + var calls []struct { + Ctx context.Context + Number *big.Int + } + mock.lockHeaderByNumber.RLock() + calls = mock.calls.HeaderByNumber + mock.lockHeaderByNumber.RUnlock() + return calls +} + +// NetworkID calls NetworkIDFunc. +func (mock *EtherClientMock) NetworkID(ctx context.Context) (*big.Int, error) { + if mock.NetworkIDFunc == nil { + panic("EtherClientMock.NetworkIDFunc: method is nil but EtherClient.NetworkID was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockNetworkID.Lock() + mock.calls.NetworkID = append(mock.calls.NetworkID, callInfo) + mock.lockNetworkID.Unlock() + return mock.NetworkIDFunc(ctx) +} + +// NetworkIDCalls gets all the calls that were made to NetworkID. +// Check the length with: +// len(mockedEtherClient.NetworkIDCalls()) +func (mock *EtherClientMock) NetworkIDCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockNetworkID.RLock() + calls = mock.calls.NetworkID + mock.lockNetworkID.RUnlock() + return calls +} + +// NonceAt calls NonceAtFunc. +func (mock *EtherClientMock) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + if mock.NonceAtFunc == nil { + panic("EtherClientMock.NonceAtFunc: method is nil but EtherClient.NonceAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int + }{ + Ctx: ctx, + Account: account, + BlockNumber: blockNumber, + } + mock.lockNonceAt.Lock() + mock.calls.NonceAt = append(mock.calls.NonceAt, callInfo) + mock.lockNonceAt.Unlock() + return mock.NonceAtFunc(ctx, account, blockNumber) +} + +// NonceAtCalls gets all the calls that were made to NonceAt. +// Check the length with: +// len(mockedEtherClient.NonceAtCalls()) +func (mock *EtherClientMock) NonceAtCalls() []struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int +} { + var calls []struct { + Ctx context.Context + Account common.Address + BlockNumber *big.Int + } + mock.lockNonceAt.RLock() + calls = mock.calls.NonceAt + mock.lockNonceAt.RUnlock() + return calls +} + +// PendingBalanceAt calls PendingBalanceAtFunc. +func (mock *EtherClientMock) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) { + if mock.PendingBalanceAtFunc == nil { + panic("EtherClientMock.PendingBalanceAtFunc: method is nil but EtherClient.PendingBalanceAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + }{ + Ctx: ctx, + Account: account, + } + mock.lockPendingBalanceAt.Lock() + mock.calls.PendingBalanceAt = append(mock.calls.PendingBalanceAt, callInfo) + mock.lockPendingBalanceAt.Unlock() + return mock.PendingBalanceAtFunc(ctx, account) +} + +// PendingBalanceAtCalls gets all the calls that were made to PendingBalanceAt. +// Check the length with: +// len(mockedEtherClient.PendingBalanceAtCalls()) +func (mock *EtherClientMock) PendingBalanceAtCalls() []struct { + Ctx context.Context + Account common.Address +} { + var calls []struct { + Ctx context.Context + Account common.Address + } + mock.lockPendingBalanceAt.RLock() + calls = mock.calls.PendingBalanceAt + mock.lockPendingBalanceAt.RUnlock() + return calls +} + +// PendingCallContract calls PendingCallContractFunc. +func (mock *EtherClientMock) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { + if mock.PendingCallContractFunc == nil { + panic("EtherClientMock.PendingCallContractFunc: method is nil but EtherClient.PendingCallContract was just called") + } + callInfo := struct { + Ctx context.Context + Msg ethereum.CallMsg + }{ + Ctx: ctx, + Msg: msg, + } + mock.lockPendingCallContract.Lock() + mock.calls.PendingCallContract = append(mock.calls.PendingCallContract, callInfo) + mock.lockPendingCallContract.Unlock() + return mock.PendingCallContractFunc(ctx, msg) +} + +// PendingCallContractCalls gets all the calls that were made to PendingCallContract. +// Check the length with: +// len(mockedEtherClient.PendingCallContractCalls()) +func (mock *EtherClientMock) PendingCallContractCalls() []struct { + Ctx context.Context + Msg ethereum.CallMsg +} { + var calls []struct { + Ctx context.Context + Msg ethereum.CallMsg + } + mock.lockPendingCallContract.RLock() + calls = mock.calls.PendingCallContract + mock.lockPendingCallContract.RUnlock() + return calls +} + +// PendingCodeAt calls PendingCodeAtFunc. +func (mock *EtherClientMock) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { + if mock.PendingCodeAtFunc == nil { + panic("EtherClientMock.PendingCodeAtFunc: method is nil but EtherClient.PendingCodeAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + }{ + Ctx: ctx, + Account: account, + } + mock.lockPendingCodeAt.Lock() + mock.calls.PendingCodeAt = append(mock.calls.PendingCodeAt, callInfo) + mock.lockPendingCodeAt.Unlock() + return mock.PendingCodeAtFunc(ctx, account) +} + +// PendingCodeAtCalls gets all the calls that were made to PendingCodeAt. +// Check the length with: +// len(mockedEtherClient.PendingCodeAtCalls()) +func (mock *EtherClientMock) PendingCodeAtCalls() []struct { + Ctx context.Context + Account common.Address +} { + var calls []struct { + Ctx context.Context + Account common.Address + } + mock.lockPendingCodeAt.RLock() + calls = mock.calls.PendingCodeAt + mock.lockPendingCodeAt.RUnlock() + return calls +} + +// PendingNonceAt calls PendingNonceAtFunc. +func (mock *EtherClientMock) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + if mock.PendingNonceAtFunc == nil { + panic("EtherClientMock.PendingNonceAtFunc: method is nil but EtherClient.PendingNonceAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + }{ + Ctx: ctx, + Account: account, + } + mock.lockPendingNonceAt.Lock() + mock.calls.PendingNonceAt = append(mock.calls.PendingNonceAt, callInfo) + mock.lockPendingNonceAt.Unlock() + return mock.PendingNonceAtFunc(ctx, account) +} + +// PendingNonceAtCalls gets all the calls that were made to PendingNonceAt. +// Check the length with: +// len(mockedEtherClient.PendingNonceAtCalls()) +func (mock *EtherClientMock) PendingNonceAtCalls() []struct { + Ctx context.Context + Account common.Address +} { + var calls []struct { + Ctx context.Context + Account common.Address + } + mock.lockPendingNonceAt.RLock() + calls = mock.calls.PendingNonceAt + mock.lockPendingNonceAt.RUnlock() + return calls +} + +// PendingStorageAt calls PendingStorageAtFunc. +func (mock *EtherClientMock) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { + if mock.PendingStorageAtFunc == nil { + panic("EtherClientMock.PendingStorageAtFunc: method is nil but EtherClient.PendingStorageAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + Key common.Hash + }{ + Ctx: ctx, + Account: account, + Key: key, + } + mock.lockPendingStorageAt.Lock() + mock.calls.PendingStorageAt = append(mock.calls.PendingStorageAt, callInfo) + mock.lockPendingStorageAt.Unlock() + return mock.PendingStorageAtFunc(ctx, account, key) +} + +// PendingStorageAtCalls gets all the calls that were made to PendingStorageAt. +// Check the length with: +// len(mockedEtherClient.PendingStorageAtCalls()) +func (mock *EtherClientMock) PendingStorageAtCalls() []struct { + Ctx context.Context + Account common.Address + Key common.Hash +} { + var calls []struct { + Ctx context.Context + Account common.Address + Key common.Hash + } + mock.lockPendingStorageAt.RLock() + calls = mock.calls.PendingStorageAt + mock.lockPendingStorageAt.RUnlock() + return calls +} + +// PendingTransactionCount calls PendingTransactionCountFunc. +func (mock *EtherClientMock) PendingTransactionCount(ctx context.Context) (uint, error) { + if mock.PendingTransactionCountFunc == nil { + panic("EtherClientMock.PendingTransactionCountFunc: method is nil but EtherClient.PendingTransactionCount was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockPendingTransactionCount.Lock() + mock.calls.PendingTransactionCount = append(mock.calls.PendingTransactionCount, callInfo) + mock.lockPendingTransactionCount.Unlock() + return mock.PendingTransactionCountFunc(ctx) +} + +// PendingTransactionCountCalls gets all the calls that were made to PendingTransactionCount. +// Check the length with: +// len(mockedEtherClient.PendingTransactionCountCalls()) +func (mock *EtherClientMock) PendingTransactionCountCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockPendingTransactionCount.RLock() + calls = mock.calls.PendingTransactionCount + mock.lockPendingTransactionCount.RUnlock() + return calls +} + +// SendTransaction calls SendTransactionFunc. +func (mock *EtherClientMock) SendTransaction(ctx context.Context, tx *types.Transaction) error { + if mock.SendTransactionFunc == nil { + panic("EtherClientMock.SendTransactionFunc: method is nil but EtherClient.SendTransaction was just called") + } + callInfo := struct { + Ctx context.Context + Tx *types.Transaction + }{ + Ctx: ctx, + Tx: tx, + } + mock.lockSendTransaction.Lock() + mock.calls.SendTransaction = append(mock.calls.SendTransaction, callInfo) + mock.lockSendTransaction.Unlock() + return mock.SendTransactionFunc(ctx, tx) +} + +// SendTransactionCalls gets all the calls that were made to SendTransaction. +// Check the length with: +// len(mockedEtherClient.SendTransactionCalls()) +func (mock *EtherClientMock) SendTransactionCalls() []struct { + Ctx context.Context + Tx *types.Transaction +} { + var calls []struct { + Ctx context.Context + Tx *types.Transaction + } + mock.lockSendTransaction.RLock() + calls = mock.calls.SendTransaction + mock.lockSendTransaction.RUnlock() + return calls +} + +// StorageAt calls StorageAtFunc. +func (mock *EtherClientMock) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { + if mock.StorageAtFunc == nil { + panic("EtherClientMock.StorageAtFunc: method is nil but EtherClient.StorageAt was just called") + } + callInfo := struct { + Ctx context.Context + Account common.Address + Key common.Hash + BlockNumber *big.Int + }{ + Ctx: ctx, + Account: account, + Key: key, + BlockNumber: blockNumber, + } + mock.lockStorageAt.Lock() + mock.calls.StorageAt = append(mock.calls.StorageAt, callInfo) + mock.lockStorageAt.Unlock() + return mock.StorageAtFunc(ctx, account, key, blockNumber) +} + +// StorageAtCalls gets all the calls that were made to StorageAt. +// Check the length with: +// len(mockedEtherClient.StorageAtCalls()) +func (mock *EtherClientMock) StorageAtCalls() []struct { + Ctx context.Context + Account common.Address + Key common.Hash + BlockNumber *big.Int +} { + var calls []struct { + Ctx context.Context + Account common.Address + Key common.Hash + BlockNumber *big.Int + } + mock.lockStorageAt.RLock() + calls = mock.calls.StorageAt + mock.lockStorageAt.RUnlock() + return calls +} + +// SubscribeFilterLogs calls SubscribeFilterLogsFunc. +func (mock *EtherClientMock) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { + if mock.SubscribeFilterLogsFunc == nil { + panic("EtherClientMock.SubscribeFilterLogsFunc: method is nil but EtherClient.SubscribeFilterLogs was just called") + } + callInfo := struct { + Ctx context.Context + Q ethereum.FilterQuery + Ch chan<- types.Log + }{ + Ctx: ctx, + Q: q, + Ch: ch, + } + mock.lockSubscribeFilterLogs.Lock() + mock.calls.SubscribeFilterLogs = append(mock.calls.SubscribeFilterLogs, callInfo) + mock.lockSubscribeFilterLogs.Unlock() + return mock.SubscribeFilterLogsFunc(ctx, q, ch) +} + +// SubscribeFilterLogsCalls gets all the calls that were made to SubscribeFilterLogs. +// Check the length with: +// len(mockedEtherClient.SubscribeFilterLogsCalls()) +func (mock *EtherClientMock) SubscribeFilterLogsCalls() []struct { + Ctx context.Context + Q ethereum.FilterQuery + Ch chan<- types.Log +} { + var calls []struct { + Ctx context.Context + Q ethereum.FilterQuery + Ch chan<- types.Log + } + mock.lockSubscribeFilterLogs.RLock() + calls = mock.calls.SubscribeFilterLogs + mock.lockSubscribeFilterLogs.RUnlock() + return calls +} + +// SubscribeNewHead calls SubscribeNewHeadFunc. +func (mock *EtherClientMock) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + if mock.SubscribeNewHeadFunc == nil { + panic("EtherClientMock.SubscribeNewHeadFunc: method is nil but EtherClient.SubscribeNewHead was just called") + } + callInfo := struct { + Ctx context.Context + Ch chan<- *types.Header + }{ + Ctx: ctx, + Ch: ch, + } + mock.lockSubscribeNewHead.Lock() + mock.calls.SubscribeNewHead = append(mock.calls.SubscribeNewHead, callInfo) + mock.lockSubscribeNewHead.Unlock() + return mock.SubscribeNewHeadFunc(ctx, ch) +} + +// SubscribeNewHeadCalls gets all the calls that were made to SubscribeNewHead. +// Check the length with: +// len(mockedEtherClient.SubscribeNewHeadCalls()) +func (mock *EtherClientMock) SubscribeNewHeadCalls() []struct { + Ctx context.Context + Ch chan<- *types.Header +} { + var calls []struct { + Ctx context.Context + Ch chan<- *types.Header + } + mock.lockSubscribeNewHead.RLock() + calls = mock.calls.SubscribeNewHead + mock.lockSubscribeNewHead.RUnlock() + return calls +} + +// SuggestGasPrice calls SuggestGasPriceFunc. +func (mock *EtherClientMock) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + if mock.SuggestGasPriceFunc == nil { + panic("EtherClientMock.SuggestGasPriceFunc: method is nil but EtherClient.SuggestGasPrice was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockSuggestGasPrice.Lock() + mock.calls.SuggestGasPrice = append(mock.calls.SuggestGasPrice, callInfo) + mock.lockSuggestGasPrice.Unlock() + return mock.SuggestGasPriceFunc(ctx) +} + +// SuggestGasPriceCalls gets all the calls that were made to SuggestGasPrice. +// Check the length with: +// len(mockedEtherClient.SuggestGasPriceCalls()) +func (mock *EtherClientMock) SuggestGasPriceCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockSuggestGasPrice.RLock() + calls = mock.calls.SuggestGasPrice + mock.lockSuggestGasPrice.RUnlock() + return calls +} + +// SyncProgress calls SyncProgressFunc. +func (mock *EtherClientMock) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { + if mock.SyncProgressFunc == nil { + panic("EtherClientMock.SyncProgressFunc: method is nil but EtherClient.SyncProgress was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockSyncProgress.Lock() + mock.calls.SyncProgress = append(mock.calls.SyncProgress, callInfo) + mock.lockSyncProgress.Unlock() + return mock.SyncProgressFunc(ctx) +} + +// SyncProgressCalls gets all the calls that were made to SyncProgress. +// Check the length with: +// len(mockedEtherClient.SyncProgressCalls()) +func (mock *EtherClientMock) SyncProgressCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockSyncProgress.RLock() + calls = mock.calls.SyncProgress + mock.lockSyncProgress.RUnlock() + return calls +} + +// TransactionByHash calls TransactionByHashFunc. +func (mock *EtherClientMock) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) { + if mock.TransactionByHashFunc == nil { + panic("EtherClientMock.TransactionByHashFunc: method is nil but EtherClient.TransactionByHash was just called") + } + callInfo := struct { + Ctx context.Context + Hash common.Hash + }{ + Ctx: ctx, + Hash: hash, + } + mock.lockTransactionByHash.Lock() + mock.calls.TransactionByHash = append(mock.calls.TransactionByHash, callInfo) + mock.lockTransactionByHash.Unlock() + return mock.TransactionByHashFunc(ctx, hash) +} + +// TransactionByHashCalls gets all the calls that were made to TransactionByHash. +// Check the length with: +// len(mockedEtherClient.TransactionByHashCalls()) +func (mock *EtherClientMock) TransactionByHashCalls() []struct { + Ctx context.Context + Hash common.Hash +} { + var calls []struct { + Ctx context.Context + Hash common.Hash + } + mock.lockTransactionByHash.RLock() + calls = mock.calls.TransactionByHash + mock.lockTransactionByHash.RUnlock() + return calls +} + +// TransactionCount calls TransactionCountFunc. +func (mock *EtherClientMock) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { + if mock.TransactionCountFunc == nil { + panic("EtherClientMock.TransactionCountFunc: method is nil but EtherClient.TransactionCount was just called") + } + callInfo := struct { + Ctx context.Context + BlockHash common.Hash + }{ + Ctx: ctx, + BlockHash: blockHash, + } + mock.lockTransactionCount.Lock() + mock.calls.TransactionCount = append(mock.calls.TransactionCount, callInfo) + mock.lockTransactionCount.Unlock() + return mock.TransactionCountFunc(ctx, blockHash) +} + +// TransactionCountCalls gets all the calls that were made to TransactionCount. +// Check the length with: +// len(mockedEtherClient.TransactionCountCalls()) +func (mock *EtherClientMock) TransactionCountCalls() []struct { + Ctx context.Context + BlockHash common.Hash +} { + var calls []struct { + Ctx context.Context + BlockHash common.Hash + } + mock.lockTransactionCount.RLock() + calls = mock.calls.TransactionCount + mock.lockTransactionCount.RUnlock() + return calls +} + +// TransactionInBlock calls TransactionInBlockFunc. +func (mock *EtherClientMock) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { + if mock.TransactionInBlockFunc == nil { + panic("EtherClientMock.TransactionInBlockFunc: method is nil but EtherClient.TransactionInBlock was just called") + } + callInfo := struct { + Ctx context.Context + BlockHash common.Hash + Index uint + }{ + Ctx: ctx, + BlockHash: blockHash, + Index: index, + } + mock.lockTransactionInBlock.Lock() + mock.calls.TransactionInBlock = append(mock.calls.TransactionInBlock, callInfo) + mock.lockTransactionInBlock.Unlock() + return mock.TransactionInBlockFunc(ctx, blockHash, index) +} + +// TransactionInBlockCalls gets all the calls that were made to TransactionInBlock. +// Check the length with: +// len(mockedEtherClient.TransactionInBlockCalls()) +func (mock *EtherClientMock) TransactionInBlockCalls() []struct { + Ctx context.Context + BlockHash common.Hash + Index uint +} { + var calls []struct { + Ctx context.Context + BlockHash common.Hash + Index uint + } + mock.lockTransactionInBlock.RLock() + calls = mock.calls.TransactionInBlock + mock.lockTransactionInBlock.RUnlock() + return calls +} + +// TransactionReceipt calls TransactionReceiptFunc. +func (mock *EtherClientMock) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + if mock.TransactionReceiptFunc == nil { + panic("EtherClientMock.TransactionReceiptFunc: method is nil but EtherClient.TransactionReceipt was just called") + } + callInfo := struct { + Ctx context.Context + TxHash common.Hash + }{ + Ctx: ctx, + TxHash: txHash, + } + mock.lockTransactionReceipt.Lock() + mock.calls.TransactionReceipt = append(mock.calls.TransactionReceipt, callInfo) + mock.lockTransactionReceipt.Unlock() + return mock.TransactionReceiptFunc(ctx, txHash) +} + +// TransactionReceiptCalls gets all the calls that were made to TransactionReceipt. +// Check the length with: +// len(mockedEtherClient.TransactionReceiptCalls()) +func (mock *EtherClientMock) TransactionReceiptCalls() []struct { + Ctx context.Context + TxHash common.Hash +} { + var calls []struct { + Ctx context.Context + TxHash common.Hash + } + mock.lockTransactionReceipt.RLock() + calls = mock.calls.TransactionReceipt + mock.lockTransactionReceipt.RUnlock() + return calls +} + +// TransactionSender calls TransactionSenderFunc. +func (mock *EtherClientMock) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { + if mock.TransactionSenderFunc == nil { + panic("EtherClientMock.TransactionSenderFunc: method is nil but EtherClient.TransactionSender was just called") + } + callInfo := struct { + Ctx context.Context + Tx *types.Transaction + Block common.Hash + Index uint + }{ + Ctx: ctx, + Tx: tx, + Block: block, + Index: index, + } + mock.lockTransactionSender.Lock() + mock.calls.TransactionSender = append(mock.calls.TransactionSender, callInfo) + mock.lockTransactionSender.Unlock() + return mock.TransactionSenderFunc(ctx, tx, block, index) +} + +// TransactionSenderCalls gets all the calls that were made to TransactionSender. +// Check the length with: +// len(mockedEtherClient.TransactionSenderCalls()) +func (mock *EtherClientMock) TransactionSenderCalls() []struct { + Ctx context.Context + Tx *types.Transaction + Block common.Hash + Index uint +} { + var calls []struct { + Ctx context.Context + Tx *types.Transaction + Block common.Hash + Index uint + } + mock.lockTransactionSender.RLock() + calls = mock.calls.TransactionSender + mock.lockTransactionSender.RUnlock() + return calls +} diff --git a/client/client.go b/client/client.go index fdaf71f..e1cf9e3 100644 --- a/client/client.go +++ b/client/client.go @@ -27,7 +27,6 @@ import ( "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/ethclient" "github.com/ethereum/go-ethereum/event" "github.com/mysteriumnetwork/payments/bindings" "github.com/mysteriumnetwork/payments/bindings/rewarder" @@ -47,13 +46,9 @@ type ProviderChannel struct { Timelock *big.Int } -type ethClientGetter interface { - Client() *ethclient.Client -} - // Blockchain contains all the useful blockchain utilities for the payment off chain messaging type Blockchain struct { - ethClient ethClientGetter + ethClient EthClientGetter bcTimeout time.Duration nonceFunc nonceFunc } @@ -61,7 +56,7 @@ type Blockchain struct { type nonceFunc func(ctx context.Context, account common.Address) (uint64, error) // NewBlockchain returns a new instance of blockchain -func NewBlockchain(ethClient ethClientGetter, timeout time.Duration) *Blockchain { +func NewBlockchain(ethClient EthClientGetter, timeout time.Duration) *Blockchain { return &Blockchain{ ethClient: ethClient, bcTimeout: timeout, @@ -72,7 +67,7 @@ func NewBlockchain(ethClient ethClientGetter, timeout time.Duration) *Blockchain } // NewBlockchainWithCustomNonceTracker returns a new instance of blockchain with the provided nonce tracking func -func NewBlockchainWithCustomNonceTracker(ethClient ethClientGetter, timeout time.Duration, nonceFunc nonceFunc) *Blockchain { +func NewBlockchainWithCustomNonceTracker(ethClient EthClientGetter, timeout time.Duration, nonceFunc nonceFunc) *Blockchain { return &Blockchain{ ethClient: ethClient, bcTimeout: timeout, @@ -333,7 +328,7 @@ type RegistrationRequest struct { Nonce *big.Int } -func (r RegistrationRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r RegistrationRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.RegistryAddress, bindings.RegistryABI, ethClient.Client()) } @@ -404,7 +399,7 @@ type PayAndSettleRequest struct { BeneficiarySignature []byte } -func (psr PayAndSettleRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (psr PayAndSettleRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(psr.HermesID, bindings.HermesImplementationABI, ethClient.Client()) } @@ -461,7 +456,7 @@ type TransferRequest struct { WriteRequest } -func (r TransferRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r TransferRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.MystAddress, bindings.MystTokenABI, ethClient.Client()) } @@ -517,7 +512,7 @@ type ProviderStakeIncreaseRequest struct { Amount *big.Int } -func (r ProviderStakeIncreaseRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r ProviderStakeIncreaseRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.HermesID, bindings.HermesImplementationABI, ethClient.Client()) } @@ -553,7 +548,7 @@ type SettleIntoStakeRequest struct { ProviderID common.Address } -func (r SettleIntoStakeRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r SettleIntoStakeRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.HermesID, bindings.HermesImplementationABI, ethClient.Client()) } @@ -602,7 +597,7 @@ type DecreaseProviderStakeRequest struct { ProviderID common.Address } -func (r DecreaseProviderStakeRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r DecreaseProviderStakeRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.Request.HermesID, bindings.HermesImplementationABI, ethClient.Client()) } @@ -707,7 +702,7 @@ type SettleAndRebalanceRequest struct { Promise crypto.Promise } -func (r SettleAndRebalanceRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r SettleAndRebalanceRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.HermesID, bindings.HermesImplementationABI, ethClient.Client()) } @@ -871,7 +866,7 @@ type SettleRequest struct { Promise crypto.Promise } -func (r SettleRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r SettleRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.ChannelID, bindings.ChannelImplementationABI, ethClient.Client()) } @@ -1126,7 +1121,7 @@ type SettleWithBeneficiaryRequest struct { Signature []byte } -func (r SettleWithBeneficiaryRequest) toEstimator(ethClient ethClientGetter) (*bindings.ContractEstimator, error) { +func (r SettleWithBeneficiaryRequest) toEstimator(ethClient EthClientGetter) (*bindings.ContractEstimator, error) { return bindings.NewContractEstimator(r.HermesID, bindings.HermesImplementationABI, ethClient.Client()) } diff --git a/client/counter.go b/client/counter.go deleted file mode 100644 index 40efe9e..0000000 --- a/client/counter.go +++ /dev/null @@ -1,41 +0,0 @@ -package client - -import ( - "runtime" - "sync" - - "github.com/davecgh/go-spew/spew" -) - -var Counter = callCounter{} - -type callCounter struct { - stats map[string]uint64 - lock sync.Mutex - once sync.Once -} - -func (cc *callCounter) print() { - spew.Dump(cc.stats) -} - -func (cc *callCounter) Count() { - cc.lock.Lock() - defer cc.lock.Unlock() - pc, _, _, ok := runtime.Caller(1) - details := runtime.FuncForPC(pc) - if ok && details != nil { - cc.once.Do(func() { - cc.stats = make(map[string]uint64) - }) - - name := details.Name() - if v, ok := cc.stats[name]; ok { - cc.stats[name] = v + 1 - } else { - cc.stats[name] = 1 - } - - cc.print() - } -} diff --git a/client/ethclient.go b/client/ethclient.go index cb3513f..3bea2cf 100644 --- a/client/ethclient.go +++ b/client/ethclient.go @@ -18,15 +18,20 @@ package client import ( + "context" "fmt" "sync" + "time" "github.com/ethereum/go-ethereum/ethclient" ) // NewReconnectableEthClient creates new ethereum client that can reconnect. -func NewReconnectableEthClient(address string) (*ReconnectableEthClient, error) { - ec, err := ethclient.Dial(address) +func NewReconnectableEthClient(address string, connectTimeout time.Duration) (*ReconnectableEthClient, error) { + ctx, cancel := context.WithTimeout(context.Background(), connectTimeout) + defer cancel() + + ec, err := ethclient.DialContext(ctx, address) if err != nil { return nil, fmt.Errorf("ethereum client failed to connect: %w", err) } @@ -45,19 +50,30 @@ type ReconnectableEthClient struct { } // Client returns the currently connected ethereum client. -func (c *ReconnectableEthClient) Client() *ethclient.Client { +func (c *ReconnectableEthClient) Client() EtherClient { c.mu.Lock() defer c.mu.Unlock() return c.client } +// Address returns the current address which was used to create the client. +func (c *ReconnectableEthClient) Address() string { + c.mu.Lock() + defer c.mu.Unlock() + + return c.address +} + // Reconnect creates new ethereum client and replaces the current one. -func (c *ReconnectableEthClient) Reconnect() error { +func (c *ReconnectableEthClient) Reconnect(connectTimeout time.Duration) error { c.mu.Lock() defer c.mu.Unlock() - client, err := ethclient.Dial(c.address) + ctx, cancel := context.WithTimeout(context.Background(), connectTimeout) + defer cancel() + + client, err := ethclient.DialContext(ctx, c.address) if err != nil { return fmt.Errorf("ethereum client failed to dial: %w", err) } diff --git a/client/ethclient_test.go b/client/ethclient_test.go index 34332dd..06ffd38 100644 --- a/client/ethclient_test.go +++ b/client/ethclient_test.go @@ -19,19 +19,20 @@ package client import ( "testing" + "time" "github.com/stretchr/testify/assert" ) func TestReconnectableEthClientCreatesNewClient(t *testing.T) { - client, err := NewReconnectableEthClient("http://127.0.0.1:1234") + client, err := NewReconnectableEthClient("http://127.0.0.1:1234", time.Second) assert.Nil(t, err) c1 := client.Client() c2 := client.Client() assert.Equal(t, c1, c2) - err = client.Reconnect() + err = client.Reconnect(time.Second) assert.Nil(t, err) c3 := client.Client() diff --git a/client/ethmulticlient.go b/client/ethmulticlient.go new file mode 100644 index 0000000..9b39781 --- /dev/null +++ b/client/ethmulticlient.go @@ -0,0 +1,710 @@ +/* + * Copyright (C) 2021 The "MysteriumNetwork/payments" Authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package client + +import ( + "context" + "errors" + "fmt" + "math/big" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// EthMultiClient is a ethereum client that can reconnect. +type EthMultiClient struct { + // timeout is the default amount of time to be assigned for a parent context + // from a caller if it doesn't have one. + timeout time.Duration + + // clients holds all the possible clients to call. + clients []EthClientGetter + + // notifyDown is an optional channel. + // + // If given updates will be sent to this channel + // when a certain client goes down. + notifyDown *safeChannel + + mu sync.Mutex +} + +type safeChannel struct { + ch chan<- string + mu sync.Mutex +} + +type doFunc func(ctx context.Context, c EtherClient) + +// NewEthMultiClient creates a new multi clients eth client. +func NewEthMultiClient(defaulTimeout time.Duration, clients []EthClientGetter) (*EthMultiClient, error) { + if len(clients) == 0 { + return nil, errors.New("expected more than 0 clients to use") + } + + return &EthMultiClient{ + timeout: defaulTimeout, + clients: clients, + notifyDown: &safeChannel{ + ch: nil, + }, + }, nil +} + +// NewEthMultiClientNotifyDown creates a new multi clients eth client. +// +// Channel `notifications` must be given and will be used to push notifications to the +// client if any nodes go down. The channel is closed when before the clients are closed. +func NewEthMultiClientNotifyDown(defaulTimeout time.Duration, clients []EthClientGetter, notifications chan<- string) (*EthMultiClient, error) { + if len(clients) == 0 { + return nil, errors.New("expected more than 0 clients to use") + } + + return &EthMultiClient{ + timeout: defaulTimeout, + clients: clients, + notifyDown: &safeChannel{ + ch: notifications, + }, + }, nil +} + +// Close will close all the clients the multiclient instance holds. +func (c *EthMultiClient) Close() { + c.closeNotify() + c.doWithMultipleClients(context.Background(), func(ctx context.Context, c EtherClient) error { + c.Close() + return nil + }) +} + +// ChainId retrieves the current chain ID for transaction replay protection. +func (c *EthMultiClient) ChainID(ctx context.Context) (*big.Int, error) { + var res *big.Int + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.ChainID(ctx) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// BlockByHash returns the given full block. +// +// Note that loading full blocks requires two requests. Use HeaderByHash +// if you don't need all transactions or uncle headers. +func (c *EthMultiClient) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + var res *types.Block + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.BlockByHash(ctx, hash) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// BlockByNumber returns a block from the current canonical chain. If number is nil, the +// latest known block is returned. +// +// Note that loading full blocks requires two requests. Use HeaderByNumber +// if you don't need all transactions or uncle headers. +func (c *EthMultiClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + var res *types.Block + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.BlockByNumber(ctx, number) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// BlockNumber returns the most recent block number +func (c *EthMultiClient) BlockNumber(ctx context.Context) (uint64, error) { + var res uint64 + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.BlockNumber(ctx) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// HeaderByHash returns the block header with the given hash. +func (c *EthMultiClient) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + var res *types.Header + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.HeaderByHash(ctx, hash) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// HeaderByNumber returns a block header from the current canonical chain. If number is +// nil, the latest known header is returned. +func (c *EthMultiClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + var res *types.Header + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.HeaderByNumber(ctx, number) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// TransactionByHash returns the transaction with the given hash. +func (c *EthMultiClient) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) { + var tx *types.Transaction + var isPending bool + return tx, isPending, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + t, is, err := c.TransactionByHash(ctx, hash) + if err != nil { + return err + } + + tx = t + isPending = is + return nil + }) +} + +// TransactionSender returns the sender address of the given transaction. The transaction +// must be known to the remote node and included in the blockchain at the given block and +// index. The sender is the one derived by the protocol at the time of inclusion. +// +// There is a fast-path for transactions retrieved by TransactionByHash and +// TransactionInBlock. Getting their sender address can be done without an RPC interaction. +func (c *EthMultiClient) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { + var res common.Address + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.TransactionSender(ctx, tx, block, index) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// TransactionCount returns the total number of transactions in the given block. +func (c *EthMultiClient) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { + var res uint + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.TransactionCount(ctx, blockHash) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// TransactionInBlock returns a single transaction at index in the given block. +func (c *EthMultiClient) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { + var res *types.Transaction + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.TransactionInBlock(ctx, blockHash, index) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// TransactionReceipt returns the receipt of a transaction by transaction hash. +// Note that the receipt is not available for pending transactions. +func (c *EthMultiClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + var res *types.Receipt + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.TransactionReceipt(ctx, txHash) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// SyncProgress retrieves the current progress of the sync algorithm. If there's +// no sync currently running, it returns nil. +func (c *EthMultiClient) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { + var res *ethereum.SyncProgress + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.SyncProgress(ctx) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// SubscribeNewHead subscribes to notifications about the current blockchain head +// on the given channel. +func (c *EthMultiClient) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { + var res ethereum.Subscription + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.SubscribeNewHead(ctx, ch) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// NetworkID returns the network ID (also known as the chain ID) for this chain. +func (c *EthMultiClient) NetworkID(ctx context.Context) (*big.Int, error) { + var res *big.Int + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.NetworkID(ctx) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// BalanceAt returns the wei balance of the given account. +// The block number can be nil, in which case the balance is taken from the latest known block. +func (c *EthMultiClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { + var res *big.Int + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.BalanceAt(ctx, account, blockNumber) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// StorageAt returns the value of key in the contract storage of the given account. +// The block number can be nil, in which case the value is taken from the latest known block. +func (c *EthMultiClient) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { + var res []byte + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.StorageAt(ctx, account, key, blockNumber) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// CodeAt returns the contract code of the given account. +// The block number can be nil, in which case the code is taken from the latest known block. +func (c *EthMultiClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { + var res []byte + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.CodeAt(ctx, account, blockNumber) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// NonceAt returns the account nonce of the given account. +// The block number can be nil, in which case the nonce is taken from the latest known block. +func (c *EthMultiClient) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + var res uint64 + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.NonceAt(ctx, account, blockNumber) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// FilterLogs executes a filter query. +func (c *EthMultiClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { + var res []types.Log + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.FilterLogs(ctx, q) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// SubscribeFilterLogs subscribes to the results of a streaming filter query. +func (c *EthMultiClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { + var res ethereum.Subscription + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.SubscribeFilterLogs(ctx, q, ch) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// PendingBalanceAt returns the wei balance of the given account in the pending state. +func (c *EthMultiClient) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) { + var res *big.Int + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.PendingBalanceAt(ctx, account) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// PendingStorageAt returns the value of key in the contract storage of the given account in the pending state. +func (c *EthMultiClient) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { + var res []byte + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.PendingStorageAt(ctx, account, key) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// PendingCodeAt returns the contract code of the given account in the pending state. +func (c *EthMultiClient) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { + var res []byte + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.PendingCodeAt(ctx, account) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// PendingNonceAt returns the account nonce of the given account in the pending state. +// This is the nonce that should be used for the next transaction. +func (c *EthMultiClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + var res uint64 + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.PendingNonceAt(ctx, account) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// PendingTransactionCount returns the total number of transactions in the pending state. +func (c *EthMultiClient) PendingTransactionCount(ctx context.Context) (uint, error) { + var res uint + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.PendingTransactionCount(ctx) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// CallContract executes a message call transaction, which is directly executed in the VM +// of the node, but never mined into the blockchain. +// +// blockNumber selects the block height at which the call runs. It can be nil, in which +// case the code is taken from the latest known block. Note that state from very old +// blocks might not be available. +func (c *EthMultiClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + var res []byte + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.CallContract(ctx, msg, blockNumber) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// PendingCallContract executes a message call transaction using the EVM. +// The state seen by the contract call is the pending state. +func (c *EthMultiClient) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { + var res []byte + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.PendingCallContract(ctx, msg) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// SuggestGasPrice retrieves the currently suggested gas price to allow a timely +// execution of a transaction. +func (c *EthMultiClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + var res *big.Int + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.SuggestGasPrice(ctx) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// EstimateGas tries to estimate the gas needed to execute a specific transaction based on +// the current pending state of the backend blockchain. There is no guarantee that this is +// the true gas limit requirement as other transactions may be added or removed by miners, +// but it should provide a basis for setting a reasonable default. +func (c *EthMultiClient) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { + var res uint64 + return res, c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + val, err := c.EstimateGas(ctx, msg) + if err != nil { + return err + } + + res = val + return nil + }) +} + +// SendTransaction injects a signed transaction into the pending pool for execution. +// +// If the transaction was a contract creation use the TransactionReceipt method to get the +// contract address after the transaction has been mined. +func (c *EthMultiClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { + return c.doWithMultipleClients(ctx, func(ctx context.Context, c EtherClient) error { + return c.SendTransaction(ctx, tx) + }) +} + +// ReorderClients reorders clients to use in BC calls by the given address slice. +// If there are a lot of clients this function could be expensive and it will block all other +// calls or usage of these clients while reordering. +func (c *EthMultiClient) ReorderClients(addresses []string) error { + c.mu.Lock() + defer c.mu.Unlock() + + if len(c.clients) != len(addresses) { + return fmt.Errorf("can't reorder: given %d addresses to use when reordering but have %d clients", len(addresses), len(c.clients)) + } + + newClients := make([]EthClientGetter, len(c.clients)) + for i, addr := range addresses { + found := false + for _, cl := range c.clients { + if addr == cl.Address() { + newClients[i] = cl + found = true + break + } + } + + if !found { + return fmt.Errorf("can't re-order: no client with address: %s", addr) + } + } + + c.clients = newClients + return nil +} + +// CurrentClientOrder returns the current orders of all clients the multiclient uses. +func (c *EthMultiClient) CurrentClientOrder() []string { + c.mu.Lock() + defer c.mu.Unlock() + + result := make([]string, len(c.clients)) + for i, c := range c.clients { + result[i] = c.Address() + } + return result +} + +// doWithMultipleClientsCtx will execute a given function with all clients. +// +// If parent context is cancel or receives a timeout, all calls will be also cancels and the +// function will return. +func (c *EthMultiClient) doWithMultipleClients(ctx context.Context, do func(ctx context.Context, c EtherClient) error) error { + c.mu.Lock() + defer c.mu.Unlock() + + ctxs, cancel := c.produceCtxs(ctx) + defer cancel() + + done := make(chan struct{}, 0) + defer close(done) + + go func() { + select { + case <-done: + return + case <-ctx.Done(): + cancel() + } + }() + + var err error + for i, cl := range c.clients { + select { + case <-ctx.Done(): + return context.DeadlineExceeded + default: + childCtx := ctxs[i] + if childCtx.Err() != nil && ctx.Err() != nil { + return ctx.Err() + } + + err = do(childCtx, cl.Client()) + if err != nil { + if errors.Is(err, context.DeadlineExceeded) { + // If parent context wasn't canceled that means that we've timed out on this node. + if ctx.Err() == nil { + c.notifyDowntime(cl.Address()) + } + continue + } + return err + } + + return nil + } + } + + return err +} + +func (c *EthMultiClient) notifyDowntime(address string) { + c.notifyDown.mu.Lock() + defer c.notifyDown.mu.Unlock() + + // If no channel is given, just return. + if c.notifyDown.ch == nil { + return + } + + // If channel is full, drop the notification. + select { + case c.notifyDown.ch <- address: + default: + } +} + +func (c *EthMultiClient) closeNotify() { + c.notifyDown.mu.Lock() + defer c.notifyDown.mu.Unlock() + + if c.notifyDown.ch != nil { + close(c.notifyDown.ch) + // Set equal to `nil` so that any hanging queries dont + // get broadcasted as failure on client close. + c.notifyDown.ch = nil + } +} + +// produceCtxs produces contexts for each client. +func (c *EthMultiClient) produceCtxs(ctx context.Context) ([]context.Context, func()) { + singleCtxDuration := c.childTimeout(ctx) + ctxs := make([]context.Context, len(c.clients)) + cancels := make([]func(), len(c.clients)) + + for i := range ctxs { + ctxs[i], cancels[i] = context.WithTimeout(context.Background(), singleCtxDuration*time.Duration((i+1))) + } + + cancelFn := func() { + for _, fn := range cancels { + fn() + } + } + + return ctxs, cancelFn +} + +// childTimeout produces an average duration to use for each child context. +// +// It rounds the extracted duration down to miliseconds elimiating +// the posiblity to get context duration like: 1.99999999999s +func (c *EthMultiClient) childTimeout(ctx context.Context) time.Duration { + deadline, ok := ctx.Deadline() + if !ok { + deadline = time.Now().Add(c.timeout) + } + res := time.Until(deadline) / time.Duration(len(c.clients)) + + // avoid errors if time is actually less + if res > time.Millisecond { + res = res.Round(time.Millisecond) + } + + return res + +} diff --git a/client/ethmulticlient_test.go b/client/ethmulticlient_test.go new file mode 100644 index 0000000..9725266 --- /dev/null +++ b/client/ethmulticlient_test.go @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2021 The "MysteriumNetwork/payments" Authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package client + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func Test_EthMultiClient(t *testing.T) { + t.Run("no clients produces an error", func(t *testing.T) { + _, err := NewEthMultiClient(time.Second, []EthClientGetter{}) + assert.Error(t, err) + }) + + t.Run("only one client passed is used", func(t *testing.T) { + cl := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(1), nil + }, + } + getter := NewDefaultEthClientGetter("", cl) + multi, err := NewEthMultiClient(time.Second, []EthClientGetter{getter}) + assert.NoError(t, err) + + ctx, cancel := context.WithTimeout(context.TODO(), time.Second*2) + defer cancel() + + chainID, err := multi.ChainID(ctx) + assert.NoError(t, err) + assert.True(t, chainID.Cmp(big.NewInt(1)) == 0) + assert.True(t, len(cl.ChainIDCalls()) == 1) + }) + + t.Run("context with no timeout gets one assigned", func(t *testing.T) { + cl := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + ded, ok := ctx.Deadline() + assert.True(t, ok) + assert.NotZero(t, ded) + assert.True(t, time.Until(ded) > time.Second) + + return big.NewInt(1), nil + }, + } + getter := NewDefaultEthClientGetter("", cl) + multi, err := NewEthMultiClient(time.Second*2, []EthClientGetter{getter}) + assert.NoError(t, err) + + chainID, err := multi.ChainID(context.TODO()) + assert.NoError(t, err) + assert.True(t, chainID.Cmp(big.NewInt(1)) == 0) + assert.True(t, len(cl.ChainIDCalls()) == 1) + }) + + t.Run("two clients passed first one works, second never called", func(t *testing.T) { + cl := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(1), nil + }, + } + cl2 := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(1), nil + }, + } + getter := NewDefaultEthClientGetter("", cl) + getter2 := NewDefaultEthClientGetter("", cl2) + + multi, err := NewEthMultiClient(time.Second, []EthClientGetter{getter, getter2}) + assert.NoError(t, err) + + ctx, cancel := context.WithTimeout(context.TODO(), time.Second*2) + defer cancel() + + chainID, err := multi.ChainID(ctx) + assert.NoError(t, err) + assert.True(t, chainID.Cmp(big.NewInt(1)) == 0) + assert.True(t, len(cl.ChainIDCalls()) == 1) + assert.True(t, len(cl2.ChainIDCalls()) == 0) + }) + + t.Run("two clients passed first breaks, second is used", func(t *testing.T) { + cl := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + time.Sleep(time.Second / 6) + return big.NewInt(1), ctx.Err() + }, + } + cl2 := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(2), nil + }, + } + getter := NewDefaultEthClientGetter("", cl) + getter2 := NewDefaultEthClientGetter("", cl2) + + multi, err := NewEthMultiClient(time.Second, []EthClientGetter{getter, getter2}) + assert.NoError(t, err) + + ctx, cancel := context.WithTimeout(context.TODO(), time.Second/4) + defer cancel() + + chainID, err := multi.ChainID(ctx) + assert.NoError(t, err) + assert.True(t, chainID.Cmp(big.NewInt(2)) == 0) + assert.True(t, len(cl.ChainIDCalls()) == 1) + assert.True(t, len(cl2.ChainIDCalls()) == 1) + }) + + t.Run("two clients passed first breaks, notification received", func(t *testing.T) { + cl := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + time.Sleep(time.Second / 6) + return big.NewInt(1), ctx.Err() + }, + } + cl2 := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(2), nil + }, + } + getter := NewDefaultEthClientGetter("first", cl) + getter2 := NewDefaultEthClientGetter("second", cl2) + + notificationReceived := make(chan struct{}) + notify := make(chan string, 0) + testCtx, cancel := context.WithCancel(context.TODO()) + defer cancel() + go func() { + select { + case <-testCtx.Done(): + return + case result := <-notify: + notificationReceived <- struct{}{} + assert.Equal(t, "first", result) + } + }() + + multi, err := NewEthMultiClientNotifyDown(time.Second, []EthClientGetter{getter, getter2}, notify) + assert.NoError(t, err) + + ctx, cancel := context.WithTimeout(context.TODO(), time.Second/4) + defer cancel() + + chainID, err := multi.ChainID(ctx) + assert.NoError(t, err) + assert.True(t, chainID.Cmp(big.NewInt(2)) == 0) + assert.True(t, len(cl.ChainIDCalls()) == 1) + assert.True(t, len(cl2.ChainIDCalls()) == 1) + assert.Eventually(t, func() bool { + select { + case <-notificationReceived: + return true + default: + return false + } + }, time.Second/2, time.Second/200) + }) + + t.Run("multiple clients sorting", func(t *testing.T) { + cl := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(1), nil + }, + } + + cl2 := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(2), nil + }, + } + + cl3 := &EtherClientMock{ + ChainIDFunc: func(ctx context.Context) (*big.Int, error) { + return big.NewInt(2), nil + }, + } + getter := NewDefaultEthClientGetter("first", cl) + getter2 := NewDefaultEthClientGetter("second", cl2) + getter3 := NewDefaultEthClientGetter("third", cl3) + + multi, err := NewEthMultiClient(time.Second*2, []EthClientGetter{getter, getter2, getter3}) + assert.NoError(t, err) + + order := multi.CurrentClientOrder() + assert.Equal(t, []string{"first", "second", "third"}, order) + + err = multi.ReorderClients([]string{"first"}) + assert.Error(t, err) + + err = multi.ReorderClients([]string{"first", "second", "wrong"}) + assert.Error(t, err) + + err = multi.ReorderClients([]string{"second", "first", "third"}) + assert.NoError(t, err) + + order = multi.CurrentClientOrder() + assert.Equal(t, []string{"second", "first", "third"}, order) + }) +} diff --git a/client/with_dry_runs.go b/client/with_dry_runs.go index 94a54c3..4270ac2 100644 --- a/client/with_dry_runs.go +++ b/client/with_dry_runs.go @@ -31,7 +31,7 @@ import ( type Estimatable interface { getGasLimit() uint64 - toEstimator(ethClientGetter) (*bindings.ContractEstimator, error) + toEstimator(EthClientGetter) (*bindings.ContractEstimator, error) toEstimateOps() *bindings.EstimateOpts } @@ -52,11 +52,11 @@ func (e ErrorTransactionReverted) Error() string { // For convenience, this component proxies read only calls to the underlying blockchain. type WithDryRuns struct { bc BC - ethClient ethClientGetter + ethClient EthClientGetter } // NewWithDryRuns creates a new instance of client with dry runs. -func NewWithDryRuns(bc BC, ethClient ethClientGetter) *WithDryRuns { +func NewWithDryRuns(bc BC, ethClient EthClientGetter) *WithDryRuns { return &WithDryRuns{ bc: bc, ethClient: ethClient, diff --git a/magefile.go b/magefile.go index 72d4ea4..6474cdb 100644 --- a/magefile.go +++ b/magefile.go @@ -23,3 +23,7 @@ func GenerateMatic() error { command := `run bindings/abi/abigen.go --localdir=./bindings/matic/abi --contracts=ChildContract.json,RootChainManager.json,RootChain.json --out=bindings/matic --pkg=matic` return sh.RunV("go", strings.Split(command, " ")...) } + +func Test() error { + return sh.RunV("go", "test", "--short", "-race", "-cover", "./...") +} diff --git a/fees/gas/eth.go b/transfer/gas/eth.go similarity index 94% rename from fees/gas/eth.go rename to transfer/gas/eth.go index 7372429..2293ddd 100644 --- a/fees/gas/eth.go +++ b/transfer/gas/eth.go @@ -101,17 +101,17 @@ func (dpa *EthStation) defiRequest() (*GasStationResponse, error) { return &res, nil } -func (dpa *EthStation) result(p int64) *big.Int { - pb := float64(p) / 10.0 +func (dpa *EthStation) result(p float64) *big.Int { + pb := p / 10.0 return priceMaxUpperBound(units.FloatGweiToBigIntWei(pb), dpa.upperBound) } // GasStationResponse returns the gas station response. type GasStationResponse struct { - Fast int64 `json:"fast"` - Fastest int64 `json:"fastest"` - SafeLow int64 `json:"safeLow"` - Average int64 `json:"average"` + Fast float64 `json:"fast"` + Fastest float64 `json:"fastest"` + SafeLow float64 `json:"safeLow"` + Average float64 `json:"average"` BlockTime float64 `json:"block_time"` BlockNum int64 `json:"blockNum"` Speed float64 `json:"speed"` diff --git a/fees/gas/matic.go b/transfer/gas/matic.go similarity index 100% rename from fees/gas/matic.go rename to transfer/gas/matic.go diff --git a/fees/gas/multichain_station.go b/transfer/gas/multichain_station.go similarity index 100% rename from fees/gas/multichain_station.go rename to transfer/gas/multichain_station.go diff --git a/fees/gas/static.go b/transfer/gas/static.go similarity index 100% rename from fees/gas/static.go rename to transfer/gas/static.go diff --git a/fees/gas/station.go b/transfer/gas/station.go similarity index 100% rename from fees/gas/station.go rename to transfer/gas/station.go diff --git a/fees/handler.go b/transfer/handler.go similarity index 94% rename from fees/handler.go rename to transfer/handler.go index 7bee386..55ed514 100644 --- a/fees/handler.go +++ b/transfer/handler.go @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package fees +package transfer import ( "errors" @@ -51,9 +51,9 @@ type HandlerOpts struct { // all result in producing a transaction. type TransactionSendFn func() (*types.Transaction, error) -// ErrQueueFull is returned if the current queue is full and incremeting gas price will be impossible. +// ErrBlockchainQueueFull is returned if the current queue is full and incremeting gas price will be impossible. // Transactions which receive this error should be retried later. -var ErrQueueFull = errors.New("failed to send a transaction, queue is full") +var ErrBlockchainQueueFull = errors.New("failed to send a transaction, blockchain queue is full") // ErrNoSigners is returned if there are no signers to use for incrementing this transaction. var ErrNoSigners = errors.New("failed to send a transaction, no signers for incrementing") @@ -119,7 +119,7 @@ func (t *TransactionHandler) canQueue(opts HandlerOpts) error { return err } if !canQ { - return ErrQueueFull + return ErrBlockchainQueueFull } if !t.inc.CanSign(opts.SenderAddress) { diff --git a/fees/incrementor.go b/transfer/incrementor.go similarity index 99% rename from fees/incrementor.go rename to transfer/incrementor.go index 2934166..1f4574e 100644 --- a/fees/incrementor.go +++ b/transfer/incrementor.go @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package fees +package transfer import ( "errors" diff --git a/fees/incrementor_test.go b/transfer/incrementor_test.go similarity index 99% rename from fees/incrementor_test.go rename to transfer/incrementor_test.go index e03cf51..71871c2 100644 --- a/fees/incrementor_test.go +++ b/transfer/incrementor_test.go @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package fees +package transfer import ( "errors" diff --git a/fees/price/coinranking.go b/transfer/price/coinranking.go similarity index 100% rename from fees/price/coinranking.go rename to transfer/price/coinranking.go diff --git a/fees/price/gecko.go b/transfer/price/gecko.go similarity index 100% rename from fees/price/gecko.go rename to transfer/price/gecko.go diff --git a/transfer/queue.go b/transfer/queue.go new file mode 100644 index 0000000..afafaed --- /dev/null +++ b/transfer/queue.go @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2021 The "MysteriumNetwork/payments" Authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package transfer + +import ( + "errors" + "sync" + + "github.com/ethereum/go-ethereum/core/types" +) + +// Queue is channel queue which is able to +// queue transaction execution funcs. +type Queue struct { + queue chan queueEntry + stop chan struct{} + + once sync.Once +} + +// ErrQueueClosed is returned when queue is closed and transaction was not processed. +var ErrQueueClosed = errors.New("queue was closed") + +// ErrQueueMissingResult is returned if neither an error or a transaction exists in the queue response. +var ErrQueueMissingResult = errors.New("transaction missing with no previous error, state unknown") + +type queueEntry struct { + exec TransactionSendFn + resp chan<- QueueResponse +} + +// NewQueue returns a new queue. Size for the queue can be given +// so that more than 1 transaction could be queued at a time. +func NewQueue(size uint) *Queue { + return &Queue{ + queue: make(chan queueEntry, size), + stop: make(chan struct{}, 0), + } +} + +// Run will start to read the queue. +func (q *Queue) Run() { + for { + select { + case <-q.stop: + close(q.queue) + for entry := range q.queue { + q.resp(nil, ErrQueueClosed, entry.resp) + } + + return + case entry := <-q.queue: + tx, err := entry.exec() + q.resp(tx, err, entry.resp) + } + } +} + +func (q *Queue) resp(tx *types.Transaction, err error, ch chan<- QueueResponse) { + ch <- QueueResponse{ + tx: tx, + err: err, + } + close(ch) +} + +// Stop will stop the thread. No new transactions can be enqueued after. +func (q *Queue) Stop() { + q.once.Do(func() { + close(q.stop) + }) +} + +// TransactionEnqueue will enqueue a given transaction and respond on the given resp channel. +// +// Enqueue will fail and instantly return an error if the queue is closed. +// The given `resp` channel should be single use only. After receiving a message that channel will be closed. +func (q *Queue) TransactionEnqueue(exec TransactionSendFn, resp chan<- QueueResponse) error { + select { + case <-q.stop: + // If stop is closed, dont submit new entries + return ErrQueueClosed + default: + q.queue <- queueEntry{ + exec: exec, + resp: resp, + } + } + + return nil +} + +type QueueResponse struct { + tx *types.Transaction + err error +} + +// Result extracts the innards of the queue response. +func (qr *QueueResponse) Result() (*types.Transaction, error) { + if qr.tx == nil && qr.err == nil { + return nil, ErrQueueMissingResult + } + + return qr.tx, qr.err +} diff --git a/transfer/queue_test.go b/transfer/queue_test.go new file mode 100644 index 0000000..a52d87a --- /dev/null +++ b/transfer/queue_test.go @@ -0,0 +1,56 @@ +package transfer + +import ( + "errors" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" +) + +func TestQueue(t *testing.T) { + t.Run("green path", func(t *testing.T) { + q := NewQueue(1) + go q.Run() + defer q.Stop() + fn := func() (*types.Transaction, error) { + return types.NewTransaction(1, common.Address{}, big.NewInt(1), 10, big.NewInt(1), []byte{}), nil + } + resp := make(chan QueueResponse, 0) + err := q.TransactionEnqueue(fn, resp) + + got := <-resp + tx, err := got.Result() + assert.NoError(t, err) + assert.NotNil(t, tx) + assert.Equal(t, uint64(0x1), tx.Nonce()) + }) + t.Run("exec produced an error", func(t *testing.T) { + q := NewQueue(1) + go q.Run() + defer q.Stop() + fn := func() (*types.Transaction, error) { + return nil, errors.New(":(") + } + resp := make(chan QueueResponse, 0) + err := q.TransactionEnqueue(fn, resp) + + got := <-resp + tx, err := got.Result() + assert.Error(t, err) + assert.Nil(t, tx) + }) + t.Run("closed queue returns an error", func(t *testing.T) { + q := NewQueue(1) + q.Stop() + fn := func() (*types.Transaction, error) { + return types.NewTransaction(1, common.Address{}, big.NewInt(1), 10, big.NewInt(1), []byte{}), nil + } + resp := make(chan QueueResponse, 0) + err := q.TransactionEnqueue(fn, resp) + assert.ErrorIs(t, err, ErrQueueClosed) + assert.Len(t, resp, 0) + }) +} diff --git a/fees/transaction.go b/transfer/transaction.go similarity index 99% rename from fees/transaction.go rename to transfer/transaction.go index 0764da5..69cd56d 100644 --- a/fees/transaction.go +++ b/transfer/transaction.go @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -package fees +package transfer import ( "errors" From 51c7fb3748220739ece794882d563505938a68f8 Mon Sep 17 00:00:00 2001 From: Viktoras Kuznecovas Date: Mon, 2 Aug 2021 12:23:08 +0300 Subject: [PATCH 14/14] Filtering added --- client/bc.go | 1 + client/client.go | 24 ++++++++++++++++++++++++ client/multichain_client.go | 9 +++++++++ 3 files changed, 34 insertions(+) diff --git a/client/bc.go b/client/bc.go index 96d5d66..9c9bd33 100644 --- a/client/bc.go +++ b/client/bc.go @@ -90,6 +90,7 @@ type BC interface { PayAndSettle(psr PayAndSettleRequest) (*types.Transaction, error) IsChannelOpened(registryID, identity, hermesID common.Address) (bool, error) + FilterPromiseSettledEventByChannelID(from uint64, to *uint64, hermesID common.Address, providerAddresses [][32]byte) ([]bindings.HermesImplementationPromiseSettled, error) } // EtherClient interface implements all methods required for a EtherClient to work diff --git a/client/client.go b/client/client.go index e1cf9e3..f975349 100644 --- a/client/client.go +++ b/client/client.go @@ -1024,6 +1024,30 @@ func (bc *Blockchain) SubscribeToPromiseSettledEventByChannelID(hermesID common. return sink, sub.Unsubscribe, nil } +// FilterPromiseSettledEventByChannelID filters promise settled events +func (bc *Blockchain) FilterPromiseSettledEventByChannelID(from uint64, to *uint64, hermesID common.Address, providerAddresses [][32]byte) ([]bindings.HermesImplementationPromiseSettled, error) { + caller, err := bindings.NewHermesImplementationFilterer(hermesID, bc.ethClient.Client()) + if err != nil { + return nil, errors.Wrap(err, "could not create hermes caller") + } + ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout) + defer cancel() + iter, err := caller.FilterPromiseSettled(&bind.FilterOpts{ + Start: from, + End: to, + Context: ctx, + }, providerAddresses, []common.Address{}) + if err != nil { + return nil, err + } + res := make([]bindings.HermesImplementationPromiseSettled, 0) + for iter.Next() { + ev := iter.Event + res = append(res, *ev) + } + return res, nil +} + // GetEthBalance gets the current ethereum balance for the address. func (bc *Blockchain) GetEthBalance(address common.Address) (*big.Int, error) { ctx, cancel := context.WithTimeout(context.Background(), bc.bcTimeout) diff --git a/client/multichain_client.go b/client/multichain_client.go index dc69c45..6e012c3 100644 --- a/client/multichain_client.go +++ b/client/multichain_client.go @@ -135,6 +135,15 @@ func (mbc *MultichainBlockchainClient) SuggestGasPrice(chainID int64) (*big.Int, return bc.SuggestGasPrice() } +func (mbc *MultichainBlockchainClient) FilterPromiseSettledEventByChannelID(chainID int64, from uint64, to *uint64, hermesID common.Address, providerAddresses [][32]byte) ([]bindings.HermesImplementationPromiseSettled, error) { + bc, err := mbc.getClientByChain(chainID) + if err != nil { + return nil, err + } + + return bc.FilterPromiseSettledEventByChannelID(from, to, hermesID, providerAddresses) +} + func (mbc *MultichainBlockchainClient) SubscribeToConsumerChannelBalanceUpdate(chainID int64, mystSCAddress common.Address, channelAddresses []common.Address) (sink chan *bindings.MystTokenTransfer, cancel func(), err error) { bc, err := mbc.getClientByChain(chainID) if err != nil {