diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 198badfc5..a5edf0aed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,8 +45,8 @@ jobs: source scripts/constants.sh go test ./... - e2e_tests: - name: e2e_tests + teleporter_e2e: + name: teleporter-e2e-tests runs-on: ubuntu-22.04 steps: - name: Checkout repositories and submodules @@ -67,15 +67,52 @@ jobs: run: | export PATH=$PATH:$HOME/.foundry/bin export PATH="$PATH:$GOPATH/bin" - ./scripts/local/e2e_test.sh + ./scripts/local/e2e_test.sh --components teleporter - - name: Upload tmpnet network dir - uses: actions/upload-artifact@v4 - if: always() + governance_e2e: + name: governance-e2e-tests + runs-on: ubuntu-22.04 + steps: + - name: Checkout repositories and submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: Install Foundry + run: ./scripts/install_foundry.sh + + - name: Run E2E Tests + # Forge installs to BASE_DIR, but updates the PATH definition in $HOME/.bashrc + run: | + export PATH=$PATH:$HOME/.foundry/bin + export PATH="$PATH:$GOPATH/bin" + ./scripts/local/e2e_test.sh --components governance + + validator_manager_e2e: + name: validator-manager-e2e-tests + runs-on: ubuntu-22.04 + steps: + - name: Checkout repositories and submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Go + uses: actions/setup-go@v5 with: - name: e2e-tmpnet-data - path: | - ~/.tmpnet/networks - ~/.tmpnet/prometheus/prometheus.log - ~/.tmpnet/promtail/promtail.log - if-no-files-found: error + go-version-file: 'go.mod' + + - name: Install Foundry + run: ./scripts/install_foundry.sh + + - name: Run E2E Tests + # Forge installs to BASE_DIR, but updates the PATH definition in $HOME/.bashrc + run: | + export PATH=$PATH:$HOME/.foundry/bin + export PATH="$PATH:$GOPATH/bin" + ./scripts/local/e2e_test.sh --components validator-manager diff --git a/.gitignore b/.gitignore index 922ef3288..babc5dac1 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ server.log # Forge documentation docs/ +coverage/ diff --git a/abi-bindings/go/INativeMinter/INativeMinter.go b/abi-bindings/go/INativeMinter/INativeMinter.go new file mode 100644 index 000000000..308b401a0 --- /dev/null +++ b/abi-bindings/go/INativeMinter/INativeMinter.go @@ -0,0 +1,634 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package inativeminter + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// INativeMinterMetaData contains all meta data concerning the INativeMinter contract. +var INativeMinterMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"mintNativeCoin\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"readAllowList\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"role\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setAdmin\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setEnabled\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setManager\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setNone\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"NativeCoinMinted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleSet\",\"inputs\":[{\"name\":\"role\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"oldRole\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", +} + +// INativeMinterABI is the input ABI used to generate the binding from. +// Deprecated: Use INativeMinterMetaData.ABI instead. +var INativeMinterABI = INativeMinterMetaData.ABI + +// INativeMinter is an auto generated Go binding around an Ethereum contract. +type INativeMinter struct { + INativeMinterCaller // Read-only binding to the contract + INativeMinterTransactor // Write-only binding to the contract + INativeMinterFilterer // Log filterer for contract events +} + +// INativeMinterCaller is an auto generated read-only Go binding around an Ethereum contract. +type INativeMinterCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// INativeMinterTransactor is an auto generated write-only Go binding around an Ethereum contract. +type INativeMinterTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// INativeMinterFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type INativeMinterFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// INativeMinterSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type INativeMinterSession struct { + Contract *INativeMinter // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// INativeMinterCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type INativeMinterCallerSession struct { + Contract *INativeMinterCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// INativeMinterTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type INativeMinterTransactorSession struct { + Contract *INativeMinterTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// INativeMinterRaw is an auto generated low-level Go binding around an Ethereum contract. +type INativeMinterRaw struct { + Contract *INativeMinter // Generic contract binding to access the raw methods on +} + +// INativeMinterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type INativeMinterCallerRaw struct { + Contract *INativeMinterCaller // Generic read-only contract binding to access the raw methods on +} + +// INativeMinterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type INativeMinterTransactorRaw struct { + Contract *INativeMinterTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewINativeMinter creates a new instance of INativeMinter, bound to a specific deployed contract. +func NewINativeMinter(address common.Address, backend bind.ContractBackend) (*INativeMinter, error) { + contract, err := bindINativeMinter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &INativeMinter{INativeMinterCaller: INativeMinterCaller{contract: contract}, INativeMinterTransactor: INativeMinterTransactor{contract: contract}, INativeMinterFilterer: INativeMinterFilterer{contract: contract}}, nil +} + +// NewINativeMinterCaller creates a new read-only instance of INativeMinter, bound to a specific deployed contract. +func NewINativeMinterCaller(address common.Address, caller bind.ContractCaller) (*INativeMinterCaller, error) { + contract, err := bindINativeMinter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &INativeMinterCaller{contract: contract}, nil +} + +// NewINativeMinterTransactor creates a new write-only instance of INativeMinter, bound to a specific deployed contract. +func NewINativeMinterTransactor(address common.Address, transactor bind.ContractTransactor) (*INativeMinterTransactor, error) { + contract, err := bindINativeMinter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &INativeMinterTransactor{contract: contract}, nil +} + +// NewINativeMinterFilterer creates a new log filterer instance of INativeMinter, bound to a specific deployed contract. +func NewINativeMinterFilterer(address common.Address, filterer bind.ContractFilterer) (*INativeMinterFilterer, error) { + contract, err := bindINativeMinter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &INativeMinterFilterer{contract: contract}, nil +} + +// bindINativeMinter binds a generic wrapper to an already deployed contract. +func bindINativeMinter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := INativeMinterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_INativeMinter *INativeMinterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _INativeMinter.Contract.INativeMinterCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_INativeMinter *INativeMinterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _INativeMinter.Contract.INativeMinterTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_INativeMinter *INativeMinterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _INativeMinter.Contract.INativeMinterTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_INativeMinter *INativeMinterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _INativeMinter.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_INativeMinter *INativeMinterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _INativeMinter.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_INativeMinter *INativeMinterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _INativeMinter.Contract.contract.Transact(opts, method, params...) +} + +// ReadAllowList is a free data retrieval call binding the contract method 0xeb54dae1. +// +// Solidity: function readAllowList(address addr) view returns(uint256 role) +func (_INativeMinter *INativeMinterCaller) ReadAllowList(opts *bind.CallOpts, addr common.Address) (*big.Int, error) { + var out []interface{} + err := _INativeMinter.contract.Call(opts, &out, "readAllowList", addr) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ReadAllowList is a free data retrieval call binding the contract method 0xeb54dae1. +// +// Solidity: function readAllowList(address addr) view returns(uint256 role) +func (_INativeMinter *INativeMinterSession) ReadAllowList(addr common.Address) (*big.Int, error) { + return _INativeMinter.Contract.ReadAllowList(&_INativeMinter.CallOpts, addr) +} + +// ReadAllowList is a free data retrieval call binding the contract method 0xeb54dae1. +// +// Solidity: function readAllowList(address addr) view returns(uint256 role) +func (_INativeMinter *INativeMinterCallerSession) ReadAllowList(addr common.Address) (*big.Int, error) { + return _INativeMinter.Contract.ReadAllowList(&_INativeMinter.CallOpts, addr) +} + +// MintNativeCoin is a paid mutator transaction binding the contract method 0x4f5aaaba. +// +// Solidity: function mintNativeCoin(address addr, uint256 amount) returns() +func (_INativeMinter *INativeMinterTransactor) MintNativeCoin(opts *bind.TransactOpts, addr common.Address, amount *big.Int) (*types.Transaction, error) { + return _INativeMinter.contract.Transact(opts, "mintNativeCoin", addr, amount) +} + +// MintNativeCoin is a paid mutator transaction binding the contract method 0x4f5aaaba. +// +// Solidity: function mintNativeCoin(address addr, uint256 amount) returns() +func (_INativeMinter *INativeMinterSession) MintNativeCoin(addr common.Address, amount *big.Int) (*types.Transaction, error) { + return _INativeMinter.Contract.MintNativeCoin(&_INativeMinter.TransactOpts, addr, amount) +} + +// MintNativeCoin is a paid mutator transaction binding the contract method 0x4f5aaaba. +// +// Solidity: function mintNativeCoin(address addr, uint256 amount) returns() +func (_INativeMinter *INativeMinterTransactorSession) MintNativeCoin(addr common.Address, amount *big.Int) (*types.Transaction, error) { + return _INativeMinter.Contract.MintNativeCoin(&_INativeMinter.TransactOpts, addr, amount) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address addr) returns() +func (_INativeMinter *INativeMinterTransactor) SetAdmin(opts *bind.TransactOpts, addr common.Address) (*types.Transaction, error) { + return _INativeMinter.contract.Transact(opts, "setAdmin", addr) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address addr) returns() +func (_INativeMinter *INativeMinterSession) SetAdmin(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetAdmin(&_INativeMinter.TransactOpts, addr) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address addr) returns() +func (_INativeMinter *INativeMinterTransactorSession) SetAdmin(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetAdmin(&_INativeMinter.TransactOpts, addr) +} + +// SetEnabled is a paid mutator transaction binding the contract method 0x0aaf7043. +// +// Solidity: function setEnabled(address addr) returns() +func (_INativeMinter *INativeMinterTransactor) SetEnabled(opts *bind.TransactOpts, addr common.Address) (*types.Transaction, error) { + return _INativeMinter.contract.Transact(opts, "setEnabled", addr) +} + +// SetEnabled is a paid mutator transaction binding the contract method 0x0aaf7043. +// +// Solidity: function setEnabled(address addr) returns() +func (_INativeMinter *INativeMinterSession) SetEnabled(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetEnabled(&_INativeMinter.TransactOpts, addr) +} + +// SetEnabled is a paid mutator transaction binding the contract method 0x0aaf7043. +// +// Solidity: function setEnabled(address addr) returns() +func (_INativeMinter *INativeMinterTransactorSession) SetEnabled(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetEnabled(&_INativeMinter.TransactOpts, addr) +} + +// SetManager is a paid mutator transaction binding the contract method 0xd0ebdbe7. +// +// Solidity: function setManager(address addr) returns() +func (_INativeMinter *INativeMinterTransactor) SetManager(opts *bind.TransactOpts, addr common.Address) (*types.Transaction, error) { + return _INativeMinter.contract.Transact(opts, "setManager", addr) +} + +// SetManager is a paid mutator transaction binding the contract method 0xd0ebdbe7. +// +// Solidity: function setManager(address addr) returns() +func (_INativeMinter *INativeMinterSession) SetManager(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetManager(&_INativeMinter.TransactOpts, addr) +} + +// SetManager is a paid mutator transaction binding the contract method 0xd0ebdbe7. +// +// Solidity: function setManager(address addr) returns() +func (_INativeMinter *INativeMinterTransactorSession) SetManager(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetManager(&_INativeMinter.TransactOpts, addr) +} + +// SetNone is a paid mutator transaction binding the contract method 0x8c6bfb3b. +// +// Solidity: function setNone(address addr) returns() +func (_INativeMinter *INativeMinterTransactor) SetNone(opts *bind.TransactOpts, addr common.Address) (*types.Transaction, error) { + return _INativeMinter.contract.Transact(opts, "setNone", addr) +} + +// SetNone is a paid mutator transaction binding the contract method 0x8c6bfb3b. +// +// Solidity: function setNone(address addr) returns() +func (_INativeMinter *INativeMinterSession) SetNone(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetNone(&_INativeMinter.TransactOpts, addr) +} + +// SetNone is a paid mutator transaction binding the contract method 0x8c6bfb3b. +// +// Solidity: function setNone(address addr) returns() +func (_INativeMinter *INativeMinterTransactorSession) SetNone(addr common.Address) (*types.Transaction, error) { + return _INativeMinter.Contract.SetNone(&_INativeMinter.TransactOpts, addr) +} + +// INativeMinterNativeCoinMintedIterator is returned from FilterNativeCoinMinted and is used to iterate over the raw logs and unpacked data for NativeCoinMinted events raised by the INativeMinter contract. +type INativeMinterNativeCoinMintedIterator struct { + Event *INativeMinterNativeCoinMinted // 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 interfaces.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 *INativeMinterNativeCoinMintedIterator) 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(INativeMinterNativeCoinMinted) + 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(INativeMinterNativeCoinMinted) + 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 *INativeMinterNativeCoinMintedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *INativeMinterNativeCoinMintedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// INativeMinterNativeCoinMinted represents a NativeCoinMinted event raised by the INativeMinter contract. +type INativeMinterNativeCoinMinted struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNativeCoinMinted is a free log retrieval operation binding the contract event 0x400cd392f3d56fd10bb1dbd5839fdda8298208ddaa97b368faa053e1850930ee. +// +// Solidity: event NativeCoinMinted(address indexed sender, address indexed recipient, uint256 amount) +func (_INativeMinter *INativeMinterFilterer) FilterNativeCoinMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*INativeMinterNativeCoinMintedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _INativeMinter.contract.FilterLogs(opts, "NativeCoinMinted", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &INativeMinterNativeCoinMintedIterator{contract: _INativeMinter.contract, event: "NativeCoinMinted", logs: logs, sub: sub}, nil +} + +// WatchNativeCoinMinted is a free log subscription operation binding the contract event 0x400cd392f3d56fd10bb1dbd5839fdda8298208ddaa97b368faa053e1850930ee. +// +// Solidity: event NativeCoinMinted(address indexed sender, address indexed recipient, uint256 amount) +func (_INativeMinter *INativeMinterFilterer) WatchNativeCoinMinted(opts *bind.WatchOpts, sink chan<- *INativeMinterNativeCoinMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _INativeMinter.contract.WatchLogs(opts, "NativeCoinMinted", senderRule, recipientRule) + 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(INativeMinterNativeCoinMinted) + if err := _INativeMinter.contract.UnpackLog(event, "NativeCoinMinted", 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 +} + +// ParseNativeCoinMinted is a log parse operation binding the contract event 0x400cd392f3d56fd10bb1dbd5839fdda8298208ddaa97b368faa053e1850930ee. +// +// Solidity: event NativeCoinMinted(address indexed sender, address indexed recipient, uint256 amount) +func (_INativeMinter *INativeMinterFilterer) ParseNativeCoinMinted(log types.Log) (*INativeMinterNativeCoinMinted, error) { + event := new(INativeMinterNativeCoinMinted) + if err := _INativeMinter.contract.UnpackLog(event, "NativeCoinMinted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// INativeMinterRoleSetIterator is returned from FilterRoleSet and is used to iterate over the raw logs and unpacked data for RoleSet events raised by the INativeMinter contract. +type INativeMinterRoleSetIterator struct { + Event *INativeMinterRoleSet // 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 interfaces.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 *INativeMinterRoleSetIterator) 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(INativeMinterRoleSet) + 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(INativeMinterRoleSet) + 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 *INativeMinterRoleSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *INativeMinterRoleSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// INativeMinterRoleSet represents a RoleSet event raised by the INativeMinter contract. +type INativeMinterRoleSet struct { + Role *big.Int + Account common.Address + Sender common.Address + OldRole *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleSet is a free log retrieval operation binding the contract event 0xcdb7ea01f00a414d78757bdb0f6391664ba3fedf987eed280927c1e7d695be3e. +// +// Solidity: event RoleSet(uint256 indexed role, address indexed account, address indexed sender, uint256 oldRole) +func (_INativeMinter *INativeMinterFilterer) FilterRoleSet(opts *bind.FilterOpts, role []*big.Int, account []common.Address, sender []common.Address) (*INativeMinterRoleSetIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _INativeMinter.contract.FilterLogs(opts, "RoleSet", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &INativeMinterRoleSetIterator{contract: _INativeMinter.contract, event: "RoleSet", logs: logs, sub: sub}, nil +} + +// WatchRoleSet is a free log subscription operation binding the contract event 0xcdb7ea01f00a414d78757bdb0f6391664ba3fedf987eed280927c1e7d695be3e. +// +// Solidity: event RoleSet(uint256 indexed role, address indexed account, address indexed sender, uint256 oldRole) +func (_INativeMinter *INativeMinterFilterer) WatchRoleSet(opts *bind.WatchOpts, sink chan<- *INativeMinterRoleSet, role []*big.Int, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _INativeMinter.contract.WatchLogs(opts, "RoleSet", roleRule, accountRule, senderRule) + 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(INativeMinterRoleSet) + if err := _INativeMinter.contract.UnpackLog(event, "RoleSet", 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 +} + +// ParseRoleSet is a log parse operation binding the contract event 0xcdb7ea01f00a414d78757bdb0f6391664ba3fedf987eed280927c1e7d695be3e. +// +// Solidity: event RoleSet(uint256 indexed role, address indexed account, address indexed sender, uint256 oldRole) +func (_INativeMinter *INativeMinterFilterer) ParseRoleSet(log types.Log) (*INativeMinterRoleSet, error) { + event := new(INativeMinterRoleSet) + if err := _INativeMinter.contract.UnpackLog(event, "RoleSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/abi-bindings/go/ProxyAdmin/ProxyAdmin.go b/abi-bindings/go/ProxyAdmin/ProxyAdmin.go new file mode 100644 index 000000000..02989d202 --- /dev/null +++ b/abi-bindings/go/ProxyAdmin/ProxyAdmin.go @@ -0,0 +1,481 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package proxyadmin + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ProxyAdminMetaData contains all meta data concerning the ProxyAdmin contract. +var ProxyAdminMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"initialOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeAndCall\",\"inputs\":[{\"name\":\"proxy\",\"type\":\"address\",\"internalType\":\"contractITransparentUpgradeableProxy\"},{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x608060405234801561000f575f80fd5b506040516104d33803806104d383398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b6103de806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea164736f6c6343000819000a", +} + +// ProxyAdminABI is the input ABI used to generate the binding from. +// Deprecated: Use ProxyAdminMetaData.ABI instead. +var ProxyAdminABI = ProxyAdminMetaData.ABI + +// ProxyAdminBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ProxyAdminMetaData.Bin instead. +var ProxyAdminBin = ProxyAdminMetaData.Bin + +// DeployProxyAdmin deploys a new Ethereum contract, binding an instance of ProxyAdmin to it. +func DeployProxyAdmin(auth *bind.TransactOpts, backend bind.ContractBackend, initialOwner common.Address) (common.Address, *types.Transaction, *ProxyAdmin, error) { + parsed, err := ProxyAdminMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ProxyAdminBin), backend, initialOwner) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ProxyAdmin{ProxyAdminCaller: ProxyAdminCaller{contract: contract}, ProxyAdminTransactor: ProxyAdminTransactor{contract: contract}, ProxyAdminFilterer: ProxyAdminFilterer{contract: contract}}, nil +} + +// ProxyAdmin is an auto generated Go binding around an Ethereum contract. +type ProxyAdmin struct { + ProxyAdminCaller // Read-only binding to the contract + ProxyAdminTransactor // Write-only binding to the contract + ProxyAdminFilterer // Log filterer for contract events +} + +// ProxyAdminCaller is an auto generated read-only Go binding around an Ethereum contract. +type ProxyAdminCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ProxyAdminTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ProxyAdminTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ProxyAdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ProxyAdminFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ProxyAdminSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ProxyAdminSession struct { + Contract *ProxyAdmin // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ProxyAdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ProxyAdminCallerSession struct { + Contract *ProxyAdminCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ProxyAdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ProxyAdminTransactorSession struct { + Contract *ProxyAdminTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ProxyAdminRaw is an auto generated low-level Go binding around an Ethereum contract. +type ProxyAdminRaw struct { + Contract *ProxyAdmin // Generic contract binding to access the raw methods on +} + +// ProxyAdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ProxyAdminCallerRaw struct { + Contract *ProxyAdminCaller // Generic read-only contract binding to access the raw methods on +} + +// ProxyAdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ProxyAdminTransactorRaw struct { + Contract *ProxyAdminTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewProxyAdmin creates a new instance of ProxyAdmin, bound to a specific deployed contract. +func NewProxyAdmin(address common.Address, backend bind.ContractBackend) (*ProxyAdmin, error) { + contract, err := bindProxyAdmin(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ProxyAdmin{ProxyAdminCaller: ProxyAdminCaller{contract: contract}, ProxyAdminTransactor: ProxyAdminTransactor{contract: contract}, ProxyAdminFilterer: ProxyAdminFilterer{contract: contract}}, nil +} + +// NewProxyAdminCaller creates a new read-only instance of ProxyAdmin, bound to a specific deployed contract. +func NewProxyAdminCaller(address common.Address, caller bind.ContractCaller) (*ProxyAdminCaller, error) { + contract, err := bindProxyAdmin(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ProxyAdminCaller{contract: contract}, nil +} + +// NewProxyAdminTransactor creates a new write-only instance of ProxyAdmin, bound to a specific deployed contract. +func NewProxyAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*ProxyAdminTransactor, error) { + contract, err := bindProxyAdmin(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ProxyAdminTransactor{contract: contract}, nil +} + +// NewProxyAdminFilterer creates a new log filterer instance of ProxyAdmin, bound to a specific deployed contract. +func NewProxyAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*ProxyAdminFilterer, error) { + contract, err := bindProxyAdmin(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ProxyAdminFilterer{contract: contract}, nil +} + +// bindProxyAdmin binds a generic wrapper to an already deployed contract. +func bindProxyAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ProxyAdminMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ProxyAdmin *ProxyAdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ProxyAdmin.Contract.ProxyAdminCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ProxyAdmin *ProxyAdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ProxyAdmin.Contract.ProxyAdminTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ProxyAdmin *ProxyAdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ProxyAdmin.Contract.ProxyAdminTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ProxyAdmin *ProxyAdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ProxyAdmin.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ProxyAdmin *ProxyAdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ProxyAdmin.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ProxyAdmin *ProxyAdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ProxyAdmin.Contract.contract.Transact(opts, method, params...) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_ProxyAdmin *ProxyAdminCaller) UPGRADEINTERFACEVERSION(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ProxyAdmin.contract.Call(opts, &out, "UPGRADE_INTERFACE_VERSION") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_ProxyAdmin *ProxyAdminSession) UPGRADEINTERFACEVERSION() (string, error) { + return _ProxyAdmin.Contract.UPGRADEINTERFACEVERSION(&_ProxyAdmin.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_ProxyAdmin *ProxyAdminCallerSession) UPGRADEINTERFACEVERSION() (string, error) { + return _ProxyAdmin.Contract.UPGRADEINTERFACEVERSION(&_ProxyAdmin.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ProxyAdmin *ProxyAdminCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ProxyAdmin.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ProxyAdmin *ProxyAdminSession) Owner() (common.Address, error) { + return _ProxyAdmin.Contract.Owner(&_ProxyAdmin.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ProxyAdmin *ProxyAdminCallerSession) Owner() (common.Address, error) { + return _ProxyAdmin.Contract.Owner(&_ProxyAdmin.CallOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ProxyAdmin *ProxyAdminTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ProxyAdmin.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ProxyAdmin *ProxyAdminSession) RenounceOwnership() (*types.Transaction, error) { + return _ProxyAdmin.Contract.RenounceOwnership(&_ProxyAdmin.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ProxyAdmin *ProxyAdminTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _ProxyAdmin.Contract.RenounceOwnership(&_ProxyAdmin.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ProxyAdmin *ProxyAdminTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _ProxyAdmin.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ProxyAdmin *ProxyAdminSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _ProxyAdmin.Contract.TransferOwnership(&_ProxyAdmin.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ProxyAdmin *ProxyAdminTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _ProxyAdmin.Contract.TransferOwnership(&_ProxyAdmin.TransactOpts, newOwner) +} + +// UpgradeAndCall is a paid mutator transaction binding the contract method 0x9623609d. +// +// Solidity: function upgradeAndCall(address proxy, address implementation, bytes data) payable returns() +func (_ProxyAdmin *ProxyAdminTransactor) UpgradeAndCall(opts *bind.TransactOpts, proxy common.Address, implementation common.Address, data []byte) (*types.Transaction, error) { + return _ProxyAdmin.contract.Transact(opts, "upgradeAndCall", proxy, implementation, data) +} + +// UpgradeAndCall is a paid mutator transaction binding the contract method 0x9623609d. +// +// Solidity: function upgradeAndCall(address proxy, address implementation, bytes data) payable returns() +func (_ProxyAdmin *ProxyAdminSession) UpgradeAndCall(proxy common.Address, implementation common.Address, data []byte) (*types.Transaction, error) { + return _ProxyAdmin.Contract.UpgradeAndCall(&_ProxyAdmin.TransactOpts, proxy, implementation, data) +} + +// UpgradeAndCall is a paid mutator transaction binding the contract method 0x9623609d. +// +// Solidity: function upgradeAndCall(address proxy, address implementation, bytes data) payable returns() +func (_ProxyAdmin *ProxyAdminTransactorSession) UpgradeAndCall(proxy common.Address, implementation common.Address, data []byte) (*types.Transaction, error) { + return _ProxyAdmin.Contract.UpgradeAndCall(&_ProxyAdmin.TransactOpts, proxy, implementation, data) +} + +// ProxyAdminOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the ProxyAdmin contract. +type ProxyAdminOwnershipTransferredIterator struct { + Event *ProxyAdminOwnershipTransferred // 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 interfaces.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 *ProxyAdminOwnershipTransferredIterator) 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(ProxyAdminOwnershipTransferred) + 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(ProxyAdminOwnershipTransferred) + 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 *ProxyAdminOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ProxyAdminOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ProxyAdminOwnershipTransferred represents a OwnershipTransferred event raised by the ProxyAdmin contract. +type ProxyAdminOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ProxyAdmin *ProxyAdminFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*ProxyAdminOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _ProxyAdmin.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &ProxyAdminOwnershipTransferredIterator{contract: _ProxyAdmin.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ProxyAdmin *ProxyAdminFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ProxyAdminOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _ProxyAdmin.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(ProxyAdminOwnershipTransferred) + if err := _ProxyAdmin.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ProxyAdmin *ProxyAdminFilterer) ParseOwnershipTransferred(log types.Log) (*ProxyAdminOwnershipTransferred, error) { + event := new(ProxyAdminOwnershipTransferred) + if err := _ProxyAdmin.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/abi-bindings/go/TransparentUpgradeableProxy/TransparentUpgradeableProxy.go b/abi-bindings/go/TransparentUpgradeableProxy/TransparentUpgradeableProxy.go new file mode 100644 index 000000000..a054267e5 --- /dev/null +++ b/abi-bindings/go/TransparentUpgradeableProxy/TransparentUpgradeableProxy.go @@ -0,0 +1,503 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package transparentupgradeableproxy + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// TransparentUpgradeableProxyMetaData contains all meta data concerning the TransparentUpgradeableProxy contract. +var TransparentUpgradeableProxyMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_logic\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"initialOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"payable\"},{\"type\":\"fallback\",\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"AdminChanged\",\"inputs\":[{\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967InvalidAdmin\",\"inputs\":[{\"name\":\"admin\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ProxyDeniedAdminAccess\",\"inputs\":[]}]", + Bin: "0x60a0604052604051610dbb380380610dbb8339810160408190526100229161038c565b828161002e828261008c565b50508160405161003d9061032e565b6001600160a01b039091168152602001604051809103905ff080158015610066573d5f803e3d5ffd5b506001600160a01b031660805261008461007f60805190565b6100ea565b505050610471565b61009582610157565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100de576100d982826101d5565b505050565b6100e6610248565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6101295f80516020610d9b833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a161015481610269565b50565b806001600160a01b03163b5f0361019157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516101f19190610456565b5f60405180830381855af49150503d805f8114610229576040519150601f19603f3d011682016040523d82523d5f602084013e61022e565b606091505b50909250905061023f8583836102a6565b95945050505050565b34156102675760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b03811661029257604051633173bdd160e11b81525f6004820152602401610188565b805f80516020610d9b8339815191526101b4565b6060826102bb576102b682610305565b6102fe565b81511580156102d257506001600160a01b0384163b155b156102fb57604051639996b31560e01b81526001600160a01b0385166004820152602401610188565b50805b9392505050565b8051156103155780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6104d3806108c883390190565b80516001600160a01b0381168114610351575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b8381101561038457818101518382015260200161036c565b50505f910152565b5f805f6060848603121561039e575f80fd5b6103a78461033b565b92506103b56020850161033b565b60408501519092506001600160401b03808211156103d1575f80fd5b818601915086601f8301126103e4575f80fd5b8151818111156103f6576103f6610356565b604051601f8201601f19908116603f0116810190838211818310171561041e5761041e610356565b81604052828152896020848701011115610436575f80fd5b61044783602083016020880161036a565b80955050505050509250925092565b5f825161046781846020870161036a565b9190910192915050565b6080516104406104885f395f601001526104405ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610303565b81019061009e919061033e565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102069190610407565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102ea5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610311575f80fd5b8386111561031d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561034f575f80fd5b82356001600160a01b0381168114610365575f80fd5b9150602083013567ffffffffffffffff80821115610381575f80fd5b818501915085601f830112610394575f80fd5b8135818111156103a6576103a661032a565b604051601f8201601f19908116603f011681019083821181831017156103ce576103ce61032a565b816040528281528860208487010111156103e6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610426576020818601810151858301520161040c565b505f92019182525091905056fea164736f6c6343000819000a608060405234801561000f575f80fd5b506040516104d33803806104d383398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b6103de806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610372565b3480156100e9575f80fd5b506100616100f836600461038b565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061014890869086906004016103a6565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff808211156102a9575f80fd5b818601915086601f8301126102bc575f80fd5b8135818111156102ce576102ce61024c565b604051601f8201601f19908116603f011681019083821181831017156102f6576102f661024c565b8160405282815289602084870101111561030e575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f81518084525f5b8181101561035357602081850181015186830182015201610337565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610384602083018461032f565b9392505050565b5f6020828403121561039b575f80fd5b813561038481610238565b6001600160a01b03831681526040602082018190525f906103c99083018461032f565b94935050505056fea164736f6c6343000819000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", +} + +// TransparentUpgradeableProxyABI is the input ABI used to generate the binding from. +// Deprecated: Use TransparentUpgradeableProxyMetaData.ABI instead. +var TransparentUpgradeableProxyABI = TransparentUpgradeableProxyMetaData.ABI + +// TransparentUpgradeableProxyBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use TransparentUpgradeableProxyMetaData.Bin instead. +var TransparentUpgradeableProxyBin = TransparentUpgradeableProxyMetaData.Bin + +// DeployTransparentUpgradeableProxy deploys a new Ethereum contract, binding an instance of TransparentUpgradeableProxy to it. +func DeployTransparentUpgradeableProxy(auth *bind.TransactOpts, backend bind.ContractBackend, _logic common.Address, initialOwner common.Address, _data []byte) (common.Address, *types.Transaction, *TransparentUpgradeableProxy, error) { + parsed, err := TransparentUpgradeableProxyMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TransparentUpgradeableProxyBin), backend, _logic, initialOwner, _data) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &TransparentUpgradeableProxy{TransparentUpgradeableProxyCaller: TransparentUpgradeableProxyCaller{contract: contract}, TransparentUpgradeableProxyTransactor: TransparentUpgradeableProxyTransactor{contract: contract}, TransparentUpgradeableProxyFilterer: TransparentUpgradeableProxyFilterer{contract: contract}}, nil +} + +// TransparentUpgradeableProxy is an auto generated Go binding around an Ethereum contract. +type TransparentUpgradeableProxy struct { + TransparentUpgradeableProxyCaller // Read-only binding to the contract + TransparentUpgradeableProxyTransactor // Write-only binding to the contract + TransparentUpgradeableProxyFilterer // Log filterer for contract events +} + +// TransparentUpgradeableProxyCaller is an auto generated read-only Go binding around an Ethereum contract. +type TransparentUpgradeableProxyCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TransparentUpgradeableProxyTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TransparentUpgradeableProxyTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TransparentUpgradeableProxyFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TransparentUpgradeableProxyFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TransparentUpgradeableProxySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TransparentUpgradeableProxySession struct { + Contract *TransparentUpgradeableProxy // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TransparentUpgradeableProxyCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TransparentUpgradeableProxyCallerSession struct { + Contract *TransparentUpgradeableProxyCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TransparentUpgradeableProxyTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TransparentUpgradeableProxyTransactorSession struct { + Contract *TransparentUpgradeableProxyTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TransparentUpgradeableProxyRaw is an auto generated low-level Go binding around an Ethereum contract. +type TransparentUpgradeableProxyRaw struct { + Contract *TransparentUpgradeableProxy // Generic contract binding to access the raw methods on +} + +// TransparentUpgradeableProxyCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TransparentUpgradeableProxyCallerRaw struct { + Contract *TransparentUpgradeableProxyCaller // Generic read-only contract binding to access the raw methods on +} + +// TransparentUpgradeableProxyTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TransparentUpgradeableProxyTransactorRaw struct { + Contract *TransparentUpgradeableProxyTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTransparentUpgradeableProxy creates a new instance of TransparentUpgradeableProxy, bound to a specific deployed contract. +func NewTransparentUpgradeableProxy(address common.Address, backend bind.ContractBackend) (*TransparentUpgradeableProxy, error) { + contract, err := bindTransparentUpgradeableProxy(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &TransparentUpgradeableProxy{TransparentUpgradeableProxyCaller: TransparentUpgradeableProxyCaller{contract: contract}, TransparentUpgradeableProxyTransactor: TransparentUpgradeableProxyTransactor{contract: contract}, TransparentUpgradeableProxyFilterer: TransparentUpgradeableProxyFilterer{contract: contract}}, nil +} + +// NewTransparentUpgradeableProxyCaller creates a new read-only instance of TransparentUpgradeableProxy, bound to a specific deployed contract. +func NewTransparentUpgradeableProxyCaller(address common.Address, caller bind.ContractCaller) (*TransparentUpgradeableProxyCaller, error) { + contract, err := bindTransparentUpgradeableProxy(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TransparentUpgradeableProxyCaller{contract: contract}, nil +} + +// NewTransparentUpgradeableProxyTransactor creates a new write-only instance of TransparentUpgradeableProxy, bound to a specific deployed contract. +func NewTransparentUpgradeableProxyTransactor(address common.Address, transactor bind.ContractTransactor) (*TransparentUpgradeableProxyTransactor, error) { + contract, err := bindTransparentUpgradeableProxy(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TransparentUpgradeableProxyTransactor{contract: contract}, nil +} + +// NewTransparentUpgradeableProxyFilterer creates a new log filterer instance of TransparentUpgradeableProxy, bound to a specific deployed contract. +func NewTransparentUpgradeableProxyFilterer(address common.Address, filterer bind.ContractFilterer) (*TransparentUpgradeableProxyFilterer, error) { + contract, err := bindTransparentUpgradeableProxy(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TransparentUpgradeableProxyFilterer{contract: contract}, nil +} + +// bindTransparentUpgradeableProxy binds a generic wrapper to an already deployed contract. +func bindTransparentUpgradeableProxy(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := TransparentUpgradeableProxyMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TransparentUpgradeableProxy.Contract.TransparentUpgradeableProxyCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.Contract.TransparentUpgradeableProxyTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.Contract.TransparentUpgradeableProxyTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TransparentUpgradeableProxy.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.Contract.contract.Transact(opts, method, params...) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.contract.RawTransact(opts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxySession) Fallback(calldata []byte) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.Contract.Fallback(&_TransparentUpgradeableProxy.TransactOpts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _TransparentUpgradeableProxy.Contract.Fallback(&_TransparentUpgradeableProxy.TransactOpts, calldata) +} + +// TransparentUpgradeableProxyAdminChangedIterator is returned from FilterAdminChanged and is used to iterate over the raw logs and unpacked data for AdminChanged events raised by the TransparentUpgradeableProxy contract. +type TransparentUpgradeableProxyAdminChangedIterator struct { + Event *TransparentUpgradeableProxyAdminChanged // 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 interfaces.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 *TransparentUpgradeableProxyAdminChangedIterator) 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(TransparentUpgradeableProxyAdminChanged) + 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(TransparentUpgradeableProxyAdminChanged) + 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 *TransparentUpgradeableProxyAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TransparentUpgradeableProxyAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TransparentUpgradeableProxyAdminChanged represents a AdminChanged event raised by the TransparentUpgradeableProxy contract. +type TransparentUpgradeableProxyAdminChanged struct { + PreviousAdmin common.Address + NewAdmin common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAdminChanged is a free log retrieval operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyFilterer) FilterAdminChanged(opts *bind.FilterOpts) (*TransparentUpgradeableProxyAdminChangedIterator, error) { + + logs, sub, err := _TransparentUpgradeableProxy.contract.FilterLogs(opts, "AdminChanged") + if err != nil { + return nil, err + } + return &TransparentUpgradeableProxyAdminChangedIterator{contract: _TransparentUpgradeableProxy.contract, event: "AdminChanged", logs: logs, sub: sub}, nil +} + +// WatchAdminChanged is a free log subscription operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyFilterer) WatchAdminChanged(opts *bind.WatchOpts, sink chan<- *TransparentUpgradeableProxyAdminChanged) (event.Subscription, error) { + + logs, sub, err := _TransparentUpgradeableProxy.contract.WatchLogs(opts, "AdminChanged") + 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(TransparentUpgradeableProxyAdminChanged) + if err := _TransparentUpgradeableProxy.contract.UnpackLog(event, "AdminChanged", 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 +} + +// ParseAdminChanged is a log parse operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyFilterer) ParseAdminChanged(log types.Log) (*TransparentUpgradeableProxyAdminChanged, error) { + event := new(TransparentUpgradeableProxyAdminChanged) + if err := _TransparentUpgradeableProxy.contract.UnpackLog(event, "AdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TransparentUpgradeableProxyUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the TransparentUpgradeableProxy contract. +type TransparentUpgradeableProxyUpgradedIterator struct { + Event *TransparentUpgradeableProxyUpgraded // 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 interfaces.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 *TransparentUpgradeableProxyUpgradedIterator) 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(TransparentUpgradeableProxyUpgraded) + 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(TransparentUpgradeableProxyUpgraded) + 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 *TransparentUpgradeableProxyUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TransparentUpgradeableProxyUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TransparentUpgradeableProxyUpgraded represents a Upgraded event raised by the TransparentUpgradeableProxy contract. +type TransparentUpgradeableProxyUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*TransparentUpgradeableProxyUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _TransparentUpgradeableProxy.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &TransparentUpgradeableProxyUpgradedIterator{contract: _TransparentUpgradeableProxy.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *TransparentUpgradeableProxyUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _TransparentUpgradeableProxy.contract.WatchLogs(opts, "Upgraded", implementationRule) + 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(TransparentUpgradeableProxyUpgraded) + if err := _TransparentUpgradeableProxy.contract.UnpackLog(event, "Upgraded", 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 +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_TransparentUpgradeableProxy *TransparentUpgradeableProxyFilterer) ParseUpgraded(log types.Log) (*TransparentUpgradeableProxyUpgraded, error) { + event := new(TransparentUpgradeableProxyUpgraded) + if err := _TransparentUpgradeableProxy.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/abi-bindings/go/governance/ValidatorSetSig/ValidatorSetSig.go b/abi-bindings/go/governance/ValidatorSetSig/ValidatorSetSig.go index e330c6c51..59ff01e96 100644 --- a/abi-bindings/go/governance/ValidatorSetSig/ValidatorSetSig.go +++ b/abi-bindings/go/governance/ValidatorSetSig/ValidatorSetSig.go @@ -42,7 +42,7 @@ type ValidatorSetSigMessage struct { // ValidatorSetSigMetaData contains all meta data concerning the ValidatorSetSig contract. var ValidatorSetSigMetaData = &bind.MetaData{ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"validatorBlockchainID_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"VALIDATORS_SOURCE_ADDRESS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blockchainID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeCall\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"nonces\",\"inputs\":[{\"name\":\"targetContractAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"validateMessage\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structValidatorSetSigMessage\",\"components\":[{\"name\":\"targetBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorSetSigAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"targetContractAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"payload\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"validatorBlockchainID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Delivered\",\"inputs\":[{\"name\":\"targetContractAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]}]", - Bin: "0x60c060405234801561000f575f80fd5b50604051610b4d380380610b4d83398101604081905261002e916100b2565b60015f5560808190526040805163084279ef60e31b8152905173020000000000000000000000000000000000000591634213cf789160048083019260209291908290030181865afa158015610085573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a991906100b2565b60a052506100c9565b5f602082840312156100c2575f80fd5b5051919050565b60805160a051610a556100f85f395f818161017701526104ba01525f818161012a01526102790152610a555ff3fe608060405260043610610071575f3560e01c80637ecebe001161004c5780637ecebe00146100e05780638d6e579d14610119578063b771b3bc1461014c578063d127dc9b14610166575f80fd5b80630731775d1461007c5780635433da42146100ac5780637d969c34146100c1575f80fd5b3661007857005b5f80fd5b348015610087575f80fd5b5061008f5f81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100bf6100ba366004610642565b610199565b005b3480156100cc575f80fd5b506100bf6100db36600461079a565b6104b6565b3480156100eb575f80fd5b5061010b6100fa366004610842565b60016020525f908152604090205481565b6040519081526020016100a3565b348015610124575f80fd5b5061010b7f000000000000000000000000000000000000000000000000000000000000000081565b348015610157575f80fd5b5061008f6005600160991b0181565b348015610171575f80fd5b5061010b7f000000000000000000000000000000000000000000000000000000000000000081565b6101a161061a565b6040516306f8253560e41b815263ffffffff821660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156101ea573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261021191908101906108c9565b91509150806102755760405162461bcd60e51b815260206004820152602560248201527f56616c696461746f725365745369673a20696e76616c69642077617270206d65604482015264737361676560d81b60648201526084015b60405180910390fd5b81517f0000000000000000000000000000000000000000000000000000000000000000146102f45760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f725365745369673a20696e76616c696420736f75726365436044820152651a185a5b925160d21b606482015260840161026c565b60208201516001600160a01b0316156103655760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f725365745369673a206e6f6e2d7a65726f206f726967696e60448201526c53656e6465724164647265737360981b606482015260840161026c565b5f826040015180602001905181019061037e9190610969565b9050610389816104b6565b6060810151610399906001610a08565b604080830180516001600160a01b039081165f9081526001602052838120949094559051608085015160a0860151935191909216926103d791610a2d565b5f6040518083038185875af1925050503d805f8114610411576040519150601f19603f3d011682016040523d82523d5f602084013e610416565b606091505b50509050806104675760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f725365745369673a2063616c6c206661696c656400000000604482015260640161026c565b816060015182604001516001600160a01b03167f5942a9a3968c7d49fc51c027041544ea295f5c1e395d6d8aa35c4369959f8ed960405160405180910390a3505050506104b360015f55565b50565b80517f00000000000000000000000000000000000000000000000000000000000000001461053a5760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f725365745369673a20696e76616c6964207461726765744260448201526a1b1bd8dad8da185a5b925160aa1b606482015260840161026c565b60208101516001600160a01b031630146105ae5760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f725365745369673a20696e76616c69642076616c6964617460448201526e6f725365745369674164647265737360881b606482015260840161026c565b60608101516040808301516001600160a01b03165f90815260016020522054146104b35760405162461bcd60e51b815260206004820152601e60248201527f56616c696461746f725365745369673a20696e76616c6964206e6f6e63650000604482015260640161026c565b60025f540361063c57604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b5f60208284031215610652575f80fd5b813563ffffffff81168114610665575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c0810167ffffffffffffffff811182821017156106a3576106a361066c565b60405290565b6040516060810167ffffffffffffffff811182821017156106a3576106a361066c565b604051601f8201601f1916810167ffffffffffffffff811182821017156106f5576106f561066c565b604052919050565b6001600160a01b03811681146104b3575f80fd5b803561071c816106fd565b919050565b5f67ffffffffffffffff82111561073a5761073a61066c565b50601f01601f191660200190565b5f82601f830112610757575f80fd5b813561076a61076582610721565b6106cc565b81815284602083860101111561077e575f80fd5b816020850160208301375f918101602001919091529392505050565b5f602082840312156107aa575f80fd5b813567ffffffffffffffff808211156107c1575f80fd5b9083019060c082860312156107d4575f80fd5b6107dc610680565b823581526107ec60208401610711565b60208201526107fd60408401610711565b6040820152606083013560608201526080830135608082015260a083013582811115610827575f80fd5b61083387828601610748565b60a08301525095945050505050565b5f60208284031215610852575f80fd5b8135610665816106fd565b5f5b8381101561087757818101518382015260200161085f565b50505f910152565b5f82601f83011261088e575f80fd5b815161089c61076582610721565b8181528460208386010111156108b0575f80fd5b6108c182602083016020870161085d565b949350505050565b5f80604083850312156108da575f80fd5b825167ffffffffffffffff808211156108f1575f80fd5b9084019060608287031215610904575f80fd5b61090c6106a9565b82518152602083015161091e816106fd565b6020820152604083015182811115610934575f80fd5b6109408882860161087f565b6040830152508094505050506020830151801515811461095e575f80fd5b809150509250929050565b5f60208284031215610979575f80fd5b815167ffffffffffffffff80821115610990575f80fd5b9083019060c082860312156109a3575f80fd5b6109ab610680565b8251815260208301516109bd816106fd565b602082015260408301516109d0816106fd565b80604083015250606083015160608201526080830151608082015260a0830151828111156109fc575f80fd5b6108338782860161087f565b80820180821115610a2757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f8251610a3e81846020870161085d565b919091019291505056fea164736f6c6343000819000a", + Bin: "0x60c060405234801561000f575f80fd5b50604051610b37380380610b3783398101604081905261002e916100b2565b60015f5560808190526040805163084279ef60e31b8152905173020000000000000000000000000000000000000591634213cf789160048083019260209291908290030181865afa158015610085573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a991906100b2565b60a052506100c9565b5f602082840312156100c2575f80fd5b5051919050565b60805160a051610a3f6100f85f395f818161016801526104ab01525f818161011b015261026a0152610a3f5ff3fe608060405260043610610062575f3560e01c80630731775d1461006d5780635433da421461009d5780637d969c34146100b25780637ecebe00146100d15780638d6e579d1461010a578063b771b3bc1461013d578063d127dc9b14610157575f80fd5b3661006957005b5f80fd5b348015610078575f80fd5b506100805f81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100b06100ab366004610633565b61018a565b005b3480156100bd575f80fd5b506100b06100cc366004610787565b6104a7565b3480156100dc575f80fd5b506100fc6100eb36600461082e565b60016020525f908152604090205481565b604051908152602001610094565b348015610115575f80fd5b506100fc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610148575f80fd5b506100806005600160991b0181565b348015610162575f80fd5b506100fc7f000000000000000000000000000000000000000000000000000000000000000081565b61019261060b565b6040516306f8253560e41b815263ffffffff821660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261020291908101906108b5565b91509150806102665760405162461bcd60e51b815260206004820152602560248201527f56616c696461746f725365745369673a20696e76616c69642077617270206d65604482015264737361676560d81b60648201526084015b60405180910390fd5b81517f0000000000000000000000000000000000000000000000000000000000000000146102e55760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f725365745369673a20696e76616c696420736f75726365436044820152651a185a5b925160d21b606482015260840161025d565b60208201516001600160a01b0316156103565760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f725365745369673a206e6f6e2d7a65726f206f726967696e60448201526c53656e6465724164647265737360981b606482015260840161025d565b5f826040015180602001905181019061036f9190610954565b905061037a816104a7565b606081015161038a9060016109f2565b604080830180516001600160a01b039081165f9081526001602052838120949094559051608085015160a0860151935191909216926103c891610a17565b5f6040518083038185875af1925050503d805f8114610402576040519150601f19603f3d011682016040523d82523d5f602084013e610407565b606091505b50509050806104585760405162461bcd60e51b815260206004820152601c60248201527f56616c696461746f725365745369673a2063616c6c206661696c656400000000604482015260640161025d565b816060015182604001516001600160a01b03167f5942a9a3968c7d49fc51c027041544ea295f5c1e395d6d8aa35c4369959f8ed960405160405180910390a3505050506104a460015f55565b50565b80517f00000000000000000000000000000000000000000000000000000000000000001461052b5760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f725365745369673a20696e76616c6964207461726765744260448201526a1b1bd8dad8da185a5b925160aa1b606482015260840161025d565b60208101516001600160a01b0316301461059f5760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f725365745369673a20696e76616c69642076616c6964617460448201526e6f725365745369674164647265737360881b606482015260840161025d565b60608101516040808301516001600160a01b03165f90815260016020522054146104a45760405162461bcd60e51b815260206004820152601e60248201527f56616c696461746f725365745369673a20696e76616c6964206e6f6e63650000604482015260640161025d565b60025f540361062d57604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b5f60208284031215610643575f80fd5b813563ffffffff81168114610656575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b03811182821017156106935761069361065d565b60405290565b604051606081016001600160401b03811182821017156106935761069361065d565b604051601f8201601f191681016001600160401b03811182821017156106e3576106e361065d565b604052919050565b6001600160a01b03811681146104a4575f80fd5b803561070a816106eb565b919050565b5f6001600160401b038211156107275761072761065d565b50601f01601f191660200190565b5f82601f830112610744575f80fd5b81356107576107528261070f565b6106bb565b81815284602083860101111561076b575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215610797575f80fd5b81356001600160401b03808211156107ad575f80fd5b9083019060c082860312156107c0575f80fd5b6107c8610671565b823581526107d8602084016106ff565b60208201526107e9604084016106ff565b6040820152606083013560608201526080830135608082015260a083013582811115610813575f80fd5b61081f87828601610735565b60a08301525095945050505050565b5f6020828403121561083e575f80fd5b8135610656816106eb565b5f5b8381101561086357818101518382015260200161084b565b50505f910152565b5f82601f83011261087a575f80fd5b81516108886107528261070f565b81815284602083860101111561089c575f80fd5b6108ad826020830160208701610849565b949350505050565b5f80604083850312156108c6575f80fd5b82516001600160401b03808211156108dc575f80fd5b90840190606082870312156108ef575f80fd5b6108f7610699565b825181526020830151610909816106eb565b602082015260408301518281111561091f575f80fd5b61092b8882860161086b565b60408301525080945050505060208301518015158114610949575f80fd5b809150509250929050565b5f60208284031215610964575f80fd5b81516001600160401b038082111561097a575f80fd5b9083019060c0828603121561098d575f80fd5b610995610671565b8251815260208301516109a7816106eb565b602082015260408301516109ba816106eb565b80604083015250606083015160608201526080830151608082015260a0830151828111156109e6575f80fd5b61081f8782860161086b565b80820180821115610a1157634e487b7160e01b5f52601160045260245ffd5b92915050565b5f8251610a28818460208701610849565b919091019291505056fea164736f6c6343000819000a", } // ValidatorSetSigABI is the input ABI used to generate the binding from. diff --git a/abi-bindings/go/mocks/ExampleERC20/ExampleERC20.go b/abi-bindings/go/mocks/ExampleERC20/ExampleERC20.go index bc7f00d16..1b2b5e53a 100644 --- a/abi-bindings/go/mocks/ExampleERC20/ExampleERC20.go +++ b/abi-bindings/go/mocks/ExampleERC20/ExampleERC20.go @@ -31,8 +31,8 @@ var ( // ExampleERC20MetaData contains all meta data concerning the ExampleERC20 contract. var ExampleERC20MetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burnFrom\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"ERC20InsufficientAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ERC20InsufficientBalance\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidApprover\",\"inputs\":[{\"name\":\"approver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidReceiver\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidSender\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidSpender\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x608060405234801561000f575f80fd5b506040518060400160405280600a81526020016926b7b1b5902a37b5b2b760b11b81525060405180604001604052806004815260200163045584d560e41b815250816003908161005f919061028b565b50600461006c828261028b565b50505061008b336b204fce5e3e2502611000000061009060201b60201c565b61036f565b6001600160a01b0382166100be5760405163ec442f0560e01b81525f60048201526024015b60405180910390fd5b6100c95f83836100cd565b5050565b6001600160a01b0383166100f7578060025f8282546100ec919061034a565b909155506101679050565b6001600160a01b0383165f90815260208190526040902054818110156101495760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016100b5565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610183576002805482900390556101a1565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516101e691815260200190565b60405180910390a3505050565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061021b57607f821691505b60208210810361023957634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561028657805f5260205f20601f840160051c810160208510156102645750805b601f840160051c820191505b81811015610283575f8155600101610270565b50505b505050565b81516001600160401b038111156102a4576102a46101f3565b6102b8816102b28454610207565b8461023f565b602080601f8311600181146102eb575f84156102d45750858301515b5f19600386901b1c1916600185901b178555610342565b5f85815260208120601f198616915b82811015610319578886015182559484019460019091019084016102fa565b508582101561033657878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b8082018082111561036957634e487b7160e01b5f52601160045260245ffd5b92915050565b6108328061037c5f395ff3fe608060405234801561000f575f80fd5b50600436106100b1575f3560e01c806370a082311161006e57806370a082311461013f57806379cc67901461016757806395d89b411461017a578063a0712d6814610182578063a9059cbb14610195578063dd62ed3e146101a8575f80fd5b806306fdde03146100b5578063095ea7b3146100d357806318160ddd146100f657806323b872dd14610108578063313ce5671461011b57806342966c681461012a575b5f80fd5b6100bd6101e0565b6040516100ca919061069e565b60405180910390f35b6100e66100e1366004610705565b610270565b60405190151581526020016100ca565b6002545b6040519081526020016100ca565b6100e661011636600461072d565b610289565b604051601281526020016100ca565b61013d610138366004610766565b6102ac565b005b6100fa61014d36600461077d565b6001600160a01b03165f9081526020819052604090205490565b61013d610175366004610705565b6102b9565b6100bd6102d2565b61013d610190366004610766565b6102e1565b6100e66101a3366004610705565b610347565b6100fa6101b636600461079d565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6060600380546101ef906107ce565b80601f016020809104026020016040519081016040528092919081815260200182805461021b906107ce565b80156102665780601f1061023d57610100808354040283529160200191610266565b820191905f5260205f20905b81548152906001019060200180831161024957829003601f168201915b5050505050905090565b5f3361027d818585610354565b60019150505b92915050565b5f33610296858285610366565b6102a18585856103e1565b506001949350505050565b6102b6338261043e565b50565b6102c4823383610366565b6102ce828261043e565b5050565b6060600480546101ef906107ce565b662386f26fc1000081111561033d5760405162461bcd60e51b815260206004820152601f60248201527f4578616d706c6545524332303a206d6178206d696e742065786365656465640060448201526064015b60405180910390fd5b6102b63382610472565b5f3361027d8185856103e1565b61036183838360016104a6565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f1981146103db57818110156103cd57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610334565b6103db84848484035f6104a6565b50505050565b6001600160a01b03831661040a57604051634b637e8f60e11b81525f6004820152602401610334565b6001600160a01b0382166104335760405163ec442f0560e01b81525f6004820152602401610334565b610361838383610578565b6001600160a01b03821661046757604051634b637e8f60e11b81525f6004820152602401610334565b6102ce825f83610578565b6001600160a01b03821661049b5760405163ec442f0560e01b81525f6004820152602401610334565b6102ce5f8383610578565b6001600160a01b0384166104cf5760405163e602df0560e01b81525f6004820152602401610334565b6001600160a01b0383166104f857604051634a1406b160e11b81525f6004820152602401610334565b6001600160a01b038085165f90815260016020908152604080832093871683529290522082905580156103db57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161056a91815260200190565b60405180910390a350505050565b6001600160a01b0383166105a2578060025f8282546105979190610806565b909155506106129050565b6001600160a01b0383165f90815260208190526040902054818110156105f45760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610334565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661062e5760028054829003905561064c565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161069191815260200190565b60405180910390a3505050565b5f602080835283518060208501525f5b818110156106ca578581018301518582016040015282016106ae565b505f604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114610700575f80fd5b919050565b5f8060408385031215610716575f80fd5b61071f836106ea565b946020939093013593505050565b5f805f6060848603121561073f575f80fd5b610748846106ea565b9250610756602085016106ea565b9150604084013590509250925092565b5f60208284031215610776575f80fd5b5035919050565b5f6020828403121561078d575f80fd5b610796826106ea565b9392505050565b5f80604083850312156107ae575f80fd5b6107b7836106ea565b91506107c5602084016106ea565b90509250929050565b600181811c908216806107e257607f821691505b60208210810361080057634e487b7160e01b5f52602260045260245ffd5b50919050565b8082018082111561028357634e487b7160e01b5f52601160045260245ffdfea164736f6c6343000819000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"burnFrom\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"ERC20InsufficientAllowance\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"allowance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ERC20InsufficientBalance\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"needed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidApprover\",\"inputs\":[{\"name\":\"approver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidReceiver\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidSender\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC20InvalidSpender\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x608060405234801561000f575f80fd5b506040518060400160405280600a81526020016926b7b1b5902a37b5b2b760b11b81525060405180604001604052806004815260200163045584d560e41b815250816003908161005f919061028b565b50600461006c828261028b565b50505061008b336b204fce5e3e2502611000000061009060201b60201c565b61036f565b6001600160a01b0382166100be5760405163ec442f0560e01b81525f60048201526024015b60405180910390fd5b6100c95f83836100cd565b5050565b6001600160a01b0383166100f7578060025f8282546100ec919061034a565b909155506101679050565b6001600160a01b0383165f90815260208190526040902054818110156101495760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016100b5565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610183576002805482900390556101a1565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516101e691815260200190565b60405180910390a3505050565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061021b57607f821691505b60208210810361023957634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561028657805f5260205f20601f840160051c810160208510156102645750805b601f840160051c820191505b81811015610283575f8155600101610270565b50505b505050565b81516001600160401b038111156102a4576102a46101f3565b6102b8816102b28454610207565b8461023f565b602080601f8311600181146102eb575f84156102d45750858301515b5f19600386901b1c1916600185901b178555610342565b5f85815260208120601f198616915b82811015610319578886015182559484019460019091019084016102fa565b508582101561033657878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b8082018082111561036957634e487b7160e01b5f52601160045260245ffd5b92915050565b61088a8061037c5f395ff3fe608060405234801561000f575f80fd5b50600436106100bc575f3560e01c806342966c681161007957806342966c681461014a57806370a082311461015d57806379cc67901461018557806395d89b4114610198578063a0712d68146101a0578063a9059cbb146101b3578063dd62ed3e146101c6575f80fd5b806306fdde03146100c0578063095ea7b3146100de57806318160ddd1461010157806323b872dd14610113578063313ce5671461012657806340c10f1914610135575b5f80fd5b6100c86101d9565b6040516100d5919061068a565b60405180910390f35b6100f16100ec3660046106f1565b610269565b60405190151581526020016100d5565b6002545b6040519081526020016100d5565b6100f1610121366004610719565b610282565b604051601281526020016100d5565b6101486101433660046106f1565b6102a5565b005b610148610158366004610752565b6102e4565b61010561016b366004610769565b6001600160a01b03165f9081526020819052604090205490565b6101486101933660046106f1565b6102f1565b6100c8610306565b6101486101ae366004610752565b610315565b6100f16101c13660046106f1565b610347565b6101056101d4366004610789565b610354565b6060600380546101e8906107ba565b80601f0160208091040260200160405190810160405280929190818152602001828054610214906107ba565b801561025f5780601f106102365761010080835404028352916020019161025f565b820191905f5260205f20905b81548152906001019060200180831161024257829003601f168201915b5050505050905090565b5f3361027681858561037e565b60019150505b92915050565b5f3361028f858285610390565b61029a8585856103e0565b506001949350505050565b678ac7230489e800008111156102d65760405162461bcd60e51b81526004016102cd906107f2565b60405180910390fd5b6102e0828261043d565b5050565b6102ee3382610471565b50565b6102fc823383610390565b6102e08282610471565b6060600480546101e8906107ba565b678ac7230489e8000081111561033d5760405162461bcd60e51b81526004016102cd906107f2565b6102ee338261043d565b5f336102768185856103e0565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b61038b83838360016104a5565b505050565b5f61039b8484610354565b90505f1981146103da57818110156103cc57828183604051637dc7a0d960e11b81526004016102cd93929190610829565b6103da84848484035f6104a5565b50505050565b6001600160a01b038316610409575f604051634b637e8f60e11b81526004016102cd919061084a565b6001600160a01b038216610432575f60405163ec442f0560e01b81526004016102cd919061084a565b61038b838383610577565b6001600160a01b038216610466575f60405163ec442f0560e01b81526004016102cd919061084a565b6102e05f8383610577565b6001600160a01b03821661049a575f604051634b637e8f60e11b81526004016102cd919061084a565b6102e0825f83610577565b6001600160a01b0384166104ce575f60405163e602df0560e01b81526004016102cd919061084a565b6001600160a01b0383166104f7575f604051634a1406b160e11b81526004016102cd919061084a565b6001600160a01b038085165f90815260016020908152604080832093871683529290522082905580156103da57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161056991815260200190565b60405180910390a350505050565b6001600160a01b0383166105a1578060025f828254610596919061085e565b909155506105fe9050565b6001600160a01b0383165f90815260208190526040902054818110156105e05783818360405163391434e360e21b81526004016102cd93929190610829565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661061a57600280548290039055610638565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161067d91815260200190565b60405180910390a3505050565b5f602080835283518060208501525f5b818110156106b65785810183015185820160400152820161069a565b505f604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146106ec575f80fd5b919050565b5f8060408385031215610702575f80fd5b61070b836106d6565b946020939093013593505050565b5f805f6060848603121561072b575f80fd5b610734846106d6565b9250610742602085016106d6565b9150604084013590509250925092565b5f60208284031215610762575f80fd5b5035919050565b5f60208284031215610779575f80fd5b610782826106d6565b9392505050565b5f806040838503121561079a575f80fd5b6107a3836106d6565b91506107b1602084016106d6565b90509250929050565b600181811c908216806107ce57607f821691505b6020821081036107ec57634e487b7160e01b5f52602260045260245ffd5b50919050565b6020808252601f908201527f4578616d706c6545524332303a206d6178206d696e7420657863656564656400604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b8082018082111561027c57634e487b7160e01b5f52601160045260245ffdfea164736f6c6343000819000a", } // ExampleERC20ABI is the input ABI used to generate the binding from. @@ -451,25 +451,46 @@ func (_ExampleERC20 *ExampleERC20TransactorSession) BurnFrom(account common.Addr return _ExampleERC20.Contract.BurnFrom(&_ExampleERC20.TransactOpts, account, value) } -// Mint is a paid mutator transaction binding the contract method 0xa0712d68. +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address account, uint256 amount) returns() +func (_ExampleERC20 *ExampleERC20Transactor) Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) { + return _ExampleERC20.contract.Transact(opts, "mint", account, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address account, uint256 amount) returns() +func (_ExampleERC20 *ExampleERC20Session) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { + return _ExampleERC20.Contract.Mint(&_ExampleERC20.TransactOpts, account, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address account, uint256 amount) returns() +func (_ExampleERC20 *ExampleERC20TransactorSession) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { + return _ExampleERC20.Contract.Mint(&_ExampleERC20.TransactOpts, account, amount) +} + +// Mint0 is a paid mutator transaction binding the contract method 0xa0712d68. // // Solidity: function mint(uint256 amount) returns() -func (_ExampleERC20 *ExampleERC20Transactor) Mint(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) { - return _ExampleERC20.contract.Transact(opts, "mint", amount) +func (_ExampleERC20 *ExampleERC20Transactor) Mint0(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) { + return _ExampleERC20.contract.Transact(opts, "mint0", amount) } -// Mint is a paid mutator transaction binding the contract method 0xa0712d68. +// Mint0 is a paid mutator transaction binding the contract method 0xa0712d68. // // Solidity: function mint(uint256 amount) returns() -func (_ExampleERC20 *ExampleERC20Session) Mint(amount *big.Int) (*types.Transaction, error) { - return _ExampleERC20.Contract.Mint(&_ExampleERC20.TransactOpts, amount) +func (_ExampleERC20 *ExampleERC20Session) Mint0(amount *big.Int) (*types.Transaction, error) { + return _ExampleERC20.Contract.Mint0(&_ExampleERC20.TransactOpts, amount) } -// Mint is a paid mutator transaction binding the contract method 0xa0712d68. +// Mint0 is a paid mutator transaction binding the contract method 0xa0712d68. // // Solidity: function mint(uint256 amount) returns() -func (_ExampleERC20 *ExampleERC20TransactorSession) Mint(amount *big.Int) (*types.Transaction, error) { - return _ExampleERC20.Contract.Mint(&_ExampleERC20.TransactOpts, amount) +func (_ExampleERC20 *ExampleERC20TransactorSession) Mint0(amount *big.Int) (*types.Transaction, error) { + return _ExampleERC20.Contract.Mint0(&_ExampleERC20.TransactOpts, amount) } // Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. diff --git a/abi-bindings/go/teleporter/TeleporterMessenger/TeleporterMessenger.go b/abi-bindings/go/teleporter/TeleporterMessenger/TeleporterMessenger.go index 805c6ddc4..52fdbce12 100644 --- a/abi-bindings/go/teleporter/TeleporterMessenger/TeleporterMessenger.go +++ b/abi-bindings/go/teleporter/TeleporterMessenger/TeleporterMessenger.go @@ -66,7 +66,7 @@ type TeleporterMessageReceipt struct { // TeleporterMessengerMetaData contains all meta data concerning the TeleporterMessenger contract. var TeleporterMessengerMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addFeeAmount\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"additionalFeeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"blockchainID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"calculateMessageID\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"checkRelayerRewardAmount\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeAsset\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFeeInfo\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMessageHash\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNextMessageID\",\"inputs\":[{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getReceiptAtIndex\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTeleporterMessageReceipt\",\"components\":[{\"name\":\"receivedMessageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getReceiptQueueSize\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayerRewardAddress\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initializeBlockchainID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"messageNonce\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"messageReceived\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"receiptQueues\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"first\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"last\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"receiveCrossChainMessage\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"receivedFailedMessageHashes\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"messageHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"redeemRelayerRewards\",\"inputs\":[{\"name\":\"feeAsset\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"retryMessageExecution\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structTeleporterMessage\",\"components\":[{\"name\":\"messageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"receipts\",\"type\":\"tuple[]\",\"internalType\":\"structTeleporterMessageReceipt[]\",\"components\":[{\"name\":\"receivedMessageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"retrySendCrossChainMessage\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structTeleporterMessage\",\"components\":[{\"name\":\"messageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"receipts\",\"type\":\"tuple[]\",\"internalType\":\"structTeleporterMessageReceipt[]\",\"components\":[{\"name\":\"receivedMessageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendCrossChainMessage\",\"inputs\":[{\"name\":\"messageInput\",\"type\":\"tuple\",\"internalType\":\"structTeleporterMessageInput\",\"components\":[{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeInfo\",\"type\":\"tuple\",\"internalType\":\"structTeleporterFeeInfo\",\"components\":[{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendSpecifiedReceipts\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messageIDs\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"feeInfo\",\"type\":\"tuple\",\"internalType\":\"structTeleporterFeeInfo\",\"components\":[{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sentMessageInfo\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"messageHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"feeInfo\",\"type\":\"tuple\",\"internalType\":\"structTeleporterFeeInfo\",\"components\":[{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AddFeeAmount\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"updatedFeeInfo\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structTeleporterFeeInfo\",\"components\":[{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"BlockchainIDInitialized\",\"inputs\":[{\"name\":\"blockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MessageExecuted\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MessageExecutionFailed\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structTeleporterMessage\",\"components\":[{\"name\":\"messageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"receipts\",\"type\":\"tuple[]\",\"internalType\":\"structTeleporterMessageReceipt[]\",\"components\":[{\"name\":\"receivedMessageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ReceiptReceived\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"feeInfo\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structTeleporterFeeInfo\",\"components\":[{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ReceiveCrossChainMessage\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"deliverer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"rewardRedeemer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"message\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structTeleporterMessage\",\"components\":[{\"name\":\"messageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"receipts\",\"type\":\"tuple[]\",\"internalType\":\"structTeleporterMessageReceipt[]\",\"components\":[{\"name\":\"receivedMessageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerRewardsRedeemed\",\"inputs\":[{\"name\":\"redeemer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"asset\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SendCrossChainMessage\",\"inputs\":[{\"name\":\"messageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structTeleporterMessage\",\"components\":[{\"name\":\"messageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"receipts\",\"type\":\"tuple[]\",\"internalType\":\"structTeleporterMessageReceipt[]\",\"components\":[{\"name\":\"receivedMessageNonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"relayerRewardAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"feeInfo\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structTeleporterFeeInfo\",\"components\":[{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"AddressInsufficientBalance\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x6080604052348015600e575f80fd5b5060015f81905580556130e9806100245f395ff3fe608060405234801561000f575f80fd5b5060043610610148575f3560e01c8063a8898181116100bf578063df20e8bc11610079578063df20e8bc14610331578063e69d606a14610344578063e6e67bd5146103ab578063ebc3b1ba146103e6578063ecc7042814610409578063fc2d619714610412575f80fd5b8063a8898181146102a9578063a9a85614146102bc578063b771b3bc146102cf578063c473eef8146102dd578063ccb5f80914610315578063d127dc9b14610328575f80fd5b8063399b77da11610110578063399b77da1461021257806362448850146102315780638245a1b014610244578063860a3b0614610257578063892bf412146102765780638ac0fd0414610296575f80fd5b80630af5b4ff1461014c57806322296c3a146101675780632bc8b0bf1461017c5780632ca40f551461018f5780632e27c223146101e7575b5f80fd5b610154610425565b6040519081526020015b60405180910390f35b61017a610175366004612111565b6104f3565b005b61015461018a36600461212c565b6105e6565b6101d961019d36600461212c565b600560209081525f9182526040918290208054835180850190945260018201546001600160a01b03168452600290910154918301919091529082565b60405161015e929190612143565b6101fa6101f536600461212c565b610602565b6040516001600160a01b03909116815260200161015e565b61015461022036600461212c565b5f9081526005602052604090205490565b61015461023f36600461216a565b610689565b61017a6102523660046121b7565b6106e2565b61015461026536600461212c565b60066020525f908152604090205481565b6102896102843660046121e8565b610885565b60405161015e9190612208565b61017a6102a4366004612228565b6108b6565b6101546102b736600461225d565b610aed565b6101546102ca3660046122cd565b610b2f565b6101fa6005600160991b0181565b6101546102eb36600461235e565b6001600160a01b039182165f90815260096020908152604080832093909416825291909152205490565b61017a610323366004612395565b610dc1565b61015460025481565b61015461033f36600461212c565b6111e3565b61038c61035236600461212c565b5f90815260056020908152604091829020825180840190935260018101546001600160a01b03168084526002909101549290910182905291565b604080516001600160a01b03909316835260208301919091520161015e565b6103d16103b936600461212c565b60046020525f90815260409020805460019091015482565b6040805192835260208301919091520161015e565b6103f96103f436600461212c565b61122a565b604051901515815260200161015e565b61015460035481565b61017a6104203660046123b9565b61123f565b6002545f90806104ee576005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061049691906123fc565b9050806104be5760405162461bcd60e51b81526004016104b590612413565b60405180910390fd5b600281905560405181907f1eac640109dc937d2a9f42735a05f794b39a5e3759d681951d671aabbce4b104905f90a25b919050565b335f9081526009602090815260408083206001600160a01b0385168452909152902054806105745760405162461bcd60e51b815260206004820152602860248201527f54656c65706f727465724d657373656e6765723a206e6f2072657761726420746044820152676f2072656465656d60c01b60648201526084016104b5565b335f8181526009602090815260408083206001600160a01b03871680855290835281842093909355518481529192917f3294c84e5b0f29d9803655319087207bc94f4db29f7927846944822773780b88910160405180910390a36105e26001600160a01b0383163383611494565b5050565b5f8181526004602052604081206105fc906114f8565b92915050565b5f8181526007602052604081205461066e5760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a206d657373616765206e6f74604482015268081c9958d95a5d995960ba1b60648201526084016104b5565b505f908152600860205260409020546001600160a01b031690565b5f60015f54146106ab5760405162461bcd60e51b81526004016104b59061245a565b60025f556106d86106bb83612691565b83355f9081526004602052604090206106d39061150a565b611604565b60015f5592915050565b60015f54146107035760405162461bcd60e51b81526004016104b59061245a565b60025f818155905461071b9060408401358435610aed565b5f818152600560209081526040918290208251808401845281548152835180850190945260018201546001600160a01b0316845260029091015483830152908101919091528051919250906107825760405162461bcd60e51b81526004016104b590612730565b5f8360405160200161079491906129af565b60408051601f19818403018152919052825181516020830120919250146107cd5760405162461bcd60e51b81526004016104b5906129c1565b8360400135837f2a211ad4a59ab9d003852404f9c57c690704ee755f3c79d2c2812ad32da99df8868560200151604051610808929190612a0a565b60405180910390a360405163ee5b48eb60e01b81526005600160991b019063ee5b48eb9061083a908490600401612a8b565b6020604051808303815f875af1158015610856573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087a91906123fc565b505060015f55505050565b604080518082019091525f80825260208201525f8381526004602052604090206108af9083611837565b9392505050565b60015f54146108d75760405162461bcd60e51b81526004016104b59061245a565b60025f5560018054146108fc5760405162461bcd60e51b81526004016104b590612a9d565b6002600155806109665760405162461bcd60e51b815260206004820152602f60248201527f54656c65706f727465724d657373656e6765723a207a65726f2061646469746960448201526e1bdb985b0819995948185b5bdd5b9d608a1b60648201526084016104b5565b6001600160a01b03821661098c5760405162461bcd60e51b81526004016104b590612ae2565b5f838152600560205260409020546109b65760405162461bcd60e51b81526004016104b590612730565b5f838152600560205260409020600101546001600160a01b03838116911614610a475760405162461bcd60e51b815260206004820152603760248201527f54656c65706f727465724d657373656e6765723a20696e76616c69642066656560448201527f20617373657420636f6e7472616374206164647265737300000000000000000060648201526084016104b5565b5f610a5283836118f8565b5f85815260056020526040812060020180549293508392909190610a77908490612b4a565b90915550505f8481526005602052604090819020905185917fc1bfd1f1208927dfbd414041dcb5256e6c9ad90dd61aec3249facbd34ff7b3e191610ad8916001019081546001600160a01b0316815260019190910154602082015260400190565b60405180910390a2505060018080555f555050565b6040805130602082015290810184905260608101839052608081018290525f9060a0016040516020818303038152906040528051906020012090509392505050565b5f60015f5414610b515760405162461bcd60e51b81526004016104b59061245a565b60025f818155905490866001600160401b03811115610b7257610b7261249d565b604051908082528060200260200182016040528015610bb657816020015b604080518082019091525f8082526020820152815260200190600190039081610b905790505b509050865f5b81811015610d2e575f8a8a83818110610bd757610bd7612b5d565b9050602002013590505f60075f8381526020019081526020015f20549050805f03610c535760405162461bcd60e51b815260206004820152602660248201527f54656c65706f727465724d657373656e6765723a2072656365697074206e6f7460448201526508199bdd5b9960d21b60648201526084016104b5565b610c5e8d8783610aed565b8214610cd25760405162461bcd60e51b815260206004820152603a60248201527f54656c65706f727465724d657373656e6765723a206d6573736167652049442060448201527f6e6f742066726f6d20736f7572636520626c6f636b636861696e00000000000060648201526084016104b5565b5f828152600860209081526040918290205482518084019093528383526001600160a01b03169082018190528651909190879086908110610d1557610d15612b5d565b6020026020010181905250505050806001019050610bbc565b506040805160c0810182528b81525f6020820152610daf918101610d57368b90038b018b612b71565b81526020015f81526020018888808060200260200160405190810160405280939291908181526020018383602002808284375f9201829052509385525050604080519283526020808401909152909201525083611604565b60015f559a9950505050505050505050565b6001805414610de25760405162461bcd60e51b81526004016104b590612a9d565b60026001556040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa158015610e30573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e579190810190612be7565b9150915080610eba5760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a20696e76616c69642077617260448201526870206d65737361676560b81b60648201526084016104b5565b60208201516001600160a01b03163014610f315760405162461bcd60e51b815260206004820152603260248201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b60648201526084016104b5565b5f8260400151806020019051810190610f4a9190612d7b565b90505f610f55610425565b905080826040015114610fc45760405162461bcd60e51b815260206004820152603160248201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206465736044820152701d1a5b985d1a5bdb8818da185a5b881251607a1b60648201526084016104b5565b835182515f91610fd5918490610aed565b5f81815260076020526040902054909150156110495760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f727465724d657373656e6765723a206d65737361676520616c7260448201526c1958591e481c9958d95a5d9959609a1b60648201526084016104b5565b611057338460a00151611a5a565b6110b55760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a20756e617574686f72697a6560448201526832103932b630bcb2b960b91b60648201526084016104b5565b6110c281845f0151611ac6565b6001600160a01b038616156110f8575f81815260086020526040902080546001600160a01b0319166001600160a01b0388161790555b60c0830151515f5b8181101561113b5761113384885f01518760c00151848151811061112657611126612b5d565b6020026020010151611b36565b600101611100565b50604080518082018252855181526001600160a01b03891660208083019190915288515f90815260049091529190912061117491611c5a565b336001600160a01b0316865f0151837f292ee90bbaf70b5d4936025e09d56ba08f3e421156b6a568cf3c2840d9343e348a886040516111b4929190612f81565b60405180910390a460e084015151156111d5576111d582875f015186611cb4565b505060018055505050505050565b6002545f90806112055760405162461bcd60e51b81526004016104b590612413565b5f60035460016112159190612b4a565b9050611222828583610aed565b949350505050565b5f8181526007602052604081205415156105fc565b60018054146112605760405162461bcd60e51b81526004016104b590612a9d565b60026001819055545f906112779084908435610aed565b5f81815260066020526040902054909150806112a55760405162461bcd60e51b81526004016104b590612730565b80836040516020016112b791906129af565b60405160208183030381529060405280519060200120146112ea5760405162461bcd60e51b81526004016104b5906129c1565b5f6112fb6080850160608601612111565b6001600160a01b03163b1161136f5760405162461bcd60e51b815260206004820152603460248201527f54656c65706f727465724d657373656e6765723a2064657374696e6174696f6e604482015273206164647265737320686173206e6f20636f646560601b60648201526084016104b5565b604051849083907f34795cc6b122b9a0ae684946319f1e14a577b4e8f9b3dda9ac94c21a54d3188c905f90a35f82815260066020908152604080832083905586916113be918701908701612111565b6113cb60e0870187612fa4565b6040516024016113de9493929190612fe6565b60408051601f198184030181529190526020810180516001600160e01b031663643477d560e11b17905290505f61142561141e6080870160608801612111565b5a84611de3565b9050806114885760405162461bcd60e51b815260206004820152602b60248201527f54656c65706f727465724d657373656e6765723a20726574727920657865637560448201526a1d1a5bdb8819985a5b195960aa1b60648201526084016104b5565b50506001805550505050565b6040516001600160a01b038381166024830152604482018390526114f391859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611dfa565b505050565b805460018201545f916105fc91613010565b60605f611520600561151b856114f8565b611e5b565b9050805f0361156c57604080515f8082526020820190925290611564565b604080518082019091525f808252602082015281526020019060019003908161153e5790505b509392505050565b5f816001600160401b038111156115855761158561249d565b6040519080825280602002602001820160405280156115c957816020015b604080518082019091525f80825260208201528152602001906001900390816115a35790505b5090505f5b82811015611564576115df85611e70565b8282815181106115f1576115f1612b5d565b60209081029190910101526001016115ce565b5f8061160e610425565b90505f60035f815461161f90613023565b91905081905590505f61163683875f015184610aed565b90505f604051806101000160405280848152602001336001600160a01b03168152602001885f0151815260200188602001516001600160a01b0316815260200188606001518152602001886080015181526020018781526020018860a0015181525090505f816040516020016116ac919061303b565b60405160208183030381529060405290505f808960400151602001511115611713576040890151516001600160a01b03166116f95760405162461bcd60e51b81526004016104b590612ae2565b6040890151805160209091015161171091906118f8565b90505b6040805180820182528a820151516001600160a01b03908116825260208083018590528351808501855286518783012081528082018481525f8a815260058452869020915182555180516001830180546001600160a01b03191691909516179093559101516002909101558a51915190919086907f2a211ad4a59ab9d003852404f9c57c690704ee755f3c79d2c2812ad32da99df8906117b6908890869061304d565b60405180910390a360405163ee5b48eb60e01b81526005600160991b019063ee5b48eb906117e8908690600401612a8b565b6020604051808303815f875af1158015611804573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061182891906123fc565b50939998505050505050505050565b604080518082019091525f8082526020820152611853836114f8565b82106118ab5760405162461bcd60e51b815260206004820152602160248201527f5265636569707451756575653a20696e646578206f7574206f6620626f756e646044820152607360f81b60648201526084016104b5565b826002015f83855f01546118bf9190612b4a565b815260208082019290925260409081015f20815180830190925280548252600101546001600160a01b0316918101919091529392505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038516906370a0823190602401602060405180830381865afa15801561193e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196291906123fc565b90506119796001600160a01b038516333086611f3a565b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa1580156119bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119e191906123fc565b9050818111611a475760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b60648201526084016104b5565b611a518282613010565b95945050505050565b5f81515f03611a6b575060016105fc565b81515f5b81811015611abc57846001600160a01b0316848281518110611a9357611a93612b5d565b60200260200101516001600160a01b031603611ab4576001925050506105fc565b600101611a6f565b505f949350505050565b805f03611b255760405162461bcd60e51b815260206004820152602760248201527f54656c65706f727465724d657373656e6765723a207a65726f206d657373616760448201526665206e6f6e636560c81b60648201526084016104b5565b5f9182526007602052604090912055565b5f611b458484845f0151610aed565b5f818152600560209081526040918290208251808401845281548152835180850190945260018201546001600160a01b031684526002909101548383015290810191909152805191925090611b9b575050505050565b5f8281526005602090815260408083208381556001810180546001600160a01b03191690556002018390558382018051830151878401516001600160a01b0390811686526009855283862092515116855292528220805491929091611c01908490612b4a565b9250508190555082602001516001600160a01b031684837fd13a7935f29af029349bed0a2097455b91fd06190a30478c575db3f31e00bf578460200151604051611c4b919061305f565b60405180910390a45050505050565b600182018054829160028501915f9182611c7383613023565b9091555081526020808201929092526040015f2082518155910151600190910180546001600160a01b0319166001600160a01b039092169190911790555050565b80608001515a1015611d165760405162461bcd60e51b815260206004820152602560248201527f54656c65706f727465724d657373656e6765723a20696e73756666696369656e604482015264742067617360d81b60648201526084016104b5565b80606001516001600160a01b03163b5f03611d36576114f3838383611f79565b602081015160e08201516040515f92611d5392869260240161307f565b60408051601f198184030181529190526020810180516001600160e01b031663643477d560e11b179052606083015160808401519192505f91611d97919084611de3565b905080611db057611da9858585611f79565b5050505050565b604051849086907f34795cc6b122b9a0ae684946319f1e14a577b4e8f9b3dda9ac94c21a54d3188c905f90a35050505050565b5f805f808451602086015f8989f195945050505050565b5f611e0e6001600160a01b03841683611fed565b905080515f14158015611e32575080806020019051810190611e3091906130a8565b155b156114f357604051635274afe760e01b81526001600160a01b03841660048201526024016104b5565b5f818310611e6957816108af565b5090919050565b604080518082019091525f808252602082015281546001830154819003611ed95760405162461bcd60e51b815260206004820152601960248201527f5265636569707451756575653a20656d7074792071756575650000000000000060448201526064016104b5565b5f8181526002840160208181526040808420815180830190925280548252600180820180546001600160a01b03811685870152888852959094529490556001600160a01b0319909216905590611f30908390612b4a565b9093555090919050565b6040516001600160a01b038481166024830152838116604483015260648201839052611f739186918216906323b872dd906084016114c1565b50505050565b80604051602001611f8a919061303b565b60408051601f1981840301815282825280516020918201205f878152600690925291902055829084907f4619adc1017b82e02eaefac01a43d50d6d8de4460774bc370c3ff0210d40c98590611fe090859061303b565b60405180910390a3505050565b60606108af83835f845f80856001600160a01b0316848660405161201191906130c1565b5f6040518083038185875af1925050503d805f811461204b576040519150601f19603f3d011682016040523d82523d5f602084013e612050565b606091505b509150915061206086838361206a565b9695505050505050565b60608261207f5761207a826120c6565b6108af565b815115801561209657506001600160a01b0384163b155b156120bf57604051639996b31560e01b81526001600160a01b03851660048201526024016104b5565b50806108af565b8051156120d65780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146120ef575f80fd5b80356104ee816120f2565b5f60208284031215612121575f80fd5b81356108af816120f2565b5f6020828403121561213c575f80fd5b5035919050565b828152606081016108af602083018480516001600160a01b03168252602090810151910152565b5f6020828403121561217a575f80fd5b81356001600160401b0381111561218f575f80fd5b820160e081850312156108af575f80fd5b5f61010082840312156121b1575f80fd5b50919050565b5f602082840312156121c7575f80fd5b81356001600160401b038111156121dc575f80fd5b611222848285016121a0565b5f80604083850312156121f9575f80fd5b50508035926020909101359150565b815181526020808301516001600160a01b031690820152604081016105fc565b5f805f6060848603121561223a575f80fd5b83359250602084013561224c816120f2565b929592945050506040919091013590565b5f805f6060848603121561226f575f80fd5b505081359360208301359350604090920135919050565b5f8083601f840112612296575f80fd5b5081356001600160401b038111156122ac575f80fd5b6020830191508360208260051b85010111156122c6575f80fd5b9250929050565b5f805f805f8086880360a08112156122e3575f80fd5b8735965060208801356001600160401b0380821115612300575f80fd5b61230c8b838c01612286565b90985096508691506040603f1984011215612325575f80fd5b60408a01955060808a013592508083111561233e575f80fd5b505061234c89828a01612286565b979a9699509497509295939492505050565b5f806040838503121561236f575f80fd5b823561237a816120f2565b9150602083013561238a816120f2565b809150509250929050565b5f80604083850312156123a6575f80fd5b823563ffffffff8116811461237a575f80fd5b5f80604083850312156123ca575f80fd5b8235915060208301356001600160401b038111156123e6575f80fd5b6123f2858286016121a0565b9150509250929050565b5f6020828403121561240c575f80fd5b5051919050565b60208082526027908201527f54656c65706f727465724d657373656e6765723a207a65726f20626c6f636b636040820152661a185a5b88125160ca1b606082015260800190565b60208082526023908201527f5265656e7472616e63794775617264733a2073656e646572207265656e7472616040820152626e637960e81b606082015260800190565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156124d3576124d361249d565b60405290565b60405160c081016001600160401b03811182821017156124d3576124d361249d565b60405161010081016001600160401b03811182821017156124d3576124d361249d565b604051601f8201601f191681016001600160401b03811182821017156125465761254661249d565b604052919050565b5f6040828403121561255e575f80fd5b6125666124b1565b90508135612573816120f2565b808252506020820135602082015292915050565b5f6001600160401b0382111561259f5761259f61249d565b5060051b60200190565b5f82601f8301126125b8575f80fd5b813560206125cd6125c883612587565b61251e565b8083825260208201915060208460051b8701019350868411156125ee575f80fd5b602086015b84811015612613578035612606816120f2565b83529183019183016125f3565b509695505050505050565b5f6001600160401b038211156126365761263661249d565b50601f01601f191660200190565b5f82601f830112612653575f80fd5b81356126616125c88261261e565b818152846020838601011115612675575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60e082360312156126a1575f80fd5b6126a96124d9565b823581526126b960208401612106565b60208201526126cb366040850161254e565b60408201526080830135606082015260a08301356001600160401b03808211156126f3575f80fd5b6126ff368387016125a9565b608084015260c0850135915080821115612717575f80fd5b5061272436828601612644565b60a08301525092915050565b60208082526026908201527f54656c65706f727465724d657373656e6765723a206d657373616765206e6f7460408201526508199bdd5b9960d21b606082015260800190565b5f808335601e1984360301811261278b575f80fd5b83016020810192503590506001600160401b038111156127a9575f80fd5b8060051b36038213156122c6575f80fd5b8183525f60208085019450825f5b858110156127f65781356127db816120f2565b6001600160a01b0316875295820195908201906001016127c8565b509495945050505050565b5f808335601e19843603018112612816575f80fd5b83016020810192503590506001600160401b03811115612834575f80fd5b8060061b36038213156122c6575f80fd5b8183525f60208085019450825f5b858110156127f657813587528282013561286c816120f2565b6001600160a01b0316878401526040968701969190910190600101612853565b5f808335601e198436030181126128a1575f80fd5b83016020810192503590506001600160401b038111156128bf575f80fd5b8036038213156122c6575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f61010082358452602083013561290b816120f2565b6001600160a01b031660208501526040838101359085015261292f60608401612106565b6001600160a01b031660608501526080838101359085015261295460a0840184612776565b8260a087015261296783870182846127ba565b9250505061297860c0840184612801565b85830360c087015261298b838284612845565b9250505061299c60e084018461288c565b85830360e08701526120608382846128cd565b602081525f6108af60208301846128f5565b60208082526029908201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206d65736040820152680e6c2ceca40d0c2e6d60bb1b606082015260800190565b606081525f612a1c60608301856128f5565b90506108af602083018480516001600160a01b03168252602090810151910152565b5f5b83811015612a58578181015183820152602001612a40565b50505f910152565b5f8151808452612a77816020860160208601612a3e565b601f01601f19169290920160200192915050565b602081525f6108af6020830184612a60565b60208082526025908201527f5265656e7472616e63794775617264733a207265636569766572207265656e7460408201526472616e637960d81b606082015260800190565b60208082526034908201527f54656c65706f727465724d657373656e6765723a207a65726f2066656520617360408201527373657420636f6e7472616374206164647265737360601b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156105fc576105fc612b36565b634e487b7160e01b5f52603260045260245ffd5b5f60408284031215612b81575f80fd5b6108af838361254e565b80516104ee816120f2565b5f82601f830112612ba5575f80fd5b8151612bb36125c88261261e565b818152846020838601011115612bc7575f80fd5b611222826020830160208701612a3e565b805180151581146104ee575f80fd5b5f8060408385031215612bf8575f80fd5b82516001600160401b0380821115612c0e575f80fd5b9084019060608287031215612c21575f80fd5b604051606081018181108382111715612c3c57612c3c61249d565b604052825181526020830151612c51816120f2565b6020820152604083015182811115612c67575f80fd5b612c7388828601612b96565b6040830152509350612c8a91505060208401612bd8565b90509250929050565b5f82601f830112612ca2575f80fd5b81516020612cb26125c883612587565b8083825260208201915060208460051b870101935086841115612cd3575f80fd5b602086015b84811015612613578051612ceb816120f2565b8352918301918301612cd8565b5f82601f830112612d07575f80fd5b81516020612d176125c883612587565b82815260069290921b84018101918181019086841115612d35575f80fd5b8286015b848110156126135760408189031215612d50575f80fd5b612d586124b1565b8151815284820151612d69816120f2565b81860152835291830191604001612d39565b5f60208284031215612d8b575f80fd5b81516001600160401b0380821115612da1575f80fd5b908301906101008286031215612db5575f80fd5b612dbd6124fb565b82518152612dcd60208401612b8b565b602082015260408301516040820152612de860608401612b8b565b60608201526080830151608082015260a083015182811115612e08575f80fd5b612e1487828601612c93565b60a08301525060c083015182811115612e2b575f80fd5b612e3787828601612cf8565b60c08301525060e083015182811115612e4e575f80fd5b612e5a87828601612b96565b60e08301525095945050505050565b5f815180845260208085019450602084015f5b838110156127f65781516001600160a01b031687529582019590820190600101612e7c565b5f815180845260208085019450602084015f5b838110156127f657612eda878351805182526020908101516001600160a01b0316910152565b6040969096019590820190600101612eb4565b5f6101008251845260018060a01b036020840151166020850152604083015160408501526060830151612f2b60608601826001600160a01b03169052565b506080830151608085015260a08301518160a0860152612f4d82860182612e69565b91505060c083015184820360c0860152612f678282612ea1565b91505060e083015184820360e0860152611a518282612a60565b6001600160a01b03831681526040602082018190525f9061122290830184612eed565b5f808335601e19843603018112612fb9575f80fd5b8301803591506001600160401b03821115612fd2575f80fd5b6020019150368190038213156122c6575f80fd5b8481526001600160a01b03841660208201526060604082018190525f9061206090830184866128cd565b818103818111156105fc576105fc612b36565b5f6001820161303457613034612b36565b5060010190565b602081525f6108af6020830184612eed565b606081525f612a1c6060830185612eed565b81516001600160a01b0316815260208083015190820152604081016105fc565b8381526001600160a01b03831660208201526060604082018190525f90611a5190830184612a60565b5f602082840312156130b8575f80fd5b6108af82612bd8565b5f82516130d2818460208701612a3e565b919091019291505056fea164736f6c6343000819000a", + Bin: "0x6080604052348015600e575f80fd5b5060015f81905580556130be806100245f395ff3fe608060405234801561000f575f80fd5b5060043610610148575f3560e01c8063a8898181116100bf578063df20e8bc11610079578063df20e8bc14610326578063e69d606a14610339578063e6e67bd5146103a0578063ebc3b1ba146103db578063ecc70428146103fe578063fc2d619714610407575f80fd5b8063a88981811461029e578063a9a85614146102b1578063b771b3bc146102c4578063c473eef8146102d2578063ccb5f8091461030a578063d127dc9b1461031d575f80fd5b8063399b77da11610110578063399b77da1461020757806362448850146102265780638245a1b014610239578063860a3b061461024c578063892bf4121461026b5780638ac0fd041461028b575f80fd5b80630af5b4ff1461014c57806322296c3a146101675780632bc8b0bf1461017c5780632ca40f551461018f5780632e27c223146101e7575b5f80fd5b61015461041a565b6040519081526020015b60405180910390f35b61017a6101753660046120f2565b6104e8565b005b61015461018a36600461210d565b6105db565b6101d961019d36600461210d565b600560209081525f9182526040918290208054835180850190945260018201546001600160a01b03168452600290910154918301919091529082565b60405161015e92919061213c565b6101fa6101f536600461210d565b6105f7565b60405161015e9190612150565b61015461021536600461210d565b5f9081526005602052604090205490565b610154610234366004612164565b61067e565b61017a6102473660046121b1565b6106d7565b61015461025a36600461210d565b60066020525f908152604090205481565b61027e6102793660046121e2565b61087a565b60405161015e9190612202565b61017a610299366004612222565b6108ab565b6101546102ac366004612257565b610adc565b6101546102bf3660046122c7565b610b1e565b6101fa6005600160991b0181565b6101546102e0366004612358565b6001600160a01b039182165f90815260096020908152604080832093909416825291909152205490565b61017a61031836600461238f565b610db0565b61015460025481565b61015461033436600461210d565b6111d2565b61038161034736600461210d565b5f90815260056020908152604091829020825180840190935260018101546001600160a01b03168084526002909101549290910182905291565b604080516001600160a01b03909316835260208301919091520161015e565b6103c66103ae36600461210d565b60046020525f90815260409020805460019091015482565b6040805192835260208301919091520161015e565b6103ee6103e936600461210d565b611219565b604051901515815260200161015e565b61015460035481565b61017a6104153660046123b3565b61122e565b6002545f90806104e3576005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610467573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061048b91906123f6565b9050806104b35760405162461bcd60e51b81526004016104aa9061240d565b60405180910390fd5b600281905560405181907f1eac640109dc937d2a9f42735a05f794b39a5e3759d681951d671aabbce4b104905f90a25b919050565b335f9081526009602090815260408083206001600160a01b0385168452909152902054806105695760405162461bcd60e51b815260206004820152602860248201527f54656c65706f727465724d657373656e6765723a206e6f2072657761726420746044820152676f2072656465656d60c01b60648201526084016104aa565b335f8181526009602090815260408083206001600160a01b03871680855290835281842093909355518481529192917f3294c84e5b0f29d9803655319087207bc94f4db29f7927846944822773780b88910160405180910390a36105d76001600160a01b0383163383611483565b5050565b5f8181526004602052604081206105f1906114e7565b92915050565b5f818152600760205260408120546106635760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a206d657373616765206e6f74604482015268081c9958d95a5d995960ba1b60648201526084016104aa565b505f908152600860205260409020546001600160a01b031690565b5f60015f54146106a05760405162461bcd60e51b81526004016104aa90612454565b60025f556106cd6106b08361268b565b83355f9081526004602052604090206106c8906114f9565b6115f3565b60015f5592915050565b60015f54146106f85760405162461bcd60e51b81526004016104aa90612454565b60025f81815590546107109060408401358435610adc565b5f818152600560209081526040918290208251808401845281548152835180850190945260018201546001600160a01b0316845260029091015483830152908101919091528051919250906107775760405162461bcd60e51b81526004016104aa9061272a565b5f8360405160200161078991906129a9565b60408051601f19818403018152919052825181516020830120919250146107c25760405162461bcd60e51b81526004016104aa906129bb565b8360400135837f2a211ad4a59ab9d003852404f9c57c690704ee755f3c79d2c2812ad32da99df88685602001516040516107fd929190612a04565b60405180910390a360405163ee5b48eb60e01b81526005600160991b019063ee5b48eb9061082f908490600401612a72565b6020604051808303815f875af115801561084b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061086f91906123f6565b505060015f55505050565b604080518082019091525f80825260208201525f8381526004602052604090206108a49083611826565b9392505050565b60015f54146108cc5760405162461bcd60e51b81526004016104aa90612454565b60025f5560018054146108f15760405162461bcd60e51b81526004016104aa90612a84565b60026001558061095b5760405162461bcd60e51b815260206004820152602f60248201527f54656c65706f727465724d657373656e6765723a207a65726f2061646469746960448201526e1bdb985b0819995948185b5bdd5b9d608a1b60648201526084016104aa565b6001600160a01b0382166109815760405162461bcd60e51b81526004016104aa90612ac9565b5f838152600560205260409020546109ab5760405162461bcd60e51b81526004016104aa9061272a565b5f838152600560205260409020600101546001600160a01b03838116911614610a365760405162461bcd60e51b815260206004820152603760248201527f54656c65706f727465724d657373656e6765723a20696e76616c69642066656560448201527620617373657420636f6e7472616374206164647265737360481b60648201526084016104aa565b5f610a4183836118e7565b5f85815260056020526040812060020180549293508392909190610a66908490612b31565b90915550505f8481526005602052604090819020905185917fc1bfd1f1208927dfbd414041dcb5256e6c9ad90dd61aec3249facbd34ff7b3e191610ac7916001019081546001600160a01b0316815260019190910154602082015260400190565b60405180910390a2505060018080555f555050565b6040805130602082015290810184905260608101839052608081018290525f9060a0016040516020818303038152906040528051906020012090509392505050565b5f60015f5414610b405760405162461bcd60e51b81526004016104aa90612454565b60025f818155905490866001600160401b03811115610b6157610b61612497565b604051908082528060200260200182016040528015610ba557816020015b604080518082019091525f8082526020820152815260200190600190039081610b7f5790505b509050865f5b81811015610d1d575f8a8a83818110610bc657610bc6612b44565b9050602002013590505f60075f8381526020019081526020015f20549050805f03610c425760405162461bcd60e51b815260206004820152602660248201527f54656c65706f727465724d657373656e6765723a2072656365697074206e6f7460448201526508199bdd5b9960d21b60648201526084016104aa565b610c4d8d8783610adc565b8214610cc15760405162461bcd60e51b815260206004820152603a60248201527f54656c65706f727465724d657373656e6765723a206d6573736167652049442060448201527f6e6f742066726f6d20736f7572636520626c6f636b636861696e00000000000060648201526084016104aa565b5f828152600860209081526040918290205482518084019093528383526001600160a01b03169082018190528651909190879086908110610d0457610d04612b44565b6020026020010181905250505050806001019050610bab565b506040805160c0810182528b81525f6020820152610d9e918101610d46368b90038b018b612b58565b81526020015f81526020018888808060200260200160405190810160405280939291908181526020018383602002808284375f92018290525093855250506040805192835260208084019091529092015250836115f3565b60015f559a9950505050505050505050565b6001805414610dd15760405162461bcd60e51b81526004016104aa90612a84565b60026001556040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa158015610e1f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e469190810190612bce565b9150915080610ea95760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a20696e76616c69642077617260448201526870206d65737361676560b81b60648201526084016104aa565b60208201516001600160a01b03163014610f205760405162461bcd60e51b815260206004820152603260248201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b60648201526084016104aa565b5f8260400151806020019051810190610f399190612d62565b90505f610f4461041a565b905080826040015114610fb35760405162461bcd60e51b815260206004820152603160248201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206465736044820152701d1a5b985d1a5bdb8818da185a5b881251607a1b60648201526084016104aa565b835182515f91610fc4918490610adc565b5f81815260076020526040902054909150156110385760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f727465724d657373656e6765723a206d65737361676520616c7260448201526c1958591e481c9958d95a5d9959609a1b60648201526084016104aa565b611046338460a00151611a51565b6110a45760405162461bcd60e51b815260206004820152602960248201527f54656c65706f727465724d657373656e6765723a20756e617574686f72697a6560448201526832103932b630bcb2b960b91b60648201526084016104aa565b6110b181845f0151611abd565b6001600160a01b038616156110e7575f81815260086020526040902080546001600160a01b0319166001600160a01b0388161790555b60c0830151515f5b8181101561112a5761112284885f01518760c00151848151811061111557611115612b44565b6020026020010151611b2d565b6001016110ef565b50604080518082018252855181526001600160a01b03891660208083019190915288515f90815260049091529190912061116391611c51565b336001600160a01b0316865f0151837f292ee90bbaf70b5d4936025e09d56ba08f3e421156b6a568cf3c2840d9343e348a886040516111a3929190612f68565b60405180910390a460e084015151156111c4576111c482875f015186611cab565b505060018055505050505050565b6002545f90806111f45760405162461bcd60e51b81526004016104aa9061240d565b5f60035460016112049190612b31565b9050611211828583610adc565b949350505050565b5f8181526007602052604081205415156105f1565b600180541461124f5760405162461bcd60e51b81526004016104aa90612a84565b60026001819055545f906112669084908435610adc565b5f81815260066020526040902054909150806112945760405162461bcd60e51b81526004016104aa9061272a565b80836040516020016112a691906129a9565b60405160208183030381529060405280519060200120146112d95760405162461bcd60e51b81526004016104aa906129bb565b5f6112ea60808501606086016120f2565b6001600160a01b03163b1161135e5760405162461bcd60e51b815260206004820152603460248201527f54656c65706f727465724d657373656e6765723a2064657374696e6174696f6e604482015273206164647265737320686173206e6f20636f646560601b60648201526084016104aa565b604051849083907f34795cc6b122b9a0ae684946319f1e14a577b4e8f9b3dda9ac94c21a54d3188c905f90a35f82815260066020908152604080832083905586916113ad9187019087016120f2565b6113ba60e0870187612f8b565b6040516024016113cd9493929190612fcd565b60408051601f198184030181529190526020810180516001600160e01b031663643477d560e11b17905290505f61141461140d60808701606088016120f2565b5a84611dda565b9050806114775760405162461bcd60e51b815260206004820152602b60248201527f54656c65706f727465724d657373656e6765723a20726574727920657865637560448201526a1d1a5bdb8819985a5b195960aa1b60648201526084016104aa565b50506001805550505050565b6040516001600160a01b038381166024830152604482018390526114e291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611df1565b505050565b805460018201545f916105f191612ff7565b60605f61150f600561150a856114e7565b611e49565b9050805f0361155b57604080515f8082526020820190925290611553565b604080518082019091525f808252602082015281526020019060019003908161152d5790505b509392505050565b5f816001600160401b0381111561157457611574612497565b6040519080825280602002602001820160405280156115b857816020015b604080518082019091525f80825260208201528152602001906001900390816115925790505b5090505f5b82811015611553576115ce85611e5e565b8282815181106115e0576115e0612b44565b60209081029190910101526001016115bd565b5f806115fd61041a565b90505f60035f815461160e9061300a565b91905081905590505f61162583875f015184610adc565b90505f604051806101000160405280848152602001336001600160a01b03168152602001885f0151815260200188602001516001600160a01b0316815260200188606001518152602001886080015181526020018781526020018860a0015181525090505f8160405160200161169b9190613022565b60405160208183030381529060405290505f808960400151602001511115611702576040890151516001600160a01b03166116e85760405162461bcd60e51b81526004016104aa90612ac9565b604089015180516020909101516116ff91906118e7565b90505b6040805180820182528a820151516001600160a01b03908116825260208083018590528351808501855286518783012081528082018481525f8a815260058452869020915182555180516001830180546001600160a01b03191691909516179093559101516002909101558a51915190919086907f2a211ad4a59ab9d003852404f9c57c690704ee755f3c79d2c2812ad32da99df8906117a59088908690613034565b60405180910390a360405163ee5b48eb60e01b81526005600160991b019063ee5b48eb906117d7908690600401612a72565b6020604051808303815f875af11580156117f3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061181791906123f6565b50939998505050505050505050565b604080518082019091525f8082526020820152611842836114e7565b821061189a5760405162461bcd60e51b815260206004820152602160248201527f5265636569707451756575653a20696e646578206f7574206f6620626f756e646044820152607360f81b60648201526084016104aa565b826002015f83855f01546118ae9190612b31565b815260208082019290925260409081015f20815180830190925280548252600101546001600160a01b0316918101919091529392505050565b5f80836001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016119159190612150565b602060405180830381865afa158015611930573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195491906123f6565b905061196b6001600160a01b038516333086611f24565b6040516370a0823160e01b81525f906001600160a01b038616906370a0823190611999903090600401612150565b602060405180830381865afa1580156119b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119d891906123f6565b9050818111611a3e5760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b60648201526084016104aa565b611a488282612ff7565b95945050505050565b5f81515f03611a62575060016105f1565b81515f5b81811015611ab357846001600160a01b0316848281518110611a8a57611a8a612b44565b60200260200101516001600160a01b031603611aab576001925050506105f1565b600101611a66565b505f949350505050565b805f03611b1c5760405162461bcd60e51b815260206004820152602760248201527f54656c65706f727465724d657373656e6765723a207a65726f206d657373616760448201526665206e6f6e636560c81b60648201526084016104aa565b5f9182526007602052604090912055565b5f611b3c8484845f0151610adc565b5f818152600560209081526040918290208251808401845281548152835180850190945260018201546001600160a01b031684526002909101548383015290810191909152805191925090611b92575050505050565b5f8281526005602090815260408083208381556001810180546001600160a01b03191690556002018390558382018051830151878401516001600160a01b0390811686526009855283862092515116855292528220805491929091611bf8908490612b31565b9250508190555082602001516001600160a01b031684837fd13a7935f29af029349bed0a2097455b91fd06190a30478c575db3f31e00bf578460200151604051611c429190613046565b60405180910390a45050505050565b600182018054829160028501915f9182611c6a8361300a565b9091555081526020808201929092526040015f2082518155910151600190910180546001600160a01b0319166001600160a01b039092169190911790555050565b80608001515a1015611d0d5760405162461bcd60e51b815260206004820152602560248201527f54656c65706f727465724d657373656e6765723a20696e73756666696369656e604482015264742067617360d81b60648201526084016104aa565b80606001516001600160a01b03163b5f03611d2d576114e2838383611f63565b602081015160e08201516040515f92611d4a928692602401613054565b60408051601f198184030181529190526020810180516001600160e01b031663643477d560e11b179052606083015160808401519192505f91611d8e919084611dda565b905080611da757611da0858585611f63565b5050505050565b604051849086907f34795cc6b122b9a0ae684946319f1e14a577b4e8f9b3dda9ac94c21a54d3188c905f90a35050505050565b5f805f808451602086015f8989f195945050505050565b5f611e056001600160a01b03841683611fd7565b905080515f14158015611e29575080806020019051810190611e27919061307d565b155b156114e25782604051635274afe760e01b81526004016104aa9190612150565b5f818310611e5757816108a4565b5090919050565b604080518082019091525f808252602082015281546001830154819003611ec35760405162461bcd60e51b81526020600482015260196024820152785265636569707451756575653a20656d70747920717565756560381b60448201526064016104aa565b5f8181526002840160208181526040808420815180830190925280548252600180820180546001600160a01b03811685870152888852959094529490556001600160a01b0319909216905590611f1a908390612b31565b9093555090919050565b6040516001600160a01b038481166024830152838116604483015260648201839052611f5d9186918216906323b872dd906084016114b0565b50505050565b80604051602001611f749190613022565b60408051601f1981840301815282825280516020918201205f878152600690925291902055829084907f4619adc1017b82e02eaefac01a43d50d6d8de4460774bc370c3ff0210d40c98590611fca908590613022565b60405180910390a3505050565b60606108a483835f845f80856001600160a01b03168486604051611ffb9190613096565b5f6040518083038185875af1925050503d805f8114612035576040519150601f19603f3d011682016040523d82523d5f602084013e61203a565b606091505b509150915061204a868383612054565b9695505050505050565b60608261206957612064826120a7565b6108a4565b815115801561208057506001600160a01b0384163b155b156120a05783604051639996b31560e01b81526004016104aa9190612150565b50806108a4565b8051156120b75780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146120d0575f80fd5b80356104e3816120d3565b5f60208284031215612102575f80fd5b81356108a4816120d3565b5f6020828403121561211d575f80fd5b5035919050565b80516001600160a01b03168252602090810151910152565b828152606081016108a46020830184612124565b6001600160a01b0391909116815260200190565b5f60208284031215612174575f80fd5b81356001600160401b03811115612189575f80fd5b820160e081850312156108a4575f80fd5b5f61010082840312156121ab575f80fd5b50919050565b5f602082840312156121c1575f80fd5b81356001600160401b038111156121d6575f80fd5b6112118482850161219a565b5f80604083850312156121f3575f80fd5b50508035926020909101359150565b815181526020808301516001600160a01b031690820152604081016105f1565b5f805f60608486031215612234575f80fd5b833592506020840135612246816120d3565b929592945050506040919091013590565b5f805f60608486031215612269575f80fd5b505081359360208301359350604090920135919050565b5f8083601f840112612290575f80fd5b5081356001600160401b038111156122a6575f80fd5b6020830191508360208260051b85010111156122c0575f80fd5b9250929050565b5f805f805f8086880360a08112156122dd575f80fd5b8735965060208801356001600160401b03808211156122fa575f80fd5b6123068b838c01612280565b90985096508691506040603f198401121561231f575f80fd5b60408a01955060808a0135925080831115612338575f80fd5b505061234689828a01612280565b979a9699509497509295939492505050565b5f8060408385031215612369575f80fd5b8235612374816120d3565b91506020830135612384816120d3565b809150509250929050565b5f80604083850312156123a0575f80fd5b823563ffffffff81168114612374575f80fd5b5f80604083850312156123c4575f80fd5b8235915060208301356001600160401b038111156123e0575f80fd5b6123ec8582860161219a565b9150509250929050565b5f60208284031215612406575f80fd5b5051919050565b60208082526027908201527f54656c65706f727465724d657373656e6765723a207a65726f20626c6f636b636040820152661a185a5b88125160ca1b606082015260800190565b60208082526023908201527f5265656e7472616e63794775617264733a2073656e646572207265656e7472616040820152626e637960e81b606082015260800190565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156124cd576124cd612497565b60405290565b60405160c081016001600160401b03811182821017156124cd576124cd612497565b60405161010081016001600160401b03811182821017156124cd576124cd612497565b604051601f8201601f191681016001600160401b038111828210171561254057612540612497565b604052919050565b5f60408284031215612558575f80fd5b6125606124ab565b9050813561256d816120d3565b808252506020820135602082015292915050565b5f6001600160401b0382111561259957612599612497565b5060051b60200190565b5f82601f8301126125b2575f80fd5b813560206125c76125c283612581565b612518565b8083825260208201915060208460051b8701019350868411156125e8575f80fd5b602086015b8481101561260d578035612600816120d3565b83529183019183016125ed565b509695505050505050565b5f6001600160401b0382111561263057612630612497565b50601f01601f191660200190565b5f82601f83011261264d575f80fd5b813561265b6125c282612618565b81815284602083860101111561266f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60e0823603121561269b575f80fd5b6126a36124d3565b823581526126b3602084016120e7565b60208201526126c53660408501612548565b60408201526080830135606082015260a08301356001600160401b03808211156126ed575f80fd5b6126f9368387016125a3565b608084015260c0850135915080821115612711575f80fd5b5061271e3682860161263e565b60a08301525092915050565b60208082526026908201527f54656c65706f727465724d657373656e6765723a206d657373616765206e6f7460408201526508199bdd5b9960d21b606082015260800190565b5f808335601e19843603018112612785575f80fd5b83016020810192503590506001600160401b038111156127a3575f80fd5b8060051b36038213156122c0575f80fd5b8183525f60208085019450825f5b858110156127f05781356127d5816120d3565b6001600160a01b0316875295820195908201906001016127c2565b509495945050505050565b5f808335601e19843603018112612810575f80fd5b83016020810192503590506001600160401b0381111561282e575f80fd5b8060061b36038213156122c0575f80fd5b8183525f60208085019450825f5b858110156127f0578135875282820135612866816120d3565b6001600160a01b031687840152604096870196919091019060010161284d565b5f808335601e1984360301811261289b575f80fd5b83016020810192503590506001600160401b038111156128b9575f80fd5b8036038213156122c0575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f610100823584526020830135612905816120d3565b6001600160a01b0316602085015260408381013590850152612929606084016120e7565b6001600160a01b031660608501526080838101359085015261294e60a0840184612770565b8260a087015261296183870182846127b4565b9250505061297260c08401846127fb565b85830360c087015261298583828461283f565b9250505061299660e0840184612886565b85830360e087015261204a8382846128c7565b602081525f6108a460208301846128ef565b60208082526029908201527f54656c65706f727465724d657373656e6765723a20696e76616c6964206d65736040820152680e6c2ceca40d0c2e6d60bb1b606082015260800190565b606081525f612a1660608301856128ef565b90506108a46020830184612124565b5f5b83811015612a3f578181015183820152602001612a27565b50505f910152565b5f8151808452612a5e816020860160208601612a25565b601f01601f19169290920160200192915050565b602081525f6108a46020830184612a47565b60208082526025908201527f5265656e7472616e63794775617264733a207265636569766572207265656e7460408201526472616e637960d81b606082015260800190565b60208082526034908201527f54656c65706f727465724d657373656e6765723a207a65726f2066656520617360408201527373657420636f6e7472616374206164647265737360601b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156105f1576105f1612b1d565b634e487b7160e01b5f52603260045260245ffd5b5f60408284031215612b68575f80fd5b6108a48383612548565b80516104e3816120d3565b5f82601f830112612b8c575f80fd5b8151612b9a6125c282612618565b818152846020838601011115612bae575f80fd5b611211826020830160208701612a25565b805180151581146104e3575f80fd5b5f8060408385031215612bdf575f80fd5b82516001600160401b0380821115612bf5575f80fd5b9084019060608287031215612c08575f80fd5b604051606081018181108382111715612c2357612c23612497565b604052825181526020830151612c38816120d3565b6020820152604083015182811115612c4e575f80fd5b612c5a88828601612b7d565b6040830152509350612c7191505060208401612bbf565b90509250929050565b5f82601f830112612c89575f80fd5b81516020612c996125c283612581565b8083825260208201915060208460051b870101935086841115612cba575f80fd5b602086015b8481101561260d578051612cd2816120d3565b8352918301918301612cbf565b5f82601f830112612cee575f80fd5b81516020612cfe6125c283612581565b82815260069290921b84018101918181019086841115612d1c575f80fd5b8286015b8481101561260d5760408189031215612d37575f80fd5b612d3f6124ab565b8151815284820151612d50816120d3565b81860152835291830191604001612d20565b5f60208284031215612d72575f80fd5b81516001600160401b0380821115612d88575f80fd5b908301906101008286031215612d9c575f80fd5b612da46124f5565b82518152612db460208401612b72565b602082015260408301516040820152612dcf60608401612b72565b60608201526080830151608082015260a083015182811115612def575f80fd5b612dfb87828601612c7a565b60a08301525060c083015182811115612e12575f80fd5b612e1e87828601612cdf565b60c08301525060e083015182811115612e35575f80fd5b612e4187828601612b7d565b60e08301525095945050505050565b5f815180845260208085019450602084015f5b838110156127f05781516001600160a01b031687529582019590820190600101612e63565b5f815180845260208085019450602084015f5b838110156127f057612ec1878351805182526020908101516001600160a01b0316910152565b6040969096019590820190600101612e9b565b5f6101008251845260018060a01b036020840151166020850152604083015160408501526060830151612f1260608601826001600160a01b03169052565b506080830151608085015260a08301518160a0860152612f3482860182612e50565b91505060c083015184820360c0860152612f4e8282612e88565b91505060e083015184820360e0860152611a488282612a47565b6001600160a01b03831681526040602082018190525f9061121190830184612ed4565b5f808335601e19843603018112612fa0575f80fd5b8301803591506001600160401b03821115612fb9575f80fd5b6020019150368190038213156122c0575f80fd5b8481526001600160a01b03841660208201526060604082018190525f9061204a90830184866128c7565b818103818111156105f1576105f1612b1d565b5f6001820161301b5761301b612b1d565b5060010190565b602081525f6108a46020830184612ed4565b606081525f612a166060830185612ed4565b604081016105f18284612124565b8381526001600160a01b03831660208201526060604082018190525f90611a4890830184612a47565b5f6020828403121561308d575f80fd5b6108a482612bbf565b5f82516130a7818460208701612a25565b919091019291505056fea164736f6c6343000819000a", } // TeleporterMessengerABI is the input ABI used to generate the binding from. diff --git a/abi-bindings/go/teleporter/registry/TeleporterRegistry/TeleporterRegistry.go b/abi-bindings/go/teleporter/registry/TeleporterRegistry/TeleporterRegistry.go index 866500d7f..6171b011a 100644 --- a/abi-bindings/go/teleporter/registry/TeleporterRegistry/TeleporterRegistry.go +++ b/abi-bindings/go/teleporter/registry/TeleporterRegistry/TeleporterRegistry.go @@ -38,7 +38,7 @@ type ProtocolRegistryEntry struct { // TeleporterRegistryMetaData contains all meta data concerning the TeleporterRegistry contract. var TeleporterRegistryMetaData = &bind.MetaData{ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"initialEntries\",\"type\":\"tuple[]\",\"internalType\":\"structProtocolRegistryEntry[]\",\"components\":[{\"name\":\"version\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"protocolAddress\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"MAX_VERSION_INCREMENT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VALIDATORS_SOURCE_ADDRESS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addProtocolVersion\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"blockchainID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAddressFromVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getLatestTeleporter\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractITeleporterMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTeleporterFromVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractITeleporterMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVersionFromAddress\",\"inputs\":[{\"name\":\"protocolAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AddProtocolVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"protocolAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"LatestVersionUpdated\",\"inputs\":[{\"name\":\"oldVersion\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"newVersion\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false}]", - Bin: "0x60a060405234801561000f575f80fd5b50604051610fb7380380610fb783398101604081905261002e916103e2565b7302000000000000000000000000000000000000056001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561007e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a291906104bc565b60805280515f5b818110156100e1576100d98382815181106100c6576100c66104d3565b60200260200101516100e960201b60201c565b6001016100a9565b50505061050c565b80515f0361013e5760405162461bcd60e51b815260206004820181905260248201527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e60448201526064015b60405180910390fd5b80515f908152600160205260409020546001600160a01b0316156101b75760405162461bcd60e51b815260206004820152602a60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20616c72656044820152696164792065786973747360b01b6064820152608401610135565b60208101516001600160a01b03166102235760405162461bcd60e51b815260206004820152602960248201527f54656c65706f7274657252656769737472793a207a65726f2070726f746f636f6044820152686c206164647265737360b81b6064820152608401610135565b5f546102316101f4826104e7565b825111156102985760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20696e637260448201526d0cadacadce840e8dede40d0d2ced60931b6064820152608401610135565b6020828101805184515f90815260018452604080822080546001600160a01b0319166001600160a01b03948516179055925190911681526002909252902054825111156102ff5781516020808401516001600160a01b03165f908152600290915260409020555b602082015182516040516001600160a01b03909216917fa5eed93d951a9603d5f7c0a57de79a299dd3dbd5e51429be209d8053a42ab43a905f90a381518110156103725781515f81815560405183917f30623e953733f6474dabdfbef1103ce15ab73cdc77c6dfad0f9874d167e8a9b091a35b5050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156103ac576103ac610376565b60405290565b604051601f8201601f191681016001600160401b03811182821017156103da576103da610376565b604052919050565b5f60208083850312156103f3575f80fd5b82516001600160401b0380821115610409575f80fd5b818501915085601f83011261041c575f80fd5b81518181111561042e5761042e610376565b61043c848260051b016103b2565b818152848101925060069190911b83018401908782111561045b575f80fd5b928401925b818410156104b15760408489031215610477575f80fd5b61047f61038a565b84518152858501516001600160a01b038116811461049b575f80fd5b8187015283526040939093019291840191610460565b979650505050505050565b5f602082840312156104cc575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b8082018082111561050657634e487b7160e01b5f52601160045260245ffd5b92915050565b608051610a8c61052b5f395f818161014301526102580152610a8c5ff3fe608060405234801561000f575f80fd5b506004361061009b575f3560e01c8063ac473ac311610063578063ac473ac31461011f578063b771b3bc14610128578063c07f47d414610136578063d127dc9b1461013e578063d820e64f14610165575f80fd5b80630731775d1461009f578063215abce9146100c357806341f34ed9146100d657806346f9ef49146100eb5780634c1f08ce146100fe575b5f80fd5b6100a65f81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a66100d13660046107aa565b61016d565b6100e96100e43660046107c1565b61017d565b005b6100a66100f93660046107aa565b6103ec565b61011161010c366004610802565b6104ae565b6040519081526020016100ba565b6101116101f481565b6100a66005600160991b0181565b6101115f5481565b6101117f000000000000000000000000000000000000000000000000000000000000000081565b6100a6610554565b5f610177826103ec565b92915050565b6040516306f8253560e41b815263ffffffff821660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156101c6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526101ed919081019061089f565b91509150806102545760405162461bcd60e51b815260206004820152602860248201527f54656c65706f7274657252656769737472793a20696e76616c69642077617270604482015267206d65737361676560c01b60648201526084015b60405180910390fd5b81517f0000000000000000000000000000000000000000000000000000000000000000146102d85760405162461bcd60e51b815260206004820152602b60248201527f54656c65706f7274657252656769737472793a20696e76616c696420736f757260448201526a18d94818da185a5b88125160aa1b606482015260840161024b565b60208201516001600160a01b03161561034d5760405162461bcd60e51b815260206004820152603160248201527f54656c65706f7274657252656769737472793a20696e76616c6964206f726967604482015270696e2073656e646572206164647265737360781b606482015260840161024b565b5f808360400151806020019051810190610367919061099e565b90925090506001600160a01b03811630146103dc5760405162461bcd60e51b815260206004820152602f60248201527f54656c65706f7274657252656769737472793a20696e76616c6964206465737460448201526e696e6174696f6e206164647265737360881b606482015260840161024b565b6103e582610564565b5050505050565b5f815f0361043c5760405162461bcd60e51b815260206004820181905260248201527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e604482015260640161024b565b5f828152600160205260409020546001600160a01b0316806101775760405162461bcd60e51b815260206004820152602560248201527f54656c65706f7274657252656769737472793a2076657273696f6e206e6f7420604482015264199bdd5b9960da1b606482015260840161024b565b5f6001600160a01b0382166104d55760405162461bcd60e51b815260040161024b90610a17565b6001600160a01b0382165f90815260026020526040812054908190036101775760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2070726f746f636f6c2061646460448201526d1c995cdcc81b9bdd08199bdd5b9960921b606482015260840161024b565b5f61055f5f546103ec565b905090565b80515f036105b45760405162461bcd60e51b815260206004820181905260248201527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e604482015260640161024b565b80515f908152600160205260409020546001600160a01b03161561062d5760405162461bcd60e51b815260206004820152602a60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20616c72656044820152696164792065786973747360b01b606482015260840161024b565b60208101516001600160a01b03166106575760405162461bcd60e51b815260040161024b90610a17565b5f546106656101f482610a60565b825111156106cc5760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20696e637260448201526d0cadacadce840e8dede40d0d2ced60931b606482015260840161024b565b6020828101805184515f90815260018452604080822080546001600160a01b0319166001600160a01b03948516179055925190911681526002909252902054825111156107335781516020808401516001600160a01b03165f908152600290915260409020555b602082015182516040516001600160a01b03909216917fa5eed93d951a9603d5f7c0a57de79a299dd3dbd5e51429be209d8053a42ab43a905f90a381518110156107a65781515f81815560405183917f30623e953733f6474dabdfbef1103ce15ab73cdc77c6dfad0f9874d167e8a9b091a35b5050565b5f602082840312156107ba575f80fd5b5035919050565b5f602082840312156107d1575f80fd5b813563ffffffff811681146107e4575f80fd5b9392505050565b6001600160a01b03811681146107ff575f80fd5b50565b5f60208284031215610812575f80fd5b81356107e4816107eb565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156108545761085461081d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156108835761088361081d565b604052919050565b8051801515811461089a575f80fd5b919050565b5f80604083850312156108b0575f80fd5b825167ffffffffffffffff808211156108c7575f80fd5b90840190606082870312156108da575f80fd5b6108e2610831565b825181526020808401516108f5816107eb565b8282015260408401518381111561090a575f80fd5b80850194505087601f85011261091e575f80fd5b8351838111156109305761093061081d565b610942601f8201601f1916830161085a565b93508084528882828701011115610957575f80fd5b5f5b81811015610974578581018301518582018401528201610959565b505f8282860101525082604083015281955061099181880161088b565b9450505050509250929050565b5f8082840360608112156109b0575f80fd5b60408112156109bd575f80fd5b506040516040810181811067ffffffffffffffff821117156109e1576109e161081d565b6040528351815260208401516109f6816107eb565b60208201526040840151909250610a0c816107eb565b809150509250929050565b60208082526029908201527f54656c65706f7274657252656769737472793a207a65726f2070726f746f636f6040820152686c206164647265737360b81b606082015260800190565b8082018082111561017757634e487b7160e01b5f52601160045260245ffdfea164736f6c6343000819000a", + Bin: "0x60a060405234801561000f575f80fd5b50604051610f8c380380610f8c83398101604081905261002e916103e2565b7302000000000000000000000000000000000000056001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561007e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a291906104bc565b60805280515f5b818110156100e1576100d98382815181106100c6576100c66104d3565b60200260200101516100e960201b60201c565b6001016100a9565b50505061050c565b80515f0361013e5760405162461bcd60e51b815260206004820181905260248201527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e60448201526064015b60405180910390fd5b80515f908152600160205260409020546001600160a01b0316156101b75760405162461bcd60e51b815260206004820152602a60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20616c72656044820152696164792065786973747360b01b6064820152608401610135565b60208101516001600160a01b03166102235760405162461bcd60e51b815260206004820152602960248201527f54656c65706f7274657252656769737472793a207a65726f2070726f746f636f6044820152686c206164647265737360b81b6064820152608401610135565b5f546102316101f4826104e7565b825111156102985760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20696e637260448201526d0cadacadce840e8dede40d0d2ced60931b6064820152608401610135565b6020828101805184515f90815260018452604080822080546001600160a01b0319166001600160a01b03948516179055925190911681526002909252902054825111156102ff5781516020808401516001600160a01b03165f908152600290915260409020555b602082015182516040516001600160a01b03909216917fa5eed93d951a9603d5f7c0a57de79a299dd3dbd5e51429be209d8053a42ab43a905f90a381518110156103725781515f81815560405183917f30623e953733f6474dabdfbef1103ce15ab73cdc77c6dfad0f9874d167e8a9b091a35b5050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156103ac576103ac610376565b60405290565b604051601f8201601f191681016001600160401b03811182821017156103da576103da610376565b604052919050565b5f60208083850312156103f3575f80fd5b82516001600160401b0380821115610409575f80fd5b818501915085601f83011261041c575f80fd5b81518181111561042e5761042e610376565b61043c848260051b016103b2565b818152848101925060069190911b83018401908782111561045b575f80fd5b928401925b818410156104b15760408489031215610477575f80fd5b61047f61038a565b84518152858501516001600160a01b038116811461049b575f80fd5b8187015283526040939093019291840191610460565b979650505050505050565b5f602082840312156104cc575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b8082018082111561050657634e487b7160e01b5f52601160045260245ffd5b92915050565b608051610a6161052b5f395f818161014301526102580152610a615ff3fe608060405234801561000f575f80fd5b506004361061009b575f3560e01c8063ac473ac311610063578063ac473ac31461011f578063b771b3bc14610128578063c07f47d414610136578063d127dc9b1461013e578063d820e64f14610165575f80fd5b80630731775d1461009f578063215abce9146100c357806341f34ed9146100d657806346f9ef49146100eb5780634c1f08ce146100fe575b5f80fd5b6100a65f81565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a66100d136600461074a565b61016d565b6100e96100e4366004610761565b61017d565b005b6100a66100f936600461074a565b6103ec565b61011161010c3660046107a2565b61047e565b6040519081526020016100ba565b6101116101f481565b6100a66005600160991b0181565b6101115f5481565b6101117f000000000000000000000000000000000000000000000000000000000000000081565b6100a6610524565b5f610177826103ec565b92915050565b6040516306f8253560e41b815263ffffffff821660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156101c6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526101ed919081019061083f565b91509150806102545760405162461bcd60e51b815260206004820152602860248201527f54656c65706f7274657252656769737472793a20696e76616c69642077617270604482015267206d65737361676560c01b60648201526084015b60405180910390fd5b81517f0000000000000000000000000000000000000000000000000000000000000000146102d85760405162461bcd60e51b815260206004820152602b60248201527f54656c65706f7274657252656769737472793a20696e76616c696420736f757260448201526a18d94818da185a5b88125160aa1b606482015260840161024b565b60208201516001600160a01b03161561034d5760405162461bcd60e51b815260206004820152603160248201527f54656c65706f7274657252656769737472793a20696e76616c6964206f726967604482015270696e2073656e646572206164647265737360781b606482015260840161024b565b5f808360400151806020019051810190610367919061093e565b90925090506001600160a01b03811630146103dc5760405162461bcd60e51b815260206004820152602f60248201527f54656c65706f7274657252656769737472793a20696e76616c6964206465737460448201526e696e6174696f6e206164647265737360881b606482015260840161024b565b6103e582610534565b5050505050565b5f815f0361040c5760405162461bcd60e51b815260040161024b906109b7565b5f828152600160205260409020546001600160a01b0316806101775760405162461bcd60e51b815260206004820152602560248201527f54656c65706f7274657252656769737472793a2076657273696f6e206e6f7420604482015264199bdd5b9960da1b606482015260840161024b565b5f6001600160a01b0382166104a55760405162461bcd60e51b815260040161024b906109ec565b6001600160a01b0382165f90815260026020526040812054908190036101775760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2070726f746f636f6c2061646460448201526d1c995cdcc81b9bdd08199bdd5b9960921b606482015260840161024b565b5f61052f5f546103ec565b905090565b80515f036105545760405162461bcd60e51b815260040161024b906109b7565b80515f908152600160205260409020546001600160a01b0316156105cd5760405162461bcd60e51b815260206004820152602a60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20616c72656044820152696164792065786973747360b01b606482015260840161024b565b60208101516001600160a01b03166105f75760405162461bcd60e51b815260040161024b906109ec565b5f546106056101f482610a35565b8251111561066c5760405162461bcd60e51b815260206004820152602e60248201527f54656c65706f7274657252656769737472793a2076657273696f6e20696e637260448201526d0cadacadce840e8dede40d0d2ced60931b606482015260840161024b565b6020828101805184515f90815260018452604080822080546001600160a01b0319166001600160a01b03948516179055925190911681526002909252902054825111156106d35781516020808401516001600160a01b03165f908152600290915260409020555b602082015182516040516001600160a01b03909216917fa5eed93d951a9603d5f7c0a57de79a299dd3dbd5e51429be209d8053a42ab43a905f90a381518110156107465781515f81815560405183917f30623e953733f6474dabdfbef1103ce15ab73cdc77c6dfad0f9874d167e8a9b091a35b5050565b5f6020828403121561075a575f80fd5b5035919050565b5f60208284031215610771575f80fd5b813563ffffffff81168114610784575f80fd5b9392505050565b6001600160a01b038116811461079f575f80fd5b50565b5f602082840312156107b2575f80fd5b81356107848161078b565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156107f4576107f46107bd565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610823576108236107bd565b604052919050565b8051801515811461083a575f80fd5b919050565b5f8060408385031215610850575f80fd5b825167ffffffffffffffff80821115610867575f80fd5b908401906060828703121561087a575f80fd5b6108826107d1565b825181526020808401516108958161078b565b828201526040840151838111156108aa575f80fd5b80850194505087601f8501126108be575f80fd5b8351838111156108d0576108d06107bd565b6108e2601f8201601f191683016107fa565b935080845288828287010111156108f7575f80fd5b5f5b818110156109145785810183015185820184015282016108f9565b505f8282860101525082604083015281955061093181880161082b565b9450505050509250929050565b5f808284036060811215610950575f80fd5b604081121561095d575f80fd5b506040516040810181811067ffffffffffffffff82111715610981576109816107bd565b6040528351815260208401516109968161078b565b602082015260408401519092506109ac8161078b565b809150509250929050565b6020808252818101527f54656c65706f7274657252656769737472793a207a65726f2076657273696f6e604082015260600190565b60208082526029908201527f54656c65706f7274657252656769737472793a207a65726f2070726f746f636f6040820152686c206164647265737360b81b606082015260800190565b8082018082111561017757634e487b7160e01b5f52601160045260245ffdfea164736f6c6343000819000a", } // TeleporterRegistryABI is the input ABI used to generate the binding from. diff --git a/abi-bindings/go/teleporter/tests/TestMessenger/TestMessenger.go b/abi-bindings/go/teleporter/tests/TestMessenger/TestMessenger.go index 71e916360..9c7aca910 100644 --- a/abi-bindings/go/teleporter/tests/TestMessenger/TestMessenger.go +++ b/abi-bindings/go/teleporter/tests/TestMessenger/TestMessenger.go @@ -32,7 +32,7 @@ var ( // TestMessengerMetaData contains all meta data concerning the TestMessenger contract. var TestMessengerMetaData = &bind.MetaData{ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"teleporterRegistryAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"teleporterManager\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"minTeleporterVersion\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"TELEPORTER_REGISTRY_APP_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentMessage\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getMinTeleporterVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isTeleporterAddressPaused\",\"inputs\":[{\"name\":\"teleporterAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"pauseTeleporterAddress\",\"inputs\":[{\"name\":\"teleporterAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"receiveTeleporterMessage\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendMessage\",\"inputs\":[{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"message\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unpauseTeleporterAddress\",\"inputs\":[{\"name\":\"teleporterAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateMinTeleporterVersion\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MinTeleporterVersionUpdated\",\"inputs\":[{\"name\":\"oldMinTeleporterVersion\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"newMinTeleporterVersion\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ReceiveMessage\",\"inputs\":[{\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"originSenderAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"message\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SendMessage\",\"inputs\":[{\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"destinationAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"feeTokenAddress\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"feeAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"requiredGasLimit\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"message\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TeleporterAddressPaused\",\"inputs\":[{\"name\":\"teleporterAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TeleporterAddressUnpaused\",\"inputs\":[{\"name\":\"teleporterAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"AddressInsufficientBalance\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x608060405234801561000f575f80fd5b50604051611ff6380380611ff683398101604081905261002e9161062e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff1615906001600160401b03165f811580156100775750825b90505f826001600160401b031660011480156100925750303b155b9050811580156100a0575080155b156100be5760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b031916600117855583156100ec57845460ff60401b1916680100000000000000001785555b6100f4610152565b6100ff888888610164565b831561014557845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505061067e565b61015a610184565b6101626101d2565b565b61016c610184565b6101768382610200565b61017f82610226565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661016257604051631afcd79f60e31b815260040160405180910390fd5b6101da610184565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b610208610184565b610210610152565b61021861023a565b6102228282610242565b5050565b61022e610184565b610237816103d1565b50565b610162610184565b61024a610184565b6001600160a01b0382166102cb5760405162461bcd60e51b815260206004820152603760248201527f54656c65706f7274657252656769737472794170703a207a65726f2054656c6560448201527f706f72746572207265676973747279206164647265737300000000000000000060648201526084015b60405180910390fd5b5f7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d0090505f8390505f816001600160a01b031663c07f47d46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610330573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103549190610667565b116103a95760405162461bcd60e51b815260206004820152603260248201525f80516020611fd6833981519152604482015271656c65706f7274657220726567697374727960701b60648201526084016102c2565b81546001600160a01b0319166001600160a01b0382161782556103cb8361040b565b50505050565b6103d9610184565b6001600160a01b03811661040257604051631e4fbdf760e01b81525f60048201526024016102c2565b610237816105a3565b7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d0080546040805163301fd1f560e21b815290515f926001600160a01b03169163c07f47d49160048083019260209291908290030181865afa158015610472573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104969190610667565b6002830154909150818411156104f55760405162461bcd60e51b815260206004820152603160248201525f80516020611fd683398151915260448201527032b632b837b93a32b9103b32b939b4b7b760791b60648201526084016102c2565b80841161056a5760405162461bcd60e51b815260206004820152603f60248201527f54656c65706f7274657252656769737472794170703a206e6f7420677265617460448201527f6572207468616e2063757272656e74206d696e696d756d2076657273696f6e0060648201526084016102c2565b60028301849055604051849082907fa9a7ef57e41f05b4c15480842f5f0c27edfcbb553fed281f7c4068452cc1c02d905f90a350505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b80516001600160a01b0381168114610629575f80fd5b919050565b5f805f60608486031215610640575f80fd5b61064984610613565b925061065760208501610613565b9150604084015190509250925092565b5f60208284031215610677575f80fd5b5051919050565b61194b8061068b5f395ff3fe608060405234801561000f575f80fd5b50600436106100b1575f3560e01c8063973142971161006e5780639731429714610159578063b33fead41461017c578063c868efaa1461019d578063d2cc7a70146101b0578063f2fde38b146101d7578063f63d09d7146101ea575f80fd5b80632b0d8f18146100b55780634511243e146100ca5780635eb99514146100dd578063715018a6146100f05780638da5cb5b146100f8578063909a6ac014610137575b5f80fd5b6100c86100c3366004611335565b6101fd565b005b6100c86100d8366004611335565b6102ff565b6100c86100eb366004611350565b6103ee565b6100c8610402565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020015b60405180910390f35b61014b5f8051602061191f83398151915281565b60405190815260200161012e565b61016c610167366004611335565b610415565b604051901515815260200161012e565b61018f61018a366004611350565b610435565b60405161012e9291906113b4565b6100c86101ab366004611424565b610507565b7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d025461014b565b6100c86101e5366004611335565b6106e5565b61014b6101f836600461147c565b61071f565b5f8051602061191f83398151915261021361087b565b6001600160a01b0382166102425760405162461bcd60e51b8152600401610239906114fc565b60405180910390fd5b61024c8183610883565b156102af5760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f7274657252656769737472794170703a2061646472657373206160448201526c1b1c9958591e481c185d5cd959609a1b6064820152608401610239565b6001600160a01b0382165f81815260018381016020526040808320805460ff1916909217909155517f933f93e57a222e6330362af8b376d0a8725b6901e9a2fb86d00f169702b28a4c9190a25050565b5f8051602061191f83398151915261031561087b565b6001600160a01b03821661033b5760405162461bcd60e51b8152600401610239906114fc565b6103458183610883565b6103a35760405162461bcd60e51b815260206004820152602960248201527f54656c65706f7274657252656769737472794170703a2061646472657373206e6044820152681bdd081c185d5cd95960ba1b6064820152608401610239565b6001600160a01b0382165f818152600183016020526040808220805460ff19169055517f844e2f3154214672229235858fd029d1dfd543901c6d05931f0bc2480a2d72c39190a25050565b6103f661087b565b6103ff816108a7565b50565b61040a610a3f565b6104135f610a9a565b565b5f5f8051602061191f83398151915261042e8184610883565b9392505050565b5f81815260208181526040808320815180830190925280546001600160a01b0316825260018101805460609486949392908401916104729061154a565b80601f016020809104026020016040519081016040528092919081815260200182805461049e9061154a565b80156104e95780601f106104c0576101008083540402835291602001916104e9565b820191905f5260205f20905b8154815290600101906020018083116104cc57829003601f168201915b5050505050815250509050805f015181602001519250925050915091565b61050f610b0a565b5f5f8051602061191f83398151915260028101548154919250906001600160a01b0316634c1f08ce336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561057a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061059e9190611582565b10156106055760405162461bcd60e51b815260206004820152603060248201527f54656c65706f7274657252656769737472794170703a20696e76616c6964205460448201526f32b632b837b93a32b91039b2b73232b960811b6064820152608401610239565b61060f8133610883565b156106755760405162461bcd60e51b815260206004820152603060248201527f54656c65706f7274657252656769737472794170703a2054656c65706f72746560448201526f1c881859191c995cdcc81c185d5cd95960821b6064820152608401610239565b6106b5858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610b5492505050565b506106df60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b50505050565b6106ed610a3f565b6001600160a01b03811661071657604051631e4fbdf760e01b81525f6004820152602401610239565b6103ff81610a9a565b5f610728610b0a565b5f851561073c576107398787610c09565b90505b876001600160a01b0316897fa06eff1edd0c66b8dc96d086dda7ba263edf88d7417e6cb15073b5e7bff8a8ca898489898960405161077e9594939291906115c1565b60405180910390a36108446040518060c001604052808b81526020018a6001600160a01b0316815260200160405180604001604052808b6001600160a01b031681526020018581525081526020018781526020015f67ffffffffffffffff8111156107eb576107eb6115ee565b604051908082528060200260200182016040528015610814578160200160208202803683370190505b508152602001868660405160200161082d929190611602565b604051602081830303815290604052815250610d6b565b91505061087060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b979650505050505050565b610413610a3f565b6001600160a01b0381165f90815260018301602052604090205460ff165b92915050565b5f8051602061191f83398151915280546040805163301fd1f560e21b815290515f926001600160a01b03169163c07f47d49160048083019260209291908290030181865afa1580156108fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061091f9190611582565b6002830154909150818411156109915760405162461bcd60e51b815260206004820152603160248201527f54656c65706f7274657252656769737472794170703a20696e76616c6964205460448201527032b632b837b93a32b9103b32b939b4b7b760791b6064820152608401610239565b808411610a065760405162461bcd60e51b815260206004820152603f60248201527f54656c65706f7274657252656769737472794170703a206e6f7420677265617460448201527f6572207468616e2063757272656e74206d696e696d756d2076657273696f6e006064820152608401610239565b60028301849055604051849082907fa9a7ef57e41f05b4c15480842f5f0c27edfcbb553fed281f7c4068452cc1c02d905f90a350505050565b33610a717f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146104135760405163118cdaa760e01b8152336004820152602401610239565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901610b4e57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f81806020019051810190610b699190611615565b6040805180820182526001600160a01b03868116825260208083018581525f8a815291829052939020825181546001600160a01b03191692169190911781559151929350916001820190610bbd90826116fd565b50905050826001600160a01b0316847f1f5c800b5f2b573929a7948f82a199c2a212851b53a6c5bd703ece23999d24aa83604051610bfb91906117bd565b60405180910390a350505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038516906370a0823190602401602060405180830381865afa158015610c4f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c739190611582565b9050610c8a6001600160a01b038516333086610e86565b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610cce573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cf29190611582565b9050818111610d585760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b6064820152608401610239565b610d6282826117e3565b95945050505050565b5f80610d75610eed565b60408401516020015190915015610e1a576040830151516001600160a01b0316610df75760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f7274657252656769737472794170703a207a65726f206665652060448201526c746f6b656e206164647265737360981b6064820152608401610239565b604083015160208101519051610e1a916001600160a01b03909116908390610fdd565b604051630624488560e41b81526001600160a01b03821690636244885090610e46908690600401611839565b6020604051808303815f875af1158015610e62573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061042e9190611582565b6040516001600160a01b0384811660248301528381166044830152606482018390526106df9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611064565b5f8051602061191f83398151915280546040805163d820e64f60e01b815290515f939284926001600160a01b039091169163d820e64f916004808201926020929091908290030181865afa158015610f47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6b91906118b6565b9050610f778282610883565b156108a15760405162461bcd60e51b815260206004820152603060248201527f54656c65706f7274657252656769737472794170703a2054656c65706f72746560448201526f1c881cd95b991a5b99c81c185d5cd95960821b6064820152608401610239565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa15801561102a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104e9190611582565b90506106df848461105f85856118d1565b6110ca565b5f6110786001600160a01b03841683611159565b905080515f1415801561109c57508080602001905181019061109a91906118e4565b155b156110c557604051635274afe760e01b81526001600160a01b0384166004820152602401610239565b505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261111b8482611166565b6106df576040516001600160a01b0384811660248301525f604483015261114f91869182169063095ea7b390606401610ebb565b6106df8482611064565b606061042e83835f611203565b5f805f846001600160a01b0316846040516111819190611903565b5f604051808303815f865af19150503d805f81146111ba576040519150601f19603f3d011682016040523d82523d5f602084013e6111bf565b606091505b50915091508180156111e95750805115806111e95750808060200190518101906111e991906118e4565b8015610d625750505050506001600160a01b03163b151590565b6060814710156112285760405163cd78605960e01b8152306004820152602401610239565b5f80856001600160a01b031684866040516112439190611903565b5f6040518083038185875af1925050503d805f811461127d576040519150601f19603f3d011682016040523d82523d5f602084013e611282565b606091505b509150915061129286838361129c565b9695505050505050565b6060826112b1576112ac826112f8565b61042e565b81511580156112c857506001600160a01b0384163b155b156112f157604051639996b31560e01b81526001600160a01b0385166004820152602401610239565b508061042e565b8051156113085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b03811681146103ff575f80fd5b5f60208284031215611345575f80fd5b813561042e81611321565b5f60208284031215611360575f80fd5b5035919050565b5f5b83811015611381578181015183820152602001611369565b50505f910152565b5f81518084526113a0816020860160208601611367565b601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190525f906113d790830184611389565b949350505050565b5f8083601f8401126113ef575f80fd5b50813567ffffffffffffffff811115611406575f80fd5b60208301915083602082850101111561141d575f80fd5b9250929050565b5f805f8060608587031215611437575f80fd5b84359350602085013561144981611321565b9250604085013567ffffffffffffffff811115611464575f80fd5b611470878288016113df565b95989497509550505050565b5f805f805f805f60c0888a031215611492575f80fd5b8735965060208801356114a481611321565b955060408801356114b481611321565b9450606088013593506080880135925060a088013567ffffffffffffffff8111156114dd575f80fd5b6114e98a828b016113df565b989b979a50959850939692959293505050565b6020808252602e908201527f54656c65706f7274657252656769737472794170703a207a65726f2054656c6560408201526d706f72746572206164647265737360901b606082015260800190565b600181811c9082168061155e57607f821691505b60208210810361157c57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215611592575f80fd5b5051919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b0386168152846020820152836040820152608060608201525f610870608083018486611599565b634e487b7160e01b5f52604160045260245ffd5b602081525f6113d7602083018486611599565b5f60208284031215611625575f80fd5b815167ffffffffffffffff8082111561163c575f80fd5b818401915084601f83011261164f575f80fd5b815181811115611661576116616115ee565b604051601f8201601f19908116603f01168101908382118183101715611689576116896115ee565b816040528281528760208487010111156116a1575f80fd5b610870836020830160208801611367565b601f8211156110c557805f5260205f20601f840160051c810160208510156116d75750805b601f840160051c820191505b818110156116f6575f81556001016116e3565b5050505050565b815167ffffffffffffffff811115611717576117176115ee565b61172b81611725845461154a565b846116b2565b602080601f83116001811461175e575f84156117475750858301515b5f19600386901b1c1916600185901b1785556117b5565b5f85815260208120601f198616915b8281101561178c5788860151825594840194600190910190840161176d565b50858210156117a957878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b602081525f61042e6020830184611389565b634e487b7160e01b5f52601160045260245ffd5b818103818111156108a1576108a16117cf565b5f815180845260208085019450602084015f5b8381101561182e5781516001600160a01b031687529582019590820190600101611809565b509495945050505050565b60208152815160208201525f602083015160018060a01b03808216604085015260408501519150808251166060850152506020810151608084015250606083015160a0830152608083015160e060c08401526118996101008401826117f6565b905060a0840151601f198483030160e0850152610d628282611389565b5f602082840312156118c6575f80fd5b815161042e81611321565b808201808211156108a1576108a16117cf565b5f602082840312156118f4575f80fd5b8151801515811461042e575f80fd5b5f8251611914818460208701611367565b919091019291505056fede77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d00a164736f6c6343000819000a54656c65706f7274657252656769737472794170703a20696e76616c69642054", + Bin: "0x608060405234801561000f575f80fd5b50604051611fca380380611fca83398101604081905261002e9161062e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff1615906001600160401b03165f811580156100775750825b90505f826001600160401b031660011480156100925750303b155b9050811580156100a0575080155b156100be5760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b031916600117855583156100ec57845460ff60401b1916680100000000000000001785555b6100f4610152565b6100ff888888610164565b831561014557845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505061067e565b61015a610184565b6101626101d2565b565b61016c610184565b6101768382610200565b61017f82610226565b505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661016257604051631afcd79f60e31b815260040160405180910390fd5b6101da610184565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b610208610184565b610210610152565b61021861023a565b6102228282610242565b5050565b61022e610184565b610237816103d1565b50565b610162610184565b61024a610184565b6001600160a01b0382166102cb5760405162461bcd60e51b815260206004820152603760248201527f54656c65706f7274657252656769737472794170703a207a65726f2054656c6560448201527f706f72746572207265676973747279206164647265737300000000000000000060648201526084015b60405180910390fd5b5f7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d0090505f8390505f816001600160a01b031663c07f47d46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610330573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103549190610667565b116103a95760405162461bcd60e51b815260206004820152603260248201525f80516020611faa833981519152604482015271656c65706f7274657220726567697374727960701b60648201526084016102c2565b81546001600160a01b0319166001600160a01b0382161782556103cb8361040b565b50505050565b6103d9610184565b6001600160a01b03811661040257604051631e4fbdf760e01b81525f60048201526024016102c2565b610237816105a3565b7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d0080546040805163301fd1f560e21b815290515f926001600160a01b03169163c07f47d49160048083019260209291908290030181865afa158015610472573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104969190610667565b6002830154909150818411156104f55760405162461bcd60e51b815260206004820152603160248201525f80516020611faa83398151915260448201527032b632b837b93a32b9103b32b939b4b7b760791b60648201526084016102c2565b80841161056a5760405162461bcd60e51b815260206004820152603f60248201527f54656c65706f7274657252656769737472794170703a206e6f7420677265617460448201527f6572207468616e2063757272656e74206d696e696d756d2076657273696f6e0060648201526084016102c2565b60028301849055604051849082907fa9a7ef57e41f05b4c15480842f5f0c27edfcbb553fed281f7c4068452cc1c02d905f90a350505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b80516001600160a01b0381168114610629575f80fd5b919050565b5f805f60608486031215610640575f80fd5b61064984610613565b925061065760208501610613565b9150604084015190509250925092565b5f60208284031215610677575f80fd5b5051919050565b61191f8061068b5f395ff3fe608060405234801561000f575f80fd5b50600436106100b1575f3560e01c8063973142971161006e578063973142971461014b578063b33fead41461016e578063c868efaa1461018f578063d2cc7a70146101a2578063f2fde38b146101aa578063f63d09d7146101bd575f80fd5b80632b0d8f18146100b55780634511243e146100ca5780635eb99514146100dd578063715018a6146100f05780638da5cb5b146100f8578063909a6ac014610116575b5f80fd5b6100c86100c33660046112f5565b6101d0565b005b6100c86100d83660046112f5565b6102cf565b6100c86100eb366004611310565b6103bb565b6100c86103cf565b6101006103e2565b60405161010d9190611327565b60405180910390f35b61013d7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d0081565b60405190815260200161010d565b61015e6101593660046112f5565b610410565b604051901515815260200161010d565b61018161017c366004611310565b61042d565b60405161010d929190611388565b6100c861019d3660046113f8565b6104ff565b61013d6106b9565b6100c86101b83660046112f5565b6106cd565b61013d6101cb366004611450565b610707565b5f6101d9610850565b90506101e3610874565b6001600160a01b0382166102125760405162461bcd60e51b8152600401610209906114d0565b60405180910390fd5b61021c818361087c565b1561027f5760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f7274657252656769737472794170703a2061646472657373206160448201526c1b1c9958591e481c185d5cd959609a1b6064820152608401610209565b6001600160a01b0382165f81815260018381016020526040808320805460ff1916909217909155517f933f93e57a222e6330362af8b376d0a8725b6901e9a2fb86d00f169702b28a4c9190a25050565b5f6102d8610850565b90506102e2610874565b6001600160a01b0382166103085760405162461bcd60e51b8152600401610209906114d0565b610312818361087c565b6103705760405162461bcd60e51b815260206004820152602960248201527f54656c65706f7274657252656769737472794170703a2061646472657373206e6044820152681bdd081c185d5cd95960ba1b6064820152608401610209565b6001600160a01b0382165f818152600183016020526040808220805460ff19169055517f844e2f3154214672229235858fd029d1dfd543901c6d05931f0bc2480a2d72c39190a25050565b6103c3610874565b6103cc816108a0565b50565b6103d7610a41565b6103e05f610a73565b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b5f8061041a610850565b9050610426818461087c565b9392505050565b5f81815260208181526040808320815180830190925280546001600160a01b03168252600181018054606094869493929084019161046a9061151e565b80601f01602080910402602001604051908101604052809291908181526020018280546104969061151e565b80156104e15780601f106104b8576101008083540402835291602001916104e1565b820191905f5260205f20905b8154815290600101906020018083116104c457829003601f168201915b5050505050815250509050805f015181602001519250925050915091565b610507610ae3565b5f610510610850565b60028101548154919250906001600160a01b0316634c1f08ce336040518263ffffffff1660e01b81526004016105469190611327565b602060405180830381865afa158015610561573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105859190611556565b10156105ec5760405162461bcd60e51b815260206004820152603060248201527f54656c65706f7274657252656769737472794170703a20696e76616c6964205460448201526f32b632b837b93a32b91039b2b73232b960811b6064820152608401610209565b6105f6813361087c565b1561065c5760405162461bcd60e51b815260206004820152603060248201527f54656c65706f7274657252656769737472794170703a2054656c65706f72746560448201526f1c881859191c995cdcc81c185d5cd95960821b6064820152608401610209565b61069c858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610b1a92505050565b506106b360015f805160206118f383398151915255565b50505050565b5f806106c3610850565b6002015492915050565b6106d5610a41565b6001600160a01b0381166106fe575f604051631e4fbdf760e01b81526004016102099190611327565b6103cc81610a73565b5f610710610ae3565b5f8515610724576107218787610bcf565b90505b876001600160a01b0316897fa06eff1edd0c66b8dc96d086dda7ba263edf88d7417e6cb15073b5e7bff8a8ca8984898989604051610766959493929190611595565b60405180910390a361082c6040518060c001604052808b81526020018a6001600160a01b0316815260200160405180604001604052808b6001600160a01b031681526020018581525081526020018781526020015f67ffffffffffffffff8111156107d3576107d36115c2565b6040519080825280602002602001820160405280156107fc578160200160208202803683370190505b50815260200186866040516020016108159291906115d6565b604051602081830303815290604052815250610d39565b91505061084560015f805160206118f383398151915255565b979650505050505050565b7fde77a4dc7391f6f8f2d9567915d687d3aee79e7a1fc7300392f2727e9a0f1d0090565b6103e0610a41565b6001600160a01b0381165f90815260018301602052604090205460ff165b92915050565b5f6108a9610850565b90505f815f015f9054906101000a90046001600160a01b03166001600160a01b031663c07f47d46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109219190611556565b6002830154909150818411156109935760405162461bcd60e51b815260206004820152603160248201527f54656c65706f7274657252656769737472794170703a20696e76616c6964205460448201527032b632b837b93a32b9103b32b939b4b7b760791b6064820152608401610209565b808411610a085760405162461bcd60e51b815260206004820152603f60248201527f54656c65706f7274657252656769737472794170703a206e6f7420677265617460448201527f6572207468616e2063757272656e74206d696e696d756d2076657273696f6e006064820152608401610209565b60028301849055604051849082907fa9a7ef57e41f05b4c15480842f5f0c27edfcbb553fed281f7c4068452cc1c02d905f90a350505050565b33610a4a6103e2565b6001600160a01b0316146103e0573360405163118cdaa760e01b81526004016102099190611327565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f805160206118f3833981519152805460011901610b1457604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f81806020019051810190610b2f91906115e9565b6040805180820182526001600160a01b03868116825260208083018581525f8a815291829052939020825181546001600160a01b03191692169190911781559151929350916001820190610b8390826116d1565b50905050826001600160a01b0316847f1f5c800b5f2b573929a7948f82a199c2a212851b53a6c5bd703ece23999d24aa83604051610bc19190611791565b60405180910390a350505050565b5f80836001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610bfd9190611327565b602060405180830381865afa158015610c18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c3c9190611556565b9050610c536001600160a01b038516333086610e54565b6040516370a0823160e01b81525f906001600160a01b038616906370a0823190610c81903090600401611327565b602060405180830381865afa158015610c9c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cc09190611556565b9050818111610d265760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b6064820152608401610209565b610d3082826117b7565b95945050505050565b5f80610d43610ebb565b60408401516020015190915015610de8576040830151516001600160a01b0316610dc55760405162461bcd60e51b815260206004820152602d60248201527f54656c65706f7274657252656769737472794170703a207a65726f206665652060448201526c746f6b656e206164647265737360981b6064820152608401610209565b604083015160208101519051610de8916001600160a01b03909116908390610faf565b604051630624488560e41b81526001600160a01b03821690636244885090610e1490869060040161180d565b6020604051808303815f875af1158015610e30573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104269190611556565b6040516001600160a01b0384811660248301528381166044830152606482018390526106b39186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611036565b5f80610ec5610850565b90505f815f015f9054906101000a90046001600160a01b03166001600160a01b031663d820e64f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3d919061188a565b9050610f49828261087c565b1561089a5760405162461bcd60e51b815260206004820152603060248201527f54656c65706f7274657252656769737472794170703a2054656c65706f72746560448201526f1c881cd95b991a5b99c81c185d5cd95960821b6064820152608401610209565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015610ffc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110209190611556565b90506106b3848461103185856118a5565b611093565b5f61104a6001600160a01b03841683611122565b905080515f1415801561106e57508080602001905181019061106c91906118b8565b155b1561108e5782604051635274afe760e01b81526004016102099190611327565b505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526110e4848261112f565b6106b3576040516001600160a01b0384811660248301525f604483015261111891869182169063095ea7b390606401610e89565b6106b38482611036565b606061042683835f6111cc565b5f805f846001600160a01b03168460405161114a91906118d7565b5f604051808303815f865af19150503d805f8114611183576040519150601f19603f3d011682016040523d82523d5f602084013e611188565b606091505b50915091508180156111b25750805115806111b25750808060200190518101906111b291906118b8565b8015610d305750505050506001600160a01b03163b151590565b6060814710156111f1573060405163cd78605960e01b81526004016102099190611327565b5f80856001600160a01b0316848660405161120c91906118d7565b5f6040518083038185875af1925050503d805f8114611246576040519150601f19603f3d011682016040523d82523d5f602084013e61124b565b606091505b509150915061125b868383611265565b9695505050505050565b60608261127a57611275826112b8565b610426565b815115801561129157506001600160a01b0384163b155b156112b15783604051639996b31560e01b81526004016102099190611327565b5080610426565b8051156112c85780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b03811681146103cc575f80fd5b5f60208284031215611305575f80fd5b8135610426816112e1565b5f60208284031215611320575f80fd5b5035919050565b6001600160a01b0391909116815260200190565b5f5b8381101561135557818101518382015260200161133d565b50505f910152565b5f815180845261137481602086016020860161133b565b601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190525f906113ab9083018461135d565b949350505050565b5f8083601f8401126113c3575f80fd5b50813567ffffffffffffffff8111156113da575f80fd5b6020830191508360208285010111156113f1575f80fd5b9250929050565b5f805f806060858703121561140b575f80fd5b84359350602085013561141d816112e1565b9250604085013567ffffffffffffffff811115611438575f80fd5b611444878288016113b3565b95989497509550505050565b5f805f805f805f60c0888a031215611466575f80fd5b873596506020880135611478816112e1565b95506040880135611488816112e1565b9450606088013593506080880135925060a088013567ffffffffffffffff8111156114b1575f80fd5b6114bd8a828b016113b3565b989b979a50959850939692959293505050565b6020808252602e908201527f54656c65706f7274657252656769737472794170703a207a65726f2054656c6560408201526d706f72746572206164647265737360901b606082015260800190565b600181811c9082168061153257607f821691505b60208210810361155057634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215611566575f80fd5b5051919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b0386168152846020820152836040820152608060608201525f61084560808301848661156d565b634e487b7160e01b5f52604160045260245ffd5b602081525f6113ab60208301848661156d565b5f602082840312156115f9575f80fd5b815167ffffffffffffffff80821115611610575f80fd5b818401915084601f830112611623575f80fd5b815181811115611635576116356115c2565b604051601f8201601f19908116603f0116810190838211818310171561165d5761165d6115c2565b81604052828152876020848701011115611675575f80fd5b61084583602083016020880161133b565b601f82111561108e57805f5260205f20601f840160051c810160208510156116ab5750805b601f840160051c820191505b818110156116ca575f81556001016116b7565b5050505050565b815167ffffffffffffffff8111156116eb576116eb6115c2565b6116ff816116f9845461151e565b84611686565b602080601f831160018114611732575f841561171b5750858301515b5f19600386901b1c1916600185901b178555611789565b5f85815260208120601f198616915b8281101561176057888601518255948401946001909101908401611741565b508582101561177d57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b602081525f610426602083018461135d565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561089a5761089a6117a3565b5f815180845260208085019450602084015f5b838110156118025781516001600160a01b0316875295820195908201906001016117dd565b509495945050505050565b60208152815160208201525f602083015160018060a01b03808216604085015260408501519150808251166060850152506020810151608084015250606083015160a0830152608083015160e060c084015261186d6101008401826117ca565b905060a0840151601f198483030160e0850152610d30828261135d565b5f6020828403121561189a575f80fd5b8151610426816112e1565b8082018082111561089a5761089a6117a3565b5f602082840312156118c8575f80fd5b81518015158114610426575f80fd5b5f82516118e881846020870161133b565b919091019291505056fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a164736f6c6343000819000a54656c65706f7274657252656769737472794170703a20696e76616c69642054", } // TestMessengerABI is the input ABI used to generate the binding from. diff --git a/abi-bindings/go/validator-manager/ERC20TokenStakingManager/ERC20TokenStakingManager.go b/abi-bindings/go/validator-manager/ERC20TokenStakingManager/ERC20TokenStakingManager.go new file mode 100644 index 000000000..513f1beee --- /dev/null +++ b/abi-bindings/go/validator-manager/ERC20TokenStakingManager/ERC20TokenStakingManager.go @@ -0,0 +1,2981 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc20tokenstakingmanager + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// InitialValidator is an auto generated low-level Go binding around an user-defined struct. +type InitialValidator struct { + NodeID []byte + BlsPublicKey []byte + Weight uint64 +} + +// PChainOwner is an auto generated low-level Go binding around an user-defined struct. +type PChainOwner struct { + Threshold uint32 + Addresses []common.Address +} + +// PoSValidatorManagerSettings is an auto generated low-level Go binding around an user-defined struct. +type PoSValidatorManagerSettings struct { + BaseSettings ValidatorManagerSettings + MinimumStakeAmount *big.Int + MaximumStakeAmount *big.Int + MinimumStakeDuration uint64 + MinimumDelegationFeeBips uint16 + MaximumStakeMultiplier uint8 + WeightToValueFactor *big.Int + RewardCalculator common.Address +} + +// SubnetConversionData is an auto generated low-level Go binding around an user-defined struct. +type SubnetConversionData struct { + SubnetID [32]byte + ValidatorManagerBlockchainID [32]byte + ValidatorManagerAddress common.Address + InitialValidators []InitialValidator +} + +// Validator is an auto generated low-level Go binding around an user-defined struct. +type Validator struct { + Status uint8 + NodeID []byte + StartingWeight uint64 + MessageNonce uint64 + Weight uint64 + StartedAt uint64 + EndedAt uint64 +} + +// ValidatorManagerSettings is an auto generated low-level Go binding around an user-defined struct. +type ValidatorManagerSettings struct { + SubnetID [32]byte + ChurnPeriodSeconds uint64 + MaximumChurnPercentage uint8 +} + +// ValidatorRegistrationInput is an auto generated low-level Go binding around an user-defined struct. +type ValidatorRegistrationInput struct { + NodeID []byte + BlsPublicKey []byte + RegistrationExpiry uint64 + RemainingBalanceOwner PChainOwner + DisableOwner PChainOwner +} + +// ERC20TokenStakingManagerMetaData contains all meta data concerning the ERC20TokenStakingManager contract. +var ERC20TokenStakingManagerMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ADDRESS_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"BIPS_CONVERSION_FACTOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"BLS_PUBLIC_KEY_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ERC20_STAKING_MANAGER_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_CHURN_PERCENTAGE_LIMIT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_DELEGATION_FEE_BIPS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_REGISTRATION_EXPIRY_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_STAKE_MULTIPLIER_LIMIT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"POS_VALIDATOR_MANAGER_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"P_CHAIN_BLOCKCHAIN_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VALIDATOR_MANAGER_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimDelegationFees\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeDelegatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndDelegation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"forceInitializeEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"forceInitializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getValidator\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structValidator\",\"components\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumValidatorStatus\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"startingWeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageNonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"startedAt\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"endedAt\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structPoSValidatorManagerSettings\",\"components\":[{\"name\":\"baseSettings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"churnPeriodSeconds\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maximumChurnPercentage\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"minimumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maximumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimumStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"minimumDelegationFeeBips\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"weightToValueFactor\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"rewardCalculator\",\"type\":\"address\",\"internalType\":\"contractIRewardCalculator\"}]},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20Mintable\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeDelegatorRegistration\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"delegationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"registrationInput\",\"type\":\"tuple\",\"internalType\":\"structValidatorRegistrationInput\",\"components\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remainingBalanceOwner\",\"type\":\"tuple\",\"internalType\":\"structPChainOwner\",\"components\":[{\"name\":\"threshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"addresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]},{\"name\":\"disableOwner\",\"type\":\"tuple\",\"internalType\":\"structPChainOwner\",\"components\":[{\"name\":\"threshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"addresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}]},{\"name\":\"delegationFeeBips\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"minStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"stakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorSet\",\"inputs\":[{\"name\":\"subnetConversionData\",\"type\":\"tuple\",\"internalType\":\"structSubnetConversionData\",\"components\":[{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorManagerBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"initialValidators\",\"type\":\"tuple[]\",\"internalType\":\"structInitialValidator[]\",\"components\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}]},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registeredValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendUpdateDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitUptimeProof\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"valueToWeight\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"weightToValue\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"DelegationEnded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"rewards\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"fees\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorAdded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"delegatorAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"delegatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRegistered\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"startTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRemovalInitialized\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitialValidatorCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UptimeUpdated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"uptime\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorWeightUpdate\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"AddressInsufficientBalance\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"DelegatorIneligibleForRewards\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBLSKeyLength\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidBLSPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodecID\",\"inputs\":[{\"name\":\"id\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidDelegationFee\",\"inputs\":[{\"name\":\"delegationFeeBips\",\"type\":\"uint16\",\"internalType\":\"uint16\"}]},{\"type\":\"error\",\"name\":\"InvalidDelegationID\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidDelegatorStatus\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumDelegatorStatus\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitializationStatus\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMaximumChurnPercentage\",\"inputs\":[{\"name\":\"maximumChurnPercentage\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageLength\",\"inputs\":[{\"name\":\"actual\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"expected\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageType\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMinStakeDuration\",\"inputs\":[{\"name\":\"minStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidNodeID\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidNonce\",\"inputs\":[{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidPChainOwnerThreshold\",\"inputs\":[{\"name\":\"threshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"addressesLength\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidRegistrationExpiry\",\"inputs\":[{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidStakeAmount\",\"inputs\":[{\"name\":\"stakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidStakeMultiplier\",\"inputs\":[{\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidSubnetConversionID\",\"inputs\":[{\"name\":\"encodedSubnetConversionID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"expectedSubnetConversionID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidTokenAddress\",\"inputs\":[{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidTotalWeight\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidValidationID\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorManagerAddress\",\"inputs\":[{\"name\":\"validatorManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorManagerBlockchainID\",\"inputs\":[{\"name\":\"blockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorStatus\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumValidatorStatus\"}]},{\"type\":\"error\",\"name\":\"InvalidWarpMessage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidWarpOriginSenderAddress\",\"inputs\":[{\"name\":\"senderAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidWarpSourceChainID\",\"inputs\":[{\"name\":\"sourceChainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"MaxChurnRateExceeded\",\"inputs\":[{\"name\":\"churnAmount\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MaxWeightExceeded\",\"inputs\":[{\"name\":\"newValidatorWeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MinStakeDurationNotPassed\",\"inputs\":[{\"name\":\"endTime\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"NodeAlreadyRegistered\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PChainOwnerAddressesNotSorted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedOwner\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnexpectedRegistrationStatus\",\"inputs\":[{\"name\":\"validRegistration\",\"type\":\"bool\",\"internalType\":\"bool\"}]},{\"type\":\"error\",\"name\":\"ValidatorIneligibleForRewards\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ValidatorNotPoS\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ZeroWeightToValueFactor\",\"inputs\":[]}]", + Bin: "0x608060405234801561000f575f80fd5b50604051615f31380380615f3183398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b615de48061014d5f395ff3fe608060405234801561000f575f80fd5b50600436106101c1575f3560e01c80638280a25a116100f6578063ba3a4b971161009a578063ba3a4b97146103d9578063bc5fbfec146103ec578063bee0a03f14610413578063c974d1b614610426578063d5f20ff61461042e578063df93d8de1461044e578063e4a63c4014610458578063f74c607b1461047f578063fd7ac5e714610492575f80fd5b80638280a25a1461034357806393e245981461034b57806398f3e2b41461035e5780639e1bc4ef14610371578063a3a65e4814610384578063a9778a7a14610270578063afb9809614610397578063b771b3bc146103be575f80fd5b80633a1cfff6116101685780633a1cfff61461028c578063467ef06f1461029f5780634bee0040146102b25780635297fae6146102d357806360305d62146102e6578063620658561461030357806366435abf14610316578063732214f81461032957806376f7862114610330575f80fd5b80630118acc4146101c55780630322ed98146101da578063151d30d1146101ed5780631ec447241461020c57806320d91b7a1461021f57806325e1c776146102325780632e2194d81461024557806335455ded14610270575b5f80fd5b6101d86101d3366004615085565b6104a5565b005b6101d86101e83660046150c0565b6104da565b6101f5600a81565b60405160ff90911681526020015b60405180910390f35b6101d861021a366004615085565b6106dd565b6101d861022d3660046150d7565b6106e8565b6101d8610240366004615125565b610be6565b6102586102533660046150c0565b610c5a565b6040516001600160401b039091168152602001610203565b61027961271081565b60405161ffff9091168152602001610203565b6101d861029a366004615085565b610cae565b6101d86102ad366004615146565b610cb9565b6102c56102c0366004615186565b610d69565b604051908152602001610203565b6101d86102e13660046151eb565b610d90565b6102ee601481565b60405163ffffffff9091168152602001610203565b6102c5610311366004615213565b610feb565b6102586103243660046150c0565b61100b565b6102c55f81565b6101d861033e366004615085565b61101f565b6101f5603081565b6101d86103593660046150c0565b61104a565b6101d861036c3660046151eb565b611107565b6102c561037f36600461522c565b6112c6565b6101d8610392366004615146565b6112e4565b6102c57f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0081565b6103cc6005600160991b0181565b604051610203919061524c565b6101d86103e73660046150c0565b61146a565b6102c57fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0081565b6101d86104213660046150c0565b611648565b6101f5601481565b61044161043c3660046150c0565b611765565b60405161020391906152d5565b6102586202a30081565b6102c57f6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab0081565b6101d861048d366004615369565b6118a7565b6102c56104a03660046153a7565b611986565b6104b08383836119be565b6104d557604051631036cf9160e11b8152600481018490526024015b60405180910390fd5b505050565b5f6104e3611d0b565b5f838152600782016020526040808220815160e0810190925280549394509192909190829060ff16600581111561051c5761051c615260565b600581111561052d5761052d615260565b815260200160018201805461054190615412565b80601f016020809104026020016040519081016040528092919081815260200182805461056d90615412565b80156105b85780601f1061058f576101008083540402835291602001916105b8565b820191905f5260205f20905b81548152906001019060200180831161059b57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561062357610623615260565b14610656575f8381526007830160205260409081902054905163170cc93360e21b81526104cc9160ff169060040161544a565b6005600160991b016001600160a01b031663ee5b48eb61067b8584606001515f611d2f565b6040518263ffffffff1660e01b81526004016106979190615458565b6020604051808303815f875af11580156106b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d7919061546a565b50505050565b6106d78383836119be565b5f6106f1611d0b565b600981015490915060ff161561071a57604051637fab81e560e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561075d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610781919061546a565b8360200135146107aa576040516372b0a7e760e11b8152602084013560048201526024016104cc565b306107bb6060850160408601615481565b6001600160a01b0316146107f3576107d96060840160408501615481565b604051632f88120d60e21b81526004016104cc919061524c565b5f610801606085018561549c565b905090505f805b828163ffffffff161015610ae8575f610824606088018861549c565b8363ffffffff1681811061083a5761083a6154e1565b905060200281019061084c91906154f5565b61085590615619565b80516040519192505f91600888019161086d91615692565b9081526020016040518091039020541461089d57805160405163a41f772f60e01b81526104cc9190600401615458565b5f6002885f0135846040516020016108cc92919091825260e01b6001600160e01b031916602082015260240190565b60408051601f19818403018152908290526108e691615692565b602060405180830381855afa158015610901573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610924919061546a565b90508086600801835f015160405161093c9190615692565b90815260408051602092819003830181209390935560e0830181526002835284518284015284810180516001600160401b03908116858401525f60608601819052915181166080860152421660a085015260c0840181905284815260078a01909252902081518154829060ff191660018360058111156109be576109be615260565b0217905550602082015160018201906109d790826156e7565b506040828101516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090930151600390920180546001600160401b03191692841692909217909155830151610a7b9116856157b6565b8251604051919550610a8c91615692565b60408051918290038220908401516001600160401b031682529082907f9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf9060200160405180910390a3505080610ae1906157c9565b9050610808565b50600483018190556001830154606490610b0c90600160401b900460ff16836157eb565b1015610b2e57604051635943317f60e01b8152600481018290526024016104cc565b5f610b44610b3b86611d7e565b60400151611e89565b90505f610b5087612016565b90505f600282604051610b639190615692565b602060405180830381855afa158015610b7e573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610ba1919061546a565b9050828114610bcd57604051631872fc8d60e01b815260048101829052602481018490526044016104cc565b5050506009909201805460ff1916600117905550505050565b610bef826121eb565b610c0f576040516330efa98b60e01b8152600481018390526024016104cc565b5f610c1983611765565b5190506002816005811115610c3057610c30615260565b14610c50578060405163170cc93360e21b81526004016104cc919061544a565b6106d78383612214565b5f80610c64612462565b60030154610c729084615802565b9050801580610c8757506001600160401b0381115b15610ca85760405163222d164360e21b8152600481018490526024016104cc565b92915050565b6106d7838383612486565b610cc1612651565b5f610cca612462565b90505f80610cd78461269b565b91509150610ce4826121eb565b610cf057505050610d5e565b5f8281526005840160205260409020546001600160a01b0316600482516005811115610d1e57610d1e615260565b03610d43575f83815260088501602052604081208054919055610d4182826129d5565b505b610d5981610d548460400151610feb565b612a45565b505050505b610d66612a63565b50565b5f610d72612651565b610d7e85858585612a89565b9050610d88612a63565b949350505050565b5f610d99612462565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff166003811115610dd257610dd2615260565b6003811115610de357610de3615260565b8152815461010090046001600160a01b0316602082015260018201546040808301919091526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0909101528101519091505f610e5982611765565b9050600183516003811115610e7057610e70615260565b14610e91578251604051633b0d540d60e21b81526104cc9190600401615821565b600481516005811115610ea657610ea6615260565b03610ebc57610eb485612c40565b505050505050565b5f80610ed3610eca89611d7e565b60400151612e60565b5091509150818414610f0057846040015160405163089938b360e11b81526004016104cc91815260200190565b806001600160401b031683606001516001600160401b03161080610f395750806001600160401b03168560a001516001600160401b0316115b15610f6257604051632e19bc2d60e11b81526001600160401b03821660048201526024016104cc565b5f878152600687016020908152604091829020805460ff1916600290811782550180546001600160401b034216600160401b810267ffffffffffffffff60401b19909216919091179091559151918252859189917f047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6910160405180910390a35050505050505050565b5f610ff4612462565b60030154610ca8906001600160401b0384166157eb565b5f61101582611765565b6080015192915050565b61102a838383612486565b6104d557604051635bff683f60e11b8152600481018490526024016104cc565b5f611053612462565b90505f61105f83611765565b519050600481600581111561107657611076615260565b14611096578060405163170cc93360e21b81526004016104cc919061544a565b5f8381526005830160205260409020546001600160a01b031633146110d157335b604051636e2ccd7560e11b81526004016104cc919061524c565b5f838152600883016020908152604080832080549084905560058601909252909120546106d7906001600160a01b0316826129d5565b61110f612651565b5f611118612462565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff16600381111561115157611151615260565b600381111561116257611162615260565b8152815461010090046001600160a01b03166020820152600182015460408201526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c09091015290506003815160038111156111db576111db615260565b146111fc578051604051633b0d540d60e21b81526104cc9190600401615821565b600461120b8260400151611765565b51600581111561121d5761121d615260565b146112af575f61122c85611d7e565b90505f8061123d8360400151612e60565b5091509150818460400151146112695760405163089938b360e11b8152600481018390526024016104cc565b806001600160401b03168460c001516001600160401b031611156112ab57604051632e19bc2d60e11b81526001600160401b03821660048201526024016104cc565b5050505b6112b883612c40565b50506112c2612a63565b5050565b5f6112cf612651565b6112da8333846130b6565b9050610ca8612a63565b5f6112ed611d0b565b90505f806113066112fd85611d7e565b6040015161338b565b915091508061132c57604051632d07135360e01b815281151560048201526024016104cc565b5f8281526006840160205260409020805461134690615412565b90505f0361136a5760405163089938b360e11b8152600481018390526024016104cc565b60015f83815260078501602052604090205460ff16600581111561139057611390615260565b146113c3575f8281526007840160205260409081902054905163170cc93360e21b81526104cc9160ff169060040161544a565b5f82815260068401602052604081206113db91614fd4565b5f828152600784016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160c01b026001600160c01b0390931692909217928390558451600160801b9093041682529181019190915283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a250505050565b5f611473612462565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff1660038111156114ac576114ac615260565b60038111156114bd576114bd615260565b8152815461010090046001600160a01b0316602082015260018083015460408301526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0909101529091508151600381111561153657611536615260565b14158015611557575060038151600381111561155457611554615260565b14155b15611578578051604051633b0d540d60e21b81526104cc9190600401615821565b5f6115868260400151611765565b905080606001516001600160401b03165f036115b8576040516339b894f960e21b8152600481018590526024016104cc565b6005600160991b016001600160a01b031663ee5b48eb6115e5846040015184606001518560800151611d2f565b6040518263ffffffff1660e01b81526004016116019190615458565b6020604051808303815f875af115801561161d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611641919061546a565b5050505050565b5f611651611d0b565b5f838152600682016020526040902080549192509061166f90615412565b90505f036116935760405163089938b360e11b8152600481018390526024016104cc565b60015f83815260078301602052604090205460ff1660058111156116b9576116b9615260565b146116ec575f8281526007820160205260409081902054905163170cc93360e21b81526104cc9160ff169060040161544a565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91611725919060040161583b565b6020604051808303815f875af1158015611741573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d5919061546a565b61176d61500b565b5f611776611d0b565b5f84815260078201602052604090819020815160e0810190925280549293509091829060ff1660058111156117ad576117ad615260565b60058111156117be576117be615260565b81526020016001820180546117d290615412565b80601f01602080910402602001604051908101604052809291908181526020018280546117fe90615412565b80156118495780601f1061182057610100808354040283529160200191611849565b820191905f5260205f20905b81548152906001019060200180831161182c57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b9091048116608083015260039092015490911660a0909101529392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806118f0575080546001600160401b03808416911610155b1561190e5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b1781556119398484613547565b805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b5f80611990611d0b565b90508060080184846040516119a69291906158c5565b90815260200160405180910390205491505092915050565b5f806119c8612462565b5f868152600682016020526040808220815160e0810190925280549394509192909190829060ff166003811115611a0157611a01615260565b6003811115611a1257611a12615260565b8152815461010090046001600160a01b0316602082015260018201546040808301919091526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0909101528101519091505f611a8882611765565b9050600283516003811115611a9f57611a9f615260565b14611ac0578251604051633b0d540d60e21b81526104cc9190600401615821565b60208301516001600160a01b03163314611b5c575f8281526005850160205260409020546001600160a01b03163314611af957336110b7565b5f82815260058501602052604090205460a0820151611b2891600160b01b90046001600160401b0316906158d4565b6001600160401b0316421015611b5c5760405163fb6ce63f60e01b81526001600160401b03421660048201526024016104cc565b600281516005811115611b7157611b71615260565b03611c9f5760028401546080840151611b93916001600160401b0316906158d4565b6001600160401b0316421015611bc75760405163fb6ce63f60e01b81526001600160401b03421660048201526024016104cc565b8615611bd957611bd78287612214565b505b5f8881526006850160205260409020805460ff1916600317905560608301516080820151611c12918491611c0d91906158f4565b613561565b505f898152600686016020526040812060020180546001600160401b03909316600160c01b026001600160c01b0390931692909217909155611c53846136ab565b5f8a81526007870160205260408082208390555191925084918b917f366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed5791a315159450611d049350505050565b600481516005811115611cb457611cb4615260565b03611ce857611cc2836136ab565b5f898152600786016020526040902055611cdb88612c40565b6001945050505050611d04565b805160405163170cc93360e21b81526104cc919060040161544a565b9392505050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0090565b604080515f6020820152600360e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b60408051606080820183525f8083526020830152918101919091526040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611de2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e09919081019061591f565b9150915080611e2b57604051636b2f19e960e01b815260040160405180910390fd5b815115611e51578151604051636ba589a560e01b815260048101919091526024016104cc565b60208201516001600160a01b031615611e82578160200151604051624de75d60e31b81526004016104cc919061524c565b5092915050565b5f8151602614611ebe57815160405163cc92daa160e01b815263ffffffff9091166004820152602660248201526044016104cc565b5f805b6002811015611f0d57611ed58160016159f1565b611ee09060086157eb565b61ffff16848281518110611ef657611ef66154e1565b016020015160f81c901b9190911790600101611ec1565b5061ffff811615611f375760405163407b587360e01b815261ffff821660048201526024016104cc565b5f805b6004811015611f9257611f4e8160036159f1565b611f599060086157eb565b63ffffffff1685611f6b8360026157b6565b81518110611f7b57611f7b6154e1565b016020015160f81c901b9190911790600101611f3a565b5063ffffffff811615611fb857604051635b60892f60e01b815260040160405180910390fd5b5f805b602081101561200d57611fcf81601f6159f1565b611fda9060086157eb565b86611fe68360066157b6565b81518110611ff657611ff66154e1565b016020015160f81c901b9190911790600101611fbb565b50949350505050565b60605f8083356020850135601461203287870160408901615481565b61203f606089018961549c565b60405160f09790971b6001600160f01b0319166020880152602287019590955250604285019290925260e090811b6001600160e01b0319908116606286015260609290921b6001600160601b03191660668501529190911b16607a820152607e0160405160208183030381529060405290505f5b6120c0606085018561549c565b9050811015611e8257816120d7606086018661549c565b838181106120e7576120e76154e1565b90506020028101906120f991906154f5565b6121039080615a04565b9050612112606087018761549c565b84818110612122576121226154e1565b905060200281019061213491906154f5565b61213e9080615a04565b61214b606089018961549c565b8681811061215b5761215b6154e1565b905060200281019061216d91906154f5565b61217b906020810190615a04565b61218860608b018b61549c565b88818110612198576121986154e1565b90506020028101906121aa91906154f5565b6121bb906060810190604001615213565b6040516020016121d19796959493929190615a46565b60408051601f1981840301815291905291506001016120b3565b5f806121f5612462565b5f938452600501602052505060409020546001600160a01b0316151590565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa15801561225f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612286919081019061591f565b91509150806122a857604051636b2f19e960e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061230f919061546a565b825114612335578151604051636ba589a560e01b815260048101919091526024016104cc565b60208201516001600160a01b031615612366578160200151604051624de75d60e31b81526004016104cc919061524c565b5f80612375846040015161382e565b9150915081871461239c5760405163089938b360e11b8152600481018890526024016104cc565b5f6123a5612462565b5f8981526005820160205260409020600101549091506001600160401b039081169083161115612438575f88815260058201602090815260409182902060010180546001600160401b0319166001600160401b038616908117909155915191825289917fec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435910160405180910390a2612457565b5f8881526005820160205260409020600101546001600160401b031691505b509695505050505050565b7f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0090565b5f80612490612462565b90505f61249c86613a1f565b90506124a7866121eb565b6124b657600192505050611d04565b5f8681526005830160205260409020546001600160a01b031633146124db57336110b7565b5f86815260058301602052604090205460a082015161250a91600160b01b90046001600160401b0316906158d4565b6001600160401b03168160c001516001600160401b031610156125515760c081015160405163fb6ce63f60e01b81526001600160401b0390911660048201526024016104cc565b5f8515612569576125628786612214565b9050612587565b505f8681526005830160205260409020600101546001600160401b03165b600483015460408301515f916001600160a01b031690634f22429f906125ac90610feb565b60a086015160c08701516040516001600160e01b031960e086901b1681526125dc93929182918990600401615aaf565b602060405180830381865afa1580156125f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261b919061546a565b905080846008015f8a81526020019081526020015f205f82825461263f91906157b6565b90915550501515979650505050505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0080546001190161269557604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f6126a461500b565b5f6126ad611d0b565b90505f806126bd6112fd87611d7e565b9150915080156126e457604051632d07135360e01b815281151560048201526024016104cc565b5f828152600784016020526040808220815160e081019092528054829060ff16600581111561271557612715615260565b600581111561272657612726615260565b815260200160018201805461273a90615412565b80601f016020809104026020016040519081016040528092919081815260200182805461276690615412565b80156127b15780601f10612788576101008083540402835291602001916127b1565b820191905f5260205f20905b81548152906001019060200180831161279457829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561281c5761281c615260565b1415801561283d575060018151600581111561283a5761283a615260565b14155b1561285e57805160405163170cc93360e21b81526104cc919060040161544a565b60038151600581111561287357612873615260565b036128815760048152612886565b600581525b83600801816020015160405161289c9190615692565b90815260408051602092819003830190205f908190558581526007870190925290208151815483929190829060ff191660018360058111156128e0576128e0615260565b0217905550602082015160018201906128f990826156e7565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b031916919092161790558051600581111561299e5761299e615260565b60405184907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a39196919550909350505050565b5f6129de613cf7565b80546040516340c10f1960e01b81526001600160a01b038681166004830152602482018690529293509116906340c10f19906044015f604051808303815f87803b158015612a2a575f80fd5b505af1158015612a3c573d5f803e3d5ffd5b50505050505050565b6112c28282612a52613cf7565b546001600160a01b03169190613d1b565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f80612a93612462565b600281015490915061ffff600160401b90910481169086161080612abc575061271061ffff8616115b15612ae057604051635f12e6c360e11b815261ffff861660048201526024016104cc565b60028101546001600160401b039081169085161015612b1c576040516202a06d60e11b81526001600160401b03851660048201526024016104cc565b8054831080612b2e5750806001015483115b15612b4f5760405163222d164360e21b8152600481018490526024016104cc565b5f612b5984613d7a565b90505f612b6582610c5a565b90505f612b728983613d97565b90506040518060800160405280612b863390565b6001600160a01b03908116825261ffff808c166020808501919091526001600160401b03808d166040808701919091525f60609687018190528881526005909b018352998a902086518154938801519b8801518316600160b01b0267ffffffffffffffff60b01b199c909516600160a01b026001600160b01b0319909416951694909417919091179890981617815591015160019091018054919095166001600160401b0319909116179093555090915050949350505050565b5f612c49612462565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff166003811115612c8257612c82615260565b6003811115612c9357612c93615260565b8152815461010090046001600160a01b0316602082015260018201546040808301919091526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c090910152810151909150612d076142f4565b8260800151612d1691906158d4565b6001600160401b0316421015612d4a5760405163fb6ce63f60e01b81526001600160401b03421660048201526024016104cc565b5f848152600684016020908152604080832080546001600160a81b03191681556001810184905560020183905560078601909152812080549082905590808215612e05575f84815260058701602052604090205461271090612db790600160a01b900461ffff16856157eb565b612dc19190615802565b915081866008015f8681526020019081526020015f205f828254612de591906157b6565b90915550612df5905082846159f1565b9050612e058560200151826129d5565b612e1a8560200151610d548760600151610feb565b6040805182815260208101849052859189917f8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993910160405180910390a350505050505050565b5f805f8351603614612e9757835160405163cc92daa160e01b815263ffffffff9091166004820152603660248201526044016104cc565b5f805b6002811015612ee657612eae8160016159f1565b612eb99060086157eb565b61ffff16868281518110612ecf57612ecf6154e1565b016020015160f81c901b9190911790600101612e9a565b5061ffff811615612f105760405163407b587360e01b815261ffff821660048201526024016104cc565b5f805b6004811015612f6b57612f278160036159f1565b612f329060086157eb565b63ffffffff1687612f448360026157b6565b81518110612f5457612f546154e1565b016020015160f81c901b9190911790600101612f13565b5063ffffffff8116600314612f9357604051635b60892f60e01b815260040160405180910390fd5b5f805b6020811015612fe857612faa81601f6159f1565b612fb59060086157eb565b88612fc18360066157b6565b81518110612fd157612fd16154e1565b016020015160f81c901b9190911790600101612f96565b505f805b6008811015613047576130008160076159f1565b61300b9060086157eb565b6001600160401b0316896130208360266157b6565b81518110613030576130306154e1565b016020015160f81c901b9190911790600101612fec565b505f805b60088110156130a65761305f8160076159f1565b61306a9060086157eb565b6001600160401b03168a61307f83602e6157b6565b8151811061308f5761308f6154e1565b016020015160f81c901b919091179060010161304b565b5091989097509095509350505050565b5f806130c0612462565b90505f6130cf61025385613d7a565b90505f6130db87611765565b90506130e6876121eb565b613106576040516330efa98b60e01b8152600481018890526024016104cc565b60028151600581111561311b5761311b615260565b1461313c57805160405163170cc93360e21b81526104cc919060040161544a565b5f82826080015161314d91906158d4565b905083600201600a9054906101000a90046001600160401b031682604001516131769190615add565b6001600160401b0316816001600160401b031611156131b357604051636d51fe0560e11b81526001600160401b03821660048201526024016104cc565b5f806131bf8a84613561565b915091505f8a836040516020016131ed92919091825260c01b6001600160c01b031916602082015260280190565b60408051601f19818403018152828252805160209091012060e08301909152915080600181526001600160a01b038c1660208083019190915260408083018f90526001600160401b03808b1660608501525f6080850181905290881660a085015260c090930183905284835260068b01909152902081518154829060ff1916600183600381111561328057613280615260565b02179055506020828101518254610100600160a81b0319166101006001600160a01b039283160217835560408085015160018501556060808601516002909501805460808089015160a08a015160c0909a01516001600160401b03998a166001600160801b031990941693909317600160401b918a1691909102176001600160801b0316600160801b998916999099026001600160c01b031698909817600160c01b91881691909102179055815189861681528a861694810194909452938b1690830152918101859052908c16918d9184917fb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426910160405180910390a49a9950505050505050505050565b5f8082516027146133c157825160405163cc92daa160e01b815263ffffffff9091166004820152602760248201526044016104cc565b5f805b6002811015613410576133d88160016159f1565b6133e39060086157eb565b61ffff168582815181106133f9576133f96154e1565b016020015160f81c901b91909117906001016133c4565b5061ffff81161561343a5760405163407b587360e01b815261ffff821660048201526024016104cc565b5f805b6004811015613495576134518160036159f1565b61345c9060086157eb565b63ffffffff168661346e8360026157b6565b8151811061347e5761347e6154e1565b016020015160f81c901b919091179060010161343d565b5063ffffffff81166002146134bd57604051635b60892f60e01b815260040160405180910390fd5b5f805b6020811015613512576134d481601f6159f1565b6134df9060086157eb565b876134eb8360066157b6565b815181106134fb576134fb6154e1565b016020015160f81c901b91909117906001016134c0565b505f86602681518110613527576135276154e1565b016020015191976001600160f81b03199092161515965090945050505050565b61354f61430f565b6135588261435a565b6112c2816143ce565b5f805f61356c611d0b565b5f868152600782016020526040902060020154909150600160801b90046001600160401b031661359c858261442a565b5f6135a68761464f565b5f8881526007850160205260408120600201805467ffffffffffffffff60801b1916600160801b6001600160401b038b16021790559091506005600160991b0163ee5b48eb6135f68a858b611d2f565b6040518263ffffffff1660e01b81526004016136129190615458565b6020604051808303815f875af115801561362e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613652919061546a565b604080516001600160401b038a811682526020820184905282519394508516928b927f07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df928290030190a3909450925050505b9250929050565b5f806136b5612462565b90505f6136c58460400151611765565b90505f6003825160058111156136dd576136dd615260565b14806136fb57506004825160058111156136f9576136f9615260565b145b1561370b575060c0810151613748565b60028251600581111561372057613720615260565b0361372c575042613748565b815160405163170cc93360e21b81526104cc919060040161544a565b84608001516001600160401b0316816001600160401b03161161376f57505f949350505050565b600483015460608601516001600160a01b0390911690634f22429f9061379490610feb565b60a085015160808901516040808b01515f90815260058a016020528190206001015490516001600160e01b031960e087901b1681526137e69493929188916001600160401b0390911690600401615aaf565b602060405180830381865afa158015613801573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613825919061546a565b95945050505050565b5f808251602e1461386457825160405163cc92daa160e01b815263ffffffff9091166004820152602e60248201526044016104cc565b5f805b60028110156138b35761387b8160016159f1565b6138869060086157eb565b61ffff1685828151811061389c5761389c6154e1565b016020015160f81c901b9190911790600101613867565b5061ffff8116156138dd5760405163407b587360e01b815261ffff821660048201526024016104cc565b5f805b6004811015613938576138f48160036159f1565b6138ff9060086157eb565b63ffffffff16866139118360026157b6565b81518110613921576139216154e1565b016020015160f81c901b91909117906001016138e0565b5063ffffffff81161561395e57604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156139b35761397581601f6159f1565b6139809060086157eb565b8761398c8360066157b6565b8151811061399c5761399c6154e1565b016020015160f81c901b9190911790600101613961565b505f805b6008811015613a12576139cb8160076159f1565b6139d69060086157eb565b6001600160401b0316886139eb8360266157b6565b815181106139fb576139fb6154e1565b016020015160f81c901b91909117906001016139b7565b5090969095509350505050565b613a2761500b565b5f613a30611d0b565b5f848152600782016020526040808220815160e0810190925280549394509192909190829060ff166005811115613a6957613a69615260565b6005811115613a7a57613a7a615260565b8152602001600182018054613a8e90615412565b80601f0160208091040260200160405190810160405280929190818152602001828054613aba90615412565b8015613b055780601f10613adc57610100808354040283529160200191613b05565b820191905f5260205f20905b815481529060010190602001808311613ae857829003601f168201915b50505091835250506002828101546001600160401b038082166020850152600160401b820481166040850152600160801b820481166060850152600160c01b9091048116608084015260039093015490921660a09091015290915081516005811115613b7357613b73615260565b14613ba6575f8481526007830160205260409081902054905163170cc93360e21b81526104cc9160ff169060040161544a565b60038152426001600160401b031660c08201525f84815260078301602052604090208151815483929190829060ff19166001836005811115613bea57613bea615260565b021790555060208201516001820190613c0390826156e7565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b031916919092161790555f613ca08582613561565b6080840151604080516001600160401b03909216825242602083015291935083925087917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a3509392505050565b7f6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab0090565b6040516001600160a01b038381166024830152604482018390526104d591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506146b8565b5f610ca882613d87613cf7565b546001600160a01b031690614710565b5f613da0611d0b565b6009015460ff16613dc457604051637fab81e560e01b815260040160405180910390fd5b5f613dcd611d0b565b905042613de06060860160408701615213565b6001600160401b0316111580613e1a5750613dfe6202a300426157b6565b613e0e6060860160408701615213565b6001600160401b031610155b15613e5457613e2f6060850160408601615213565b604051635879da1360e11b81526001600160401b0390911660048201526024016104cc565b613e69613e646060860186615b08565b614871565b613e79613e646080860186615b08565b6030613e886020860186615a04565b905014613eba57613e9c6020850185615a04565b6040516326475b2f60e11b81526104cc925060040190815260200190565b613ec48480615a04565b90505f03613ef157613ed68480615a04565b604051633e08a12560e11b81526004016104cc929190615b1c565b5f60088201613f008680615a04565b604051613f0e9291906158c5565b90815260200160405180910390205414613f4757613f2c8480615a04565b60405163a41f772f60e01b81526004016104cc929190615b1c565b613f51835f61442a565b6040805160e08101909152815481525f90819061405d9060208101613f768980615a04565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250602090810190613fbe908a018a615a04565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060200161400760608a0160408b01615213565b6001600160401b0316815260200161402260608a018a615b08565b61402b90615b4a565b815260200161403d60808a018a615b08565b61404690615b4a565b8152602001876001600160401b03168152506149da565b5f8281526006860160205260409020919350915061407b82826156e7565b50816008840161408b8880615a04565b6040516140999291906158c5565b9081526040519081900360200181209190915563ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906140d5908590600401615458565b6020604051808303815f875af11580156140f1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614115919061546a565b6040805160e0810190915290915080600181526020016141358980615a04565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509385525050506001600160401b0389166020808401829052604080850184905260608501929092526080840183905260a0909301829052868252600788019092522081518154829060ff191660018360058111156141c4576141c4615260565b0217905550602082015160018201906141dd90826156e7565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b031916919092161790558061427a8880615a04565b6040516142889291906158c5565b6040518091039020847fb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430898b60400160208101906142c69190615213565b604080516001600160401b0393841681529290911660208301520160405180910390a4509095945050505050565b5f6142fd611d0b565b600101546001600160401b0316919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661435857604051631afcd79f60e31b815260040160405180910390fd5b565b61436261430f565b61436b81614bc7565b614373614be0565b610d666060820135608083013561439060c0850160a08601615213565b6143a060e0860160c08701615c11565b6143b1610100870160e08801615c2a565b6101008701356143c961014089016101208a01615481565b614bf0565b6143d661430f565b5f6143df613cf7565b90506001600160a01b03821661440a5781604051637330680360e01b81526004016104cc919061524c565b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f614433611d0b565b90505f826001600160401b0316846001600160401b031611156144615761445a83856158f4565b905061446e565b61446b84846158f4565b90505b6040805160808101825260028401548082526003850154602083015260048501549282019290925260058401546001600160401b03166060820152429115806144d05750600184015481516144cc916001600160401b0316906157b6565b8210155b156144f6576001600160401b038316606082015281815260408101516020820152614515565b828160600181815161450891906158d4565b6001600160401b03169052505b6060810151614525906064615add565b602082015160018601546001600160401b0392909216916145509190600160401b900460ff166157eb565b101561458057606081015160405163dfae880160e01b81526001600160401b0390911660048201526024016104cc565b856001600160401b03168160400181815161459b91906157b6565b9052506040810180516001600160401b03871691906145bb9083906159f1565b905250600184015460408201516064916145e091600160401b90910460ff16906157eb565b1015614607578060400151604051635943317f60e01b81526004016104cc91815260200190565b80516002850155602081015160038501556040810151600485015560600151600590930180546001600160401b0319166001600160401b039094169390931790925550505050565b5f80614659611d0b565b5f848152600782016020526040902060020180549192509060089061468d90600160401b90046001600160401b0316615c4a565b91906101000a8154816001600160401b0302191690836001600160401b031602179055915050919050565b5f6146cc6001600160a01b03841683614d86565b905080515f141580156146f05750808060200190518101906146ee9190615c65565b155b156104d55782604051635274afe760e01b81526004016104cc919061524c565b5f80836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161473e919061524c565b602060405180830381865afa158015614759573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061477d919061546a565b90506147946001600160a01b038516333086614d93565b6040516370a0823160e01b81525f906001600160a01b038616906370a08231906147c290309060040161524c565b602060405180830381865afa1580156147dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614801919061546a565b90508181116148675760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b60648201526084016104cc565b61382582826159f1565b61487e6020820182615146565b63ffffffff1615801561489e5750614899602082018261549c565b151590505b156148e5576148b06020820182615146565b6148bd602083018361549c565b60405163c08a0f1d60e01b815263ffffffff90931660048401526024830152506044016104cc565b6148f2602082018261549c565b90506149016020830183615146565b63ffffffff16111561491a576148b06020820182615146565b60015b61492a602083018361549c565b90508110156112c257614940602083018361549c565b61494b6001846159f1565b81811061495a5761495a6154e1565b905060200201602081019061496f9190615481565b6001600160a01b0316614985602084018461549c565b83818110614995576149956154e1565b90506020020160208101906149aa9190615481565b6001600160a01b031610156149d257604051630dbc8d5f60e31b815260040160405180910390fd5b60010161491d565b5f6060826040015151603014614a035760405163180ffa0d60e01b815260040160405180910390fd5b82516020808501518051604080880151606089015160808a01518051908701515193515f98614a44988a986001989297929690959094909390929101615c80565b60405160208183030381529060405290505f5b84608001516020015151811015614ab657818560800151602001518281518110614a8357614a836154e1565b6020026020010151604051602001614a9c929190615d3a565b60408051601f198184030181529190529150600101614a57565b5060a0840151805160209182015151604051614ad6938593929101615d6b565b60405160208183030381529060405290505f5b8460a001516020015151811015614b4857818560a00151602001518281518110614b1557614b156154e1565b6020026020010151604051602001614b2e929190615d3a565b60408051601f198184030181529190529150600101614ae9565b5060c0840151604051614b5f918391602001615da6565b6040516020818303038152906040529050600281604051614b809190615692565b602060405180830381855afa158015614b9b573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190614bbe919061546a565b94909350915050565b614bcf61430f565b614bd7614dcc565b610d6681614dd4565b614be861430f565b614358614eb7565b614bf861430f565b5f614c01612462565b905061ffff85161580614c19575061271061ffff8616115b15614c3d57604051635f12e6c360e11b815261ffff861660048201526024016104cc565b86881115614c615760405163222d164360e21b8152600481018990526024016104cc565b60ff84161580614c745750600a60ff8516115b15614c975760405163170db35960e31b815260ff851660048201526024016104cc565b614c9f6142f4565b6001600160401b0316866001600160401b03161015614cdb576040516202a06d60e11b81526001600160401b03871660048201526024016104cc565b825f03614cfb5760405163a733007160e01b815260040160405180910390fd5b96875560018701959095556002860180546001600160401b039590951669ffffffffffffffffffff1990951694909417600160401b61ffff94909416939093029290921767ffffffffffffffff60501b191660ff91909116600160501b02179091556003830155600490910180546001600160a01b0319166001600160a01b03909216919091179055565b6060611d0483835f614ebf565b6040516001600160a01b0384811660248301528381166044830152606482018390526106d79186918216906323b872dd90608401613d48565b61435861430f565b614ddc61430f565b5f614de5611d0b565b8235815590506014614dfd6060840160408501615c2a565b60ff161180614e1c5750614e176060830160408401615c2a565b60ff16155b15614e5057614e316060830160408401615c2a565b604051634a59bbff60e11b815260ff90911660048201526024016104cc565b614e606060830160408401615c2a565b60018201805460ff92909216600160401b0260ff60401b19909216919091179055614e916040830160208401615213565b60019190910180546001600160401b0319166001600160401b0390921691909117905550565b612a6361430f565b606081471015614ee4573060405163cd78605960e01b81526004016104cc919061524c565b5f80856001600160a01b03168486604051614eff9190615692565b5f6040518083038185875af1925050503d805f8114614f39576040519150601f19603f3d011682016040523d82523d5f602084013e614f3e565b606091505b5091509150614f4e868383614f58565b9695505050505050565b606082614f6d57614f6882614fab565b611d04565b8151158015614f8457506001600160a01b0384163b155b15614fa45783604051639996b31560e01b81526004016104cc919061524c565b5080611d04565b805115614fbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054614fe090615412565b5f825580601f10614fef575050565b601f0160209004905f5260205f2090810190610d669190615048565b6040805160e08101909152805f81526060602082018190525f604083018190529082018190526080820181905260a0820181905260c09091015290565b5b8082111561505c575f8155600101615049565b5090565b8015158114610d66575f80fd5b803563ffffffff81168114615080575f80fd5b919050565b5f805f60608486031215615097575f80fd5b8335925060208401356150a981615060565b91506150b76040850161506d565b90509250925092565b5f602082840312156150d0575f80fd5b5035919050565b5f80604083850312156150e8575f80fd5b82356001600160401b038111156150fd575f80fd5b83016080818603121561510e575f80fd5b915061511c6020840161506d565b90509250929050565b5f8060408385031215615136575f80fd5b8235915061511c6020840161506d565b5f60208284031215615156575f80fd5b611d048261506d565b803561ffff81168114615080575f80fd5b80356001600160401b0381168114615080575f80fd5b5f805f8060808587031215615199575f80fd5b84356001600160401b038111156151ae575f80fd5b850160a081880312156151bf575f80fd5b93506151cd6020860161515f565b92506151db60408601615170565b9396929550929360600135925050565b5f80604083850312156151fc575f80fd5b6152058361506d565b946020939093013593505050565b5f60208284031215615223575f80fd5b611d0482615170565b5f806040838503121561523d575f80fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52602160045260245ffd5b6006811061528457615284615260565b9052565b5f5b838110156152a257818101518382015260200161528a565b50505f910152565b5f81518084526152c1816020860160208601615288565b601f01601f19169290920160200192915050565b602081526152e7602082018351615274565b5f602083015160e060408401526153026101008401826152aa565b905060408401516001600160401b0380821660608601528060608701511660808601528060808701511660a08601528060a08701511660c08601528060c08701511660e086015250508091505092915050565b6001600160a01b0381168114610d66575f80fd5b5f8082840361016081121561537c575f80fd5b6101408082121561538b575f80fd5b849350830135905061539c81615355565b809150509250929050565b5f80602083850312156153b8575f80fd5b82356001600160401b03808211156153ce575f80fd5b818501915085601f8301126153e1575f80fd5b8135818111156153ef575f80fd5b866020828501011115615400575f80fd5b60209290920196919550909350505050565b600181811c9082168061542657607f821691505b60208210810361544457634e487b7160e01b5f52602260045260245ffd5b50919050565b60208101610ca88284615274565b602081525f611d0460208301846152aa565b5f6020828403121561547a575f80fd5b5051919050565b5f60208284031215615491575f80fd5b8135611d0481615355565b5f808335601e198436030181126154b1575f80fd5b8301803591506001600160401b038211156154ca575f80fd5b6020019150600581901b36038213156136a4575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112615509575f80fd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561554957615549615513565b60405290565b604080519081016001600160401b038111828210171561554957615549615513565b604051601f8201601f191681016001600160401b038111828210171561559957615599615513565b604052919050565b5f6001600160401b038211156155b9576155b9615513565b50601f01601f191660200190565b5f82601f8301126155d6575f80fd5b81356155e96155e4826155a1565b615571565b8181528460208386010111156155fd575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608236031215615629575f80fd5b615631615527565b82356001600160401b0380821115615647575f80fd5b615653368387016155c7565b83526020850135915080821115615668575f80fd5b50615675368286016155c7565b60208301525061568760408401615170565b604082015292915050565b5f8251615509818460208701615288565b601f8211156104d557805f5260205f20601f840160051c810160208510156156c85750805b601f840160051c820191505b81811015611641575f81556001016156d4565b81516001600160401b0381111561570057615700615513565b6157148161570e8454615412565b846156a3565b602080601f831160018114615747575f84156157305750858301515b5f19600386901b1c1916600185901b178555610eb4565b5f85815260208120601f198616915b8281101561577557888601518255948401946001909101908401615756565b508582101561579257878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610ca857610ca86157a2565b5f63ffffffff8083168181036157e1576157e16157a2565b6001019392505050565b8082028115828204841417610ca857610ca86157a2565b5f8261581c57634e487b7160e01b5f52601260045260245ffd5b500490565b602081016004831061583557615835615260565b91905290565b5f60208083525f845461584d81615412565b806020870152604060018084165f811461586e576001811461588a576158b7565b60ff19851660408a0152604084151560051b8a010195506158b7565b895f5260205f205f5b858110156158ae5781548b8201860152908301908801615893565b8a016040019650505b509398975050505050505050565b818382375f9101908152919050565b6001600160401b03818116838216019080821115611e8257611e826157a2565b6001600160401b03828116828216039080821115611e8257611e826157a2565b805161508081615060565b5f8060408385031215615930575f80fd5b82516001600160401b0380821115615946575f80fd5b9084019060608287031215615959575f80fd5b615961615527565b8251815260208084015161597481615355565b82820152604084015183811115615989575f80fd5b80850194505087601f85011261599d575f80fd5b835192506159ad6155e4846155a1565b83815288828587010111156159c0575f80fd5b6159cf84838301848801615288565b806040840152508195506159e4818801615914565b9450505050509250929050565b81810381811115610ca857610ca86157a2565b5f808335601e19843603018112615a19575f80fd5b8301803591506001600160401b03821115615a32575f80fd5b6020019150368190038213156136a4575f80fd5b5f8851615a57818460208d01615288565b60e089901b6001600160e01b031916908301908152868860048301378681019050600481015f8152858782375060c09390931b6001600160c01b0319166004939094019283019390935250600c019695505050505050565b9485526001600160401b03938416602086015291831660408501528216606084015216608082015260a00190565b6001600160401b03818116838216028082169190828114615b0057615b006157a2565b505092915050565b5f8235603e19833603018112615509575f80fd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60408236031215615b5a575f80fd5b615b6261554f565b615b6b8361506d565b81526020808401356001600160401b0380821115615b87575f80fd5b9085019036601f830112615b99575f80fd5b813581811115615bab57615bab615513565b8060051b9150615bbc848301615571565b8181529183018401918481019036841115615bd5575f80fd5b938501935b83851015615bff5784359250615bef83615355565b8282529385019390850190615bda565b94860194909452509295945050505050565b5f60208284031215615c21575f80fd5b611d048261515f565b5f60208284031215615c3a575f80fd5b813560ff81168114611d04575f80fd5b5f6001600160401b038083168181036157e1576157e16157a2565b5f60208284031215615c75575f80fd5b8151611d0481615060565b61ffff60f01b8a60f01b1681525f63ffffffff60e01b808b60e01b166002840152896006840152808960e01b166026840152508651615cc681602a850160208b01615288565b865190830190615cdd81602a840160208b01615288565b60c087901b6001600160c01b031916602a9290910191820152615d0f603282018660e01b6001600160e01b0319169052565b615d28603682018560e01b6001600160e01b0319169052565b603a019b9a5050505050505050505050565b5f8351615d4b818460208801615288565b60609390931b6001600160601b0319169190920190815260140192915050565b5f8451615d7c818460208901615288565b6001600160e01b031960e095861b8116919093019081529290931b16600482015260080192915050565b5f8351615db7818460208801615288565b60c09390931b6001600160c01b031916919092019081526008019291505056fea164736f6c6343000819000a", +} + +// ERC20TokenStakingManagerABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC20TokenStakingManagerMetaData.ABI instead. +var ERC20TokenStakingManagerABI = ERC20TokenStakingManagerMetaData.ABI + +// ERC20TokenStakingManagerBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ERC20TokenStakingManagerMetaData.Bin instead. +var ERC20TokenStakingManagerBin = ERC20TokenStakingManagerMetaData.Bin + +// DeployERC20TokenStakingManager deploys a new Ethereum contract, binding an instance of ERC20TokenStakingManager to it. +func DeployERC20TokenStakingManager(auth *bind.TransactOpts, backend bind.ContractBackend, init uint8) (common.Address, *types.Transaction, *ERC20TokenStakingManager, error) { + parsed, err := ERC20TokenStakingManagerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ERC20TokenStakingManagerBin), backend, init) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ERC20TokenStakingManager{ERC20TokenStakingManagerCaller: ERC20TokenStakingManagerCaller{contract: contract}, ERC20TokenStakingManagerTransactor: ERC20TokenStakingManagerTransactor{contract: contract}, ERC20TokenStakingManagerFilterer: ERC20TokenStakingManagerFilterer{contract: contract}}, nil +} + +// ERC20TokenStakingManager is an auto generated Go binding around an Ethereum contract. +type ERC20TokenStakingManager struct { + ERC20TokenStakingManagerCaller // Read-only binding to the contract + ERC20TokenStakingManagerTransactor // Write-only binding to the contract + ERC20TokenStakingManagerFilterer // Log filterer for contract events +} + +// ERC20TokenStakingManagerCaller is an auto generated read-only Go binding around an Ethereum contract. +type ERC20TokenStakingManagerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20TokenStakingManagerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC20TokenStakingManagerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20TokenStakingManagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC20TokenStakingManagerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20TokenStakingManagerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC20TokenStakingManagerSession struct { + Contract *ERC20TokenStakingManager // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20TokenStakingManagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC20TokenStakingManagerCallerSession struct { + Contract *ERC20TokenStakingManagerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ERC20TokenStakingManagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC20TokenStakingManagerTransactorSession struct { + Contract *ERC20TokenStakingManagerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20TokenStakingManagerRaw is an auto generated low-level Go binding around an Ethereum contract. +type ERC20TokenStakingManagerRaw struct { + Contract *ERC20TokenStakingManager // Generic contract binding to access the raw methods on +} + +// ERC20TokenStakingManagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC20TokenStakingManagerCallerRaw struct { + Contract *ERC20TokenStakingManagerCaller // Generic read-only contract binding to access the raw methods on +} + +// ERC20TokenStakingManagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC20TokenStakingManagerTransactorRaw struct { + Contract *ERC20TokenStakingManagerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewERC20TokenStakingManager creates a new instance of ERC20TokenStakingManager, bound to a specific deployed contract. +func NewERC20TokenStakingManager(address common.Address, backend bind.ContractBackend) (*ERC20TokenStakingManager, error) { + contract, err := bindERC20TokenStakingManager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManager{ERC20TokenStakingManagerCaller: ERC20TokenStakingManagerCaller{contract: contract}, ERC20TokenStakingManagerTransactor: ERC20TokenStakingManagerTransactor{contract: contract}, ERC20TokenStakingManagerFilterer: ERC20TokenStakingManagerFilterer{contract: contract}}, nil +} + +// NewERC20TokenStakingManagerCaller creates a new read-only instance of ERC20TokenStakingManager, bound to a specific deployed contract. +func NewERC20TokenStakingManagerCaller(address common.Address, caller bind.ContractCaller) (*ERC20TokenStakingManagerCaller, error) { + contract, err := bindERC20TokenStakingManager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerCaller{contract: contract}, nil +} + +// NewERC20TokenStakingManagerTransactor creates a new write-only instance of ERC20TokenStakingManager, bound to a specific deployed contract. +func NewERC20TokenStakingManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*ERC20TokenStakingManagerTransactor, error) { + contract, err := bindERC20TokenStakingManager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerTransactor{contract: contract}, nil +} + +// NewERC20TokenStakingManagerFilterer creates a new log filterer instance of ERC20TokenStakingManager, bound to a specific deployed contract. +func NewERC20TokenStakingManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*ERC20TokenStakingManagerFilterer, error) { + contract, err := bindERC20TokenStakingManager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerFilterer{contract: contract}, nil +} + +// bindERC20TokenStakingManager binds a generic wrapper to an already deployed contract. +func bindERC20TokenStakingManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC20TokenStakingManagerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20TokenStakingManager.Contract.ERC20TokenStakingManagerCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ERC20TokenStakingManagerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ERC20TokenStakingManagerTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20TokenStakingManager.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.contract.Transact(opts, method, params...) +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) ADDRESSLENGTH(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "ADDRESS_LENGTH") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ADDRESSLENGTH() (uint32, error) { + return _ERC20TokenStakingManager.Contract.ADDRESSLENGTH(&_ERC20TokenStakingManager.CallOpts) +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) ADDRESSLENGTH() (uint32, error) { + return _ERC20TokenStakingManager.Contract.ADDRESSLENGTH(&_ERC20TokenStakingManager.CallOpts) +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) BIPSCONVERSIONFACTOR(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "BIPS_CONVERSION_FACTOR") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) BIPSCONVERSIONFACTOR() (uint16, error) { + return _ERC20TokenStakingManager.Contract.BIPSCONVERSIONFACTOR(&_ERC20TokenStakingManager.CallOpts) +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) BIPSCONVERSIONFACTOR() (uint16, error) { + return _ERC20TokenStakingManager.Contract.BIPSCONVERSIONFACTOR(&_ERC20TokenStakingManager.CallOpts) +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) BLSPUBLICKEYLENGTH(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "BLS_PUBLIC_KEY_LENGTH") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) BLSPUBLICKEYLENGTH() (uint8, error) { + return _ERC20TokenStakingManager.Contract.BLSPUBLICKEYLENGTH(&_ERC20TokenStakingManager.CallOpts) +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) BLSPUBLICKEYLENGTH() (uint8, error) { + return _ERC20TokenStakingManager.Contract.BLSPUBLICKEYLENGTH(&_ERC20TokenStakingManager.CallOpts) +} + +// ERC20STAKINGMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xe4a63c40. +// +// Solidity: function ERC20_STAKING_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) ERC20STAKINGMANAGERSTORAGELOCATION(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "ERC20_STAKING_MANAGER_STORAGE_LOCATION") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ERC20STAKINGMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xe4a63c40. +// +// Solidity: function ERC20_STAKING_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ERC20STAKINGMANAGERSTORAGELOCATION() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.ERC20STAKINGMANAGERSTORAGELOCATION(&_ERC20TokenStakingManager.CallOpts) +} + +// ERC20STAKINGMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xe4a63c40. +// +// Solidity: function ERC20_STAKING_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) ERC20STAKINGMANAGERSTORAGELOCATION() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.ERC20STAKINGMANAGERSTORAGELOCATION(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) MAXIMUMCHURNPERCENTAGELIMIT(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "MAXIMUM_CHURN_PERCENTAGE_LIMIT") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) MAXIMUMCHURNPERCENTAGELIMIT() (uint8, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMCHURNPERCENTAGELIMIT(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) MAXIMUMCHURNPERCENTAGELIMIT() (uint8, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMCHURNPERCENTAGELIMIT(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMDELEGATIONFEEBIPS is a free data retrieval call binding the contract method 0x35455ded. +// +// Solidity: function MAXIMUM_DELEGATION_FEE_BIPS() view returns(uint16) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) MAXIMUMDELEGATIONFEEBIPS(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "MAXIMUM_DELEGATION_FEE_BIPS") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// MAXIMUMDELEGATIONFEEBIPS is a free data retrieval call binding the contract method 0x35455ded. +// +// Solidity: function MAXIMUM_DELEGATION_FEE_BIPS() view returns(uint16) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) MAXIMUMDELEGATIONFEEBIPS() (uint16, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMDELEGATIONFEEBIPS(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMDELEGATIONFEEBIPS is a free data retrieval call binding the contract method 0x35455ded. +// +// Solidity: function MAXIMUM_DELEGATION_FEE_BIPS() view returns(uint16) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) MAXIMUMDELEGATIONFEEBIPS() (uint16, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMDELEGATIONFEEBIPS(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) MAXIMUMREGISTRATIONEXPIRYLENGTH(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "MAXIMUM_REGISTRATION_EXPIRY_LENGTH") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) MAXIMUMREGISTRATIONEXPIRYLENGTH() (uint64, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMREGISTRATIONEXPIRYLENGTH(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) MAXIMUMREGISTRATIONEXPIRYLENGTH() (uint64, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMREGISTRATIONEXPIRYLENGTH(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMSTAKEMULTIPLIERLIMIT is a free data retrieval call binding the contract method 0x151d30d1. +// +// Solidity: function MAXIMUM_STAKE_MULTIPLIER_LIMIT() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) MAXIMUMSTAKEMULTIPLIERLIMIT(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "MAXIMUM_STAKE_MULTIPLIER_LIMIT") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// MAXIMUMSTAKEMULTIPLIERLIMIT is a free data retrieval call binding the contract method 0x151d30d1. +// +// Solidity: function MAXIMUM_STAKE_MULTIPLIER_LIMIT() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) MAXIMUMSTAKEMULTIPLIERLIMIT() (uint8, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMSTAKEMULTIPLIERLIMIT(&_ERC20TokenStakingManager.CallOpts) +} + +// MAXIMUMSTAKEMULTIPLIERLIMIT is a free data retrieval call binding the contract method 0x151d30d1. +// +// Solidity: function MAXIMUM_STAKE_MULTIPLIER_LIMIT() view returns(uint8) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) MAXIMUMSTAKEMULTIPLIERLIMIT() (uint8, error) { + return _ERC20TokenStakingManager.Contract.MAXIMUMSTAKEMULTIPLIERLIMIT(&_ERC20TokenStakingManager.CallOpts) +} + +// POSVALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xafb98096. +// +// Solidity: function POS_VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) POSVALIDATORMANAGERSTORAGELOCATION(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "POS_VALIDATOR_MANAGER_STORAGE_LOCATION") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// POSVALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xafb98096. +// +// Solidity: function POS_VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) POSVALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.POSVALIDATORMANAGERSTORAGELOCATION(&_ERC20TokenStakingManager.CallOpts) +} + +// POSVALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xafb98096. +// +// Solidity: function POS_VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) POSVALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.POSVALIDATORMANAGERSTORAGELOCATION(&_ERC20TokenStakingManager.CallOpts) +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) PCHAINBLOCKCHAINID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "P_CHAIN_BLOCKCHAIN_ID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) PCHAINBLOCKCHAINID() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.PCHAINBLOCKCHAINID(&_ERC20TokenStakingManager.CallOpts) +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) PCHAINBLOCKCHAINID() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.PCHAINBLOCKCHAINID(&_ERC20TokenStakingManager.CallOpts) +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) VALIDATORMANAGERSTORAGELOCATION(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "VALIDATOR_MANAGER_STORAGE_LOCATION") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) VALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.VALIDATORMANAGERSTORAGELOCATION(&_ERC20TokenStakingManager.CallOpts) +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) VALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.VALIDATORMANAGERSTORAGELOCATION(&_ERC20TokenStakingManager.CallOpts) +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) WARPMESSENGER(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "WARP_MESSENGER") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) WARPMESSENGER() (common.Address, error) { + return _ERC20TokenStakingManager.Contract.WARPMESSENGER(&_ERC20TokenStakingManager.CallOpts) +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) WARPMESSENGER() (common.Address, error) { + return _ERC20TokenStakingManager.Contract.WARPMESSENGER(&_ERC20TokenStakingManager.CallOpts) +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) GetValidator(opts *bind.CallOpts, validationID [32]byte) (Validator, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "getValidator", validationID) + + if err != nil { + return *new(Validator), err + } + + out0 := *abi.ConvertType(out[0], new(Validator)).(*Validator) + + return out0, err + +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) GetValidator(validationID [32]byte) (Validator, error) { + return _ERC20TokenStakingManager.Contract.GetValidator(&_ERC20TokenStakingManager.CallOpts, validationID) +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) GetValidator(validationID [32]byte) (Validator, error) { + return _ERC20TokenStakingManager.Contract.GetValidator(&_ERC20TokenStakingManager.CallOpts, validationID) +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) GetWeight(opts *bind.CallOpts, validationID [32]byte) (uint64, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "getWeight", validationID) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) GetWeight(validationID [32]byte) (uint64, error) { + return _ERC20TokenStakingManager.Contract.GetWeight(&_ERC20TokenStakingManager.CallOpts, validationID) +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) GetWeight(validationID [32]byte) (uint64, error) { + return _ERC20TokenStakingManager.Contract.GetWeight(&_ERC20TokenStakingManager.CallOpts, validationID) +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) RegisteredValidators(opts *bind.CallOpts, nodeID []byte) ([32]byte, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "registeredValidators", nodeID) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) RegisteredValidators(nodeID []byte) ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.RegisteredValidators(&_ERC20TokenStakingManager.CallOpts, nodeID) +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) RegisteredValidators(nodeID []byte) ([32]byte, error) { + return _ERC20TokenStakingManager.Contract.RegisteredValidators(&_ERC20TokenStakingManager.CallOpts, nodeID) +} + +// ValueToWeight is a free data retrieval call binding the contract method 0x2e2194d8. +// +// Solidity: function valueToWeight(uint256 value) view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) ValueToWeight(opts *bind.CallOpts, value *big.Int) (uint64, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "valueToWeight", value) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// ValueToWeight is a free data retrieval call binding the contract method 0x2e2194d8. +// +// Solidity: function valueToWeight(uint256 value) view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ValueToWeight(value *big.Int) (uint64, error) { + return _ERC20TokenStakingManager.Contract.ValueToWeight(&_ERC20TokenStakingManager.CallOpts, value) +} + +// ValueToWeight is a free data retrieval call binding the contract method 0x2e2194d8. +// +// Solidity: function valueToWeight(uint256 value) view returns(uint64) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) ValueToWeight(value *big.Int) (uint64, error) { + return _ERC20TokenStakingManager.Contract.ValueToWeight(&_ERC20TokenStakingManager.CallOpts, value) +} + +// WeightToValue is a free data retrieval call binding the contract method 0x62065856. +// +// Solidity: function weightToValue(uint64 weight) view returns(uint256) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCaller) WeightToValue(opts *bind.CallOpts, weight uint64) (*big.Int, error) { + var out []interface{} + err := _ERC20TokenStakingManager.contract.Call(opts, &out, "weightToValue", weight) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// WeightToValue is a free data retrieval call binding the contract method 0x62065856. +// +// Solidity: function weightToValue(uint64 weight) view returns(uint256) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) WeightToValue(weight uint64) (*big.Int, error) { + return _ERC20TokenStakingManager.Contract.WeightToValue(&_ERC20TokenStakingManager.CallOpts, weight) +} + +// WeightToValue is a free data retrieval call binding the contract method 0x62065856. +// +// Solidity: function weightToValue(uint64 weight) view returns(uint256) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerCallerSession) WeightToValue(weight uint64) (*big.Int, error) { + return _ERC20TokenStakingManager.Contract.WeightToValue(&_ERC20TokenStakingManager.CallOpts, weight) +} + +// ClaimDelegationFees is a paid mutator transaction binding the contract method 0x93e24598. +// +// Solidity: function claimDelegationFees(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) ClaimDelegationFees(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "claimDelegationFees", validationID) +} + +// ClaimDelegationFees is a paid mutator transaction binding the contract method 0x93e24598. +// +// Solidity: function claimDelegationFees(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ClaimDelegationFees(validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ClaimDelegationFees(&_ERC20TokenStakingManager.TransactOpts, validationID) +} + +// ClaimDelegationFees is a paid mutator transaction binding the contract method 0x93e24598. +// +// Solidity: function claimDelegationFees(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) ClaimDelegationFees(validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ClaimDelegationFees(&_ERC20TokenStakingManager.TransactOpts, validationID) +} + +// CompleteDelegatorRegistration is a paid mutator transaction binding the contract method 0x5297fae6. +// +// Solidity: function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) CompleteDelegatorRegistration(opts *bind.TransactOpts, messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "completeDelegatorRegistration", messageIndex, delegationID) +} + +// CompleteDelegatorRegistration is a paid mutator transaction binding the contract method 0x5297fae6. +// +// Solidity: function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) CompleteDelegatorRegistration(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteDelegatorRegistration(&_ERC20TokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteDelegatorRegistration is a paid mutator transaction binding the contract method 0x5297fae6. +// +// Solidity: function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) CompleteDelegatorRegistration(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteDelegatorRegistration(&_ERC20TokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteEndDelegation is a paid mutator transaction binding the contract method 0x98f3e2b4. +// +// Solidity: function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) CompleteEndDelegation(opts *bind.TransactOpts, messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "completeEndDelegation", messageIndex, delegationID) +} + +// CompleteEndDelegation is a paid mutator transaction binding the contract method 0x98f3e2b4. +// +// Solidity: function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) CompleteEndDelegation(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteEndDelegation(&_ERC20TokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteEndDelegation is a paid mutator transaction binding the contract method 0x98f3e2b4. +// +// Solidity: function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) CompleteEndDelegation(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteEndDelegation(&_ERC20TokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) CompleteEndValidation(opts *bind.TransactOpts, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "completeEndValidation", messageIndex) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) CompleteEndValidation(messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteEndValidation(&_ERC20TokenStakingManager.TransactOpts, messageIndex) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) CompleteEndValidation(messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteEndValidation(&_ERC20TokenStakingManager.TransactOpts, messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) CompleteValidatorRegistration(opts *bind.TransactOpts, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "completeValidatorRegistration", messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) CompleteValidatorRegistration(messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteValidatorRegistration(&_ERC20TokenStakingManager.TransactOpts, messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) CompleteValidatorRegistration(messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.CompleteValidatorRegistration(&_ERC20TokenStakingManager.TransactOpts, messageIndex) +} + +// ForceInitializeEndDelegation is a paid mutator transaction binding the contract method 0x1ec44724. +// +// Solidity: function forceInitializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) ForceInitializeEndDelegation(opts *bind.TransactOpts, delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "forceInitializeEndDelegation", delegationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndDelegation is a paid mutator transaction binding the contract method 0x1ec44724. +// +// Solidity: function forceInitializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ForceInitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ForceInitializeEndDelegation(&_ERC20TokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndDelegation is a paid mutator transaction binding the contract method 0x1ec44724. +// +// Solidity: function forceInitializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) ForceInitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ForceInitializeEndDelegation(&_ERC20TokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndValidation is a paid mutator transaction binding the contract method 0x3a1cfff6. +// +// Solidity: function forceInitializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) ForceInitializeEndValidation(opts *bind.TransactOpts, validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "forceInitializeEndValidation", validationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndValidation is a paid mutator transaction binding the contract method 0x3a1cfff6. +// +// Solidity: function forceInitializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ForceInitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ForceInitializeEndValidation(&_ERC20TokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndValidation is a paid mutator transaction binding the contract method 0x3a1cfff6. +// +// Solidity: function forceInitializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) ForceInitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ForceInitializeEndValidation(&_ERC20TokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf74c607b. +// +// Solidity: function initialize(((bytes32,uint64,uint8),uint256,uint256,uint64,uint16,uint8,uint256,address) settings, address token) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) Initialize(opts *bind.TransactOpts, settings PoSValidatorManagerSettings, token common.Address) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "initialize", settings, token) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf74c607b. +// +// Solidity: function initialize(((bytes32,uint64,uint8),uint256,uint256,uint64,uint16,uint8,uint256,address) settings, address token) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) Initialize(settings PoSValidatorManagerSettings, token common.Address) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.Initialize(&_ERC20TokenStakingManager.TransactOpts, settings, token) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf74c607b. +// +// Solidity: function initialize(((bytes32,uint64,uint8),uint256,uint256,uint64,uint16,uint8,uint256,address) settings, address token) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) Initialize(settings PoSValidatorManagerSettings, token common.Address) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.Initialize(&_ERC20TokenStakingManager.TransactOpts, settings, token) +} + +// InitializeDelegatorRegistration is a paid mutator transaction binding the contract method 0x9e1bc4ef. +// +// Solidity: function initializeDelegatorRegistration(bytes32 validationID, uint256 delegationAmount) returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) InitializeDelegatorRegistration(opts *bind.TransactOpts, validationID [32]byte, delegationAmount *big.Int) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "initializeDelegatorRegistration", validationID, delegationAmount) +} + +// InitializeDelegatorRegistration is a paid mutator transaction binding the contract method 0x9e1bc4ef. +// +// Solidity: function initializeDelegatorRegistration(bytes32 validationID, uint256 delegationAmount) returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) InitializeDelegatorRegistration(validationID [32]byte, delegationAmount *big.Int) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeDelegatorRegistration(&_ERC20TokenStakingManager.TransactOpts, validationID, delegationAmount) +} + +// InitializeDelegatorRegistration is a paid mutator transaction binding the contract method 0x9e1bc4ef. +// +// Solidity: function initializeDelegatorRegistration(bytes32 validationID, uint256 delegationAmount) returns(bytes32) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) InitializeDelegatorRegistration(validationID [32]byte, delegationAmount *big.Int) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeDelegatorRegistration(&_ERC20TokenStakingManager.TransactOpts, validationID, delegationAmount) +} + +// InitializeEndDelegation is a paid mutator transaction binding the contract method 0x0118acc4. +// +// Solidity: function initializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) InitializeEndDelegation(opts *bind.TransactOpts, delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "initializeEndDelegation", delegationID, includeUptimeProof, messageIndex) +} + +// InitializeEndDelegation is a paid mutator transaction binding the contract method 0x0118acc4. +// +// Solidity: function initializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) InitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeEndDelegation(&_ERC20TokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// InitializeEndDelegation is a paid mutator transaction binding the contract method 0x0118acc4. +// +// Solidity: function initializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) InitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeEndDelegation(&_ERC20TokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x76f78621. +// +// Solidity: function initializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) InitializeEndValidation(opts *bind.TransactOpts, validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "initializeEndValidation", validationID, includeUptimeProof, messageIndex) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x76f78621. +// +// Solidity: function initializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) InitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeEndValidation(&_ERC20TokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x76f78621. +// +// Solidity: function initializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) InitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeEndValidation(&_ERC20TokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0x4bee0040. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint16 delegationFeeBips, uint64 minStakeDuration, uint256 stakeAmount) returns(bytes32 validationID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) InitializeValidatorRegistration(opts *bind.TransactOpts, registrationInput ValidatorRegistrationInput, delegationFeeBips uint16, minStakeDuration uint64, stakeAmount *big.Int) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "initializeValidatorRegistration", registrationInput, delegationFeeBips, minStakeDuration, stakeAmount) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0x4bee0040. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint16 delegationFeeBips, uint64 minStakeDuration, uint256 stakeAmount) returns(bytes32 validationID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) InitializeValidatorRegistration(registrationInput ValidatorRegistrationInput, delegationFeeBips uint16, minStakeDuration uint64, stakeAmount *big.Int) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeValidatorRegistration(&_ERC20TokenStakingManager.TransactOpts, registrationInput, delegationFeeBips, minStakeDuration, stakeAmount) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0x4bee0040. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint16 delegationFeeBips, uint64 minStakeDuration, uint256 stakeAmount) returns(bytes32 validationID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) InitializeValidatorRegistration(registrationInput ValidatorRegistrationInput, delegationFeeBips uint16, minStakeDuration uint64, stakeAmount *big.Int) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeValidatorRegistration(&_ERC20TokenStakingManager.TransactOpts, registrationInput, delegationFeeBips, minStakeDuration, stakeAmount) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) InitializeValidatorSet(opts *bind.TransactOpts, subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "initializeValidatorSet", subnetConversionData, messageIndex) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) InitializeValidatorSet(subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeValidatorSet(&_ERC20TokenStakingManager.TransactOpts, subnetConversionData, messageIndex) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) InitializeValidatorSet(subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.InitializeValidatorSet(&_ERC20TokenStakingManager.TransactOpts, subnetConversionData, messageIndex) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) ResendEndValidatorMessage(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "resendEndValidatorMessage", validationID) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ResendEndValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ResendEndValidatorMessage(&_ERC20TokenStakingManager.TransactOpts, validationID) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) ResendEndValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ResendEndValidatorMessage(&_ERC20TokenStakingManager.TransactOpts, validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) ResendRegisterValidatorMessage(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "resendRegisterValidatorMessage", validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ResendRegisterValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ResendRegisterValidatorMessage(&_ERC20TokenStakingManager.TransactOpts, validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) ResendRegisterValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ResendRegisterValidatorMessage(&_ERC20TokenStakingManager.TransactOpts, validationID) +} + +// ResendUpdateDelegation is a paid mutator transaction binding the contract method 0xba3a4b97. +// +// Solidity: function resendUpdateDelegation(bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) ResendUpdateDelegation(opts *bind.TransactOpts, delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "resendUpdateDelegation", delegationID) +} + +// ResendUpdateDelegation is a paid mutator transaction binding the contract method 0xba3a4b97. +// +// Solidity: function resendUpdateDelegation(bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) ResendUpdateDelegation(delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ResendUpdateDelegation(&_ERC20TokenStakingManager.TransactOpts, delegationID) +} + +// ResendUpdateDelegation is a paid mutator transaction binding the contract method 0xba3a4b97. +// +// Solidity: function resendUpdateDelegation(bytes32 delegationID) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) ResendUpdateDelegation(delegationID [32]byte) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.ResendUpdateDelegation(&_ERC20TokenStakingManager.TransactOpts, delegationID) +} + +// SubmitUptimeProof is a paid mutator transaction binding the contract method 0x25e1c776. +// +// Solidity: function submitUptimeProof(bytes32 validationID, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactor) SubmitUptimeProof(opts *bind.TransactOpts, validationID [32]byte, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.contract.Transact(opts, "submitUptimeProof", validationID, messageIndex) +} + +// SubmitUptimeProof is a paid mutator transaction binding the contract method 0x25e1c776. +// +// Solidity: function submitUptimeProof(bytes32 validationID, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerSession) SubmitUptimeProof(validationID [32]byte, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.SubmitUptimeProof(&_ERC20TokenStakingManager.TransactOpts, validationID, messageIndex) +} + +// SubmitUptimeProof is a paid mutator transaction binding the contract method 0x25e1c776. +// +// Solidity: function submitUptimeProof(bytes32 validationID, uint32 messageIndex) returns() +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerTransactorSession) SubmitUptimeProof(validationID [32]byte, messageIndex uint32) (*types.Transaction, error) { + return _ERC20TokenStakingManager.Contract.SubmitUptimeProof(&_ERC20TokenStakingManager.TransactOpts, validationID, messageIndex) +} + +// ERC20TokenStakingManagerDelegationEndedIterator is returned from FilterDelegationEnded and is used to iterate over the raw logs and unpacked data for DelegationEnded events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegationEndedIterator struct { + Event *ERC20TokenStakingManagerDelegationEnded // 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 interfaces.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 *ERC20TokenStakingManagerDelegationEndedIterator) 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(ERC20TokenStakingManagerDelegationEnded) + 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(ERC20TokenStakingManagerDelegationEnded) + 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 *ERC20TokenStakingManagerDelegationEndedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerDelegationEndedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerDelegationEnded represents a DelegationEnded event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegationEnded struct { + DelegationID [32]byte + ValidationID [32]byte + Rewards *big.Int + Fees *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegationEnded is a free log retrieval operation binding the contract event 0x8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993. +// +// Solidity: event DelegationEnded(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterDelegationEnded(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte) (*ERC20TokenStakingManagerDelegationEndedIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "DelegationEnded", delegationIDRule, validationIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerDelegationEndedIterator{contract: _ERC20TokenStakingManager.contract, event: "DelegationEnded", logs: logs, sub: sub}, nil +} + +// WatchDelegationEnded is a free log subscription operation binding the contract event 0x8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993. +// +// Solidity: event DelegationEnded(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchDelegationEnded(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerDelegationEnded, delegationID [][32]byte, validationID [][32]byte) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "DelegationEnded", delegationIDRule, validationIDRule) + 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(ERC20TokenStakingManagerDelegationEnded) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegationEnded", 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 +} + +// ParseDelegationEnded is a log parse operation binding the contract event 0x8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993. +// +// Solidity: event DelegationEnded(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseDelegationEnded(log types.Log) (*ERC20TokenStakingManagerDelegationEnded, error) { + event := new(ERC20TokenStakingManagerDelegationEnded) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegationEnded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerDelegatorAddedIterator is returned from FilterDelegatorAdded and is used to iterate over the raw logs and unpacked data for DelegatorAdded events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegatorAddedIterator struct { + Event *ERC20TokenStakingManagerDelegatorAdded // 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 interfaces.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 *ERC20TokenStakingManagerDelegatorAddedIterator) 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(ERC20TokenStakingManagerDelegatorAdded) + 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(ERC20TokenStakingManagerDelegatorAdded) + 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 *ERC20TokenStakingManagerDelegatorAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerDelegatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerDelegatorAdded represents a DelegatorAdded event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegatorAdded struct { + DelegationID [32]byte + ValidationID [32]byte + DelegatorAddress common.Address + Nonce uint64 + ValidatorWeight uint64 + DelegatorWeight uint64 + SetWeightMessageID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegatorAdded is a free log retrieval operation binding the contract event 0xb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426. +// +// Solidity: event DelegatorAdded(bytes32 indexed delegationID, bytes32 indexed validationID, address indexed delegatorAddress, uint64 nonce, uint64 validatorWeight, uint64 delegatorWeight, bytes32 setWeightMessageID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterDelegatorAdded(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte, delegatorAddress []common.Address) (*ERC20TokenStakingManagerDelegatorAddedIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var delegatorAddressRule []interface{} + for _, delegatorAddressItem := range delegatorAddress { + delegatorAddressRule = append(delegatorAddressRule, delegatorAddressItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "DelegatorAdded", delegationIDRule, validationIDRule, delegatorAddressRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerDelegatorAddedIterator{contract: _ERC20TokenStakingManager.contract, event: "DelegatorAdded", logs: logs, sub: sub}, nil +} + +// WatchDelegatorAdded is a free log subscription operation binding the contract event 0xb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426. +// +// Solidity: event DelegatorAdded(bytes32 indexed delegationID, bytes32 indexed validationID, address indexed delegatorAddress, uint64 nonce, uint64 validatorWeight, uint64 delegatorWeight, bytes32 setWeightMessageID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchDelegatorAdded(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerDelegatorAdded, delegationID [][32]byte, validationID [][32]byte, delegatorAddress []common.Address) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var delegatorAddressRule []interface{} + for _, delegatorAddressItem := range delegatorAddress { + delegatorAddressRule = append(delegatorAddressRule, delegatorAddressItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "DelegatorAdded", delegationIDRule, validationIDRule, delegatorAddressRule) + 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(ERC20TokenStakingManagerDelegatorAdded) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegatorAdded", 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 +} + +// ParseDelegatorAdded is a log parse operation binding the contract event 0xb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426. +// +// Solidity: event DelegatorAdded(bytes32 indexed delegationID, bytes32 indexed validationID, address indexed delegatorAddress, uint64 nonce, uint64 validatorWeight, uint64 delegatorWeight, bytes32 setWeightMessageID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseDelegatorAdded(log types.Log) (*ERC20TokenStakingManagerDelegatorAdded, error) { + event := new(ERC20TokenStakingManagerDelegatorAdded) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerDelegatorRegisteredIterator is returned from FilterDelegatorRegistered and is used to iterate over the raw logs and unpacked data for DelegatorRegistered events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegatorRegisteredIterator struct { + Event *ERC20TokenStakingManagerDelegatorRegistered // 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 interfaces.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 *ERC20TokenStakingManagerDelegatorRegisteredIterator) 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(ERC20TokenStakingManagerDelegatorRegistered) + 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(ERC20TokenStakingManagerDelegatorRegistered) + 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 *ERC20TokenStakingManagerDelegatorRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerDelegatorRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerDelegatorRegistered represents a DelegatorRegistered event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegatorRegistered struct { + DelegationID [32]byte + ValidationID [32]byte + StartTime *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegatorRegistered is a free log retrieval operation binding the contract event 0x047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6. +// +// Solidity: event DelegatorRegistered(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterDelegatorRegistered(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte) (*ERC20TokenStakingManagerDelegatorRegisteredIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "DelegatorRegistered", delegationIDRule, validationIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerDelegatorRegisteredIterator{contract: _ERC20TokenStakingManager.contract, event: "DelegatorRegistered", logs: logs, sub: sub}, nil +} + +// WatchDelegatorRegistered is a free log subscription operation binding the contract event 0x047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6. +// +// Solidity: event DelegatorRegistered(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchDelegatorRegistered(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerDelegatorRegistered, delegationID [][32]byte, validationID [][32]byte) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "DelegatorRegistered", delegationIDRule, validationIDRule) + 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(ERC20TokenStakingManagerDelegatorRegistered) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegatorRegistered", 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 +} + +// ParseDelegatorRegistered is a log parse operation binding the contract event 0x047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6. +// +// Solidity: event DelegatorRegistered(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseDelegatorRegistered(log types.Log) (*ERC20TokenStakingManagerDelegatorRegistered, error) { + event := new(ERC20TokenStakingManagerDelegatorRegistered) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegatorRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerDelegatorRemovalInitializedIterator is returned from FilterDelegatorRemovalInitialized and is used to iterate over the raw logs and unpacked data for DelegatorRemovalInitialized events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegatorRemovalInitializedIterator struct { + Event *ERC20TokenStakingManagerDelegatorRemovalInitialized // 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 interfaces.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 *ERC20TokenStakingManagerDelegatorRemovalInitializedIterator) 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(ERC20TokenStakingManagerDelegatorRemovalInitialized) + 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(ERC20TokenStakingManagerDelegatorRemovalInitialized) + 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 *ERC20TokenStakingManagerDelegatorRemovalInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerDelegatorRemovalInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerDelegatorRemovalInitialized represents a DelegatorRemovalInitialized event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerDelegatorRemovalInitialized struct { + DelegationID [32]byte + ValidationID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegatorRemovalInitialized is a free log retrieval operation binding the contract event 0x366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed57. +// +// Solidity: event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterDelegatorRemovalInitialized(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte) (*ERC20TokenStakingManagerDelegatorRemovalInitializedIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "DelegatorRemovalInitialized", delegationIDRule, validationIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerDelegatorRemovalInitializedIterator{contract: _ERC20TokenStakingManager.contract, event: "DelegatorRemovalInitialized", logs: logs, sub: sub}, nil +} + +// WatchDelegatorRemovalInitialized is a free log subscription operation binding the contract event 0x366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed57. +// +// Solidity: event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchDelegatorRemovalInitialized(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerDelegatorRemovalInitialized, delegationID [][32]byte, validationID [][32]byte) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "DelegatorRemovalInitialized", delegationIDRule, validationIDRule) + 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(ERC20TokenStakingManagerDelegatorRemovalInitialized) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegatorRemovalInitialized", 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 +} + +// ParseDelegatorRemovalInitialized is a log parse operation binding the contract event 0x366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed57. +// +// Solidity: event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseDelegatorRemovalInitialized(log types.Log) (*ERC20TokenStakingManagerDelegatorRemovalInitialized, error) { + event := new(ERC20TokenStakingManagerDelegatorRemovalInitialized) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "DelegatorRemovalInitialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerInitialValidatorCreatedIterator is returned from FilterInitialValidatorCreated and is used to iterate over the raw logs and unpacked data for InitialValidatorCreated events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerInitialValidatorCreatedIterator struct { + Event *ERC20TokenStakingManagerInitialValidatorCreated // 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 interfaces.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 *ERC20TokenStakingManagerInitialValidatorCreatedIterator) 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(ERC20TokenStakingManagerInitialValidatorCreated) + 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(ERC20TokenStakingManagerInitialValidatorCreated) + 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 *ERC20TokenStakingManagerInitialValidatorCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerInitialValidatorCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerInitialValidatorCreated represents a InitialValidatorCreated event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerInitialValidatorCreated struct { + ValidationID [32]byte + NodeID common.Hash + Weight *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialValidatorCreated is a free log retrieval operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterInitialValidatorCreated(opts *bind.FilterOpts, validationID [][32]byte, nodeID [][]byte) (*ERC20TokenStakingManagerInitialValidatorCreatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "InitialValidatorCreated", validationIDRule, nodeIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerInitialValidatorCreatedIterator{contract: _ERC20TokenStakingManager.contract, event: "InitialValidatorCreated", logs: logs, sub: sub}, nil +} + +// WatchInitialValidatorCreated is a free log subscription operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchInitialValidatorCreated(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerInitialValidatorCreated, validationID [][32]byte, nodeID [][]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "InitialValidatorCreated", validationIDRule, nodeIDRule) + 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(ERC20TokenStakingManagerInitialValidatorCreated) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "InitialValidatorCreated", 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 +} + +// ParseInitialValidatorCreated is a log parse operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseInitialValidatorCreated(log types.Log) (*ERC20TokenStakingManagerInitialValidatorCreated, error) { + event := new(ERC20TokenStakingManagerInitialValidatorCreated) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "InitialValidatorCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerInitializedIterator struct { + Event *ERC20TokenStakingManagerInitialized // 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 interfaces.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 *ERC20TokenStakingManagerInitializedIterator) 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(ERC20TokenStakingManagerInitialized) + 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(ERC20TokenStakingManagerInitialized) + 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 *ERC20TokenStakingManagerInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerInitialized represents a Initialized event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterInitialized(opts *bind.FilterOpts) (*ERC20TokenStakingManagerInitializedIterator, error) { + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerInitializedIterator{contract: _ERC20TokenStakingManager.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerInitialized) (event.Subscription, error) { + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "Initialized") + 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(ERC20TokenStakingManagerInitialized) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseInitialized(log types.Log) (*ERC20TokenStakingManagerInitialized, error) { + event := new(ERC20TokenStakingManagerInitialized) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerUptimeUpdatedIterator is returned from FilterUptimeUpdated and is used to iterate over the raw logs and unpacked data for UptimeUpdated events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerUptimeUpdatedIterator struct { + Event *ERC20TokenStakingManagerUptimeUpdated // 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 interfaces.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 *ERC20TokenStakingManagerUptimeUpdatedIterator) 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(ERC20TokenStakingManagerUptimeUpdated) + 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(ERC20TokenStakingManagerUptimeUpdated) + 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 *ERC20TokenStakingManagerUptimeUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerUptimeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerUptimeUpdated represents a UptimeUpdated event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerUptimeUpdated struct { + ValidationID [32]byte + Uptime uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUptimeUpdated is a free log retrieval operation binding the contract event 0xec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435. +// +// Solidity: event UptimeUpdated(bytes32 indexed validationID, uint64 uptime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterUptimeUpdated(opts *bind.FilterOpts, validationID [][32]byte) (*ERC20TokenStakingManagerUptimeUpdatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "UptimeUpdated", validationIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerUptimeUpdatedIterator{contract: _ERC20TokenStakingManager.contract, event: "UptimeUpdated", logs: logs, sub: sub}, nil +} + +// WatchUptimeUpdated is a free log subscription operation binding the contract event 0xec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435. +// +// Solidity: event UptimeUpdated(bytes32 indexed validationID, uint64 uptime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchUptimeUpdated(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerUptimeUpdated, validationID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "UptimeUpdated", validationIDRule) + 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(ERC20TokenStakingManagerUptimeUpdated) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "UptimeUpdated", 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 +} + +// ParseUptimeUpdated is a log parse operation binding the contract event 0xec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435. +// +// Solidity: event UptimeUpdated(bytes32 indexed validationID, uint64 uptime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseUptimeUpdated(log types.Log) (*ERC20TokenStakingManagerUptimeUpdated, error) { + event := new(ERC20TokenStakingManagerUptimeUpdated) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "UptimeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerValidationPeriodCreatedIterator is returned from FilterValidationPeriodCreated and is used to iterate over the raw logs and unpacked data for ValidationPeriodCreated events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidationPeriodCreatedIterator struct { + Event *ERC20TokenStakingManagerValidationPeriodCreated // 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 interfaces.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 *ERC20TokenStakingManagerValidationPeriodCreatedIterator) 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(ERC20TokenStakingManagerValidationPeriodCreated) + 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(ERC20TokenStakingManagerValidationPeriodCreated) + 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 *ERC20TokenStakingManagerValidationPeriodCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerValidationPeriodCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerValidationPeriodCreated represents a ValidationPeriodCreated event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidationPeriodCreated struct { + ValidationID [32]byte + NodeID common.Hash + RegisterValidationMessageID [32]byte + Weight *big.Int + RegistrationExpiry uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodCreated is a free log retrieval operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterValidationPeriodCreated(opts *bind.FilterOpts, validationID [][32]byte, nodeID [][]byte, registerValidationMessageID [][32]byte) (*ERC20TokenStakingManagerValidationPeriodCreatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + var registerValidationMessageIDRule []interface{} + for _, registerValidationMessageIDItem := range registerValidationMessageID { + registerValidationMessageIDRule = append(registerValidationMessageIDRule, registerValidationMessageIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "ValidationPeriodCreated", validationIDRule, nodeIDRule, registerValidationMessageIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerValidationPeriodCreatedIterator{contract: _ERC20TokenStakingManager.contract, event: "ValidationPeriodCreated", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodCreated is a free log subscription operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchValidationPeriodCreated(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerValidationPeriodCreated, validationID [][32]byte, nodeID [][]byte, registerValidationMessageID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + var registerValidationMessageIDRule []interface{} + for _, registerValidationMessageIDItem := range registerValidationMessageID { + registerValidationMessageIDRule = append(registerValidationMessageIDRule, registerValidationMessageIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "ValidationPeriodCreated", validationIDRule, nodeIDRule, registerValidationMessageIDRule) + 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(ERC20TokenStakingManagerValidationPeriodCreated) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidationPeriodCreated", 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 +} + +// ParseValidationPeriodCreated is a log parse operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseValidationPeriodCreated(log types.Log) (*ERC20TokenStakingManagerValidationPeriodCreated, error) { + event := new(ERC20TokenStakingManagerValidationPeriodCreated) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidationPeriodCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerValidationPeriodEndedIterator is returned from FilterValidationPeriodEnded and is used to iterate over the raw logs and unpacked data for ValidationPeriodEnded events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidationPeriodEndedIterator struct { + Event *ERC20TokenStakingManagerValidationPeriodEnded // 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 interfaces.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 *ERC20TokenStakingManagerValidationPeriodEndedIterator) 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(ERC20TokenStakingManagerValidationPeriodEnded) + 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(ERC20TokenStakingManagerValidationPeriodEnded) + 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 *ERC20TokenStakingManagerValidationPeriodEndedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerValidationPeriodEndedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerValidationPeriodEnded represents a ValidationPeriodEnded event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidationPeriodEnded struct { + ValidationID [32]byte + Status uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodEnded is a free log retrieval operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterValidationPeriodEnded(opts *bind.FilterOpts, validationID [][32]byte, status []uint8) (*ERC20TokenStakingManagerValidationPeriodEndedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var statusRule []interface{} + for _, statusItem := range status { + statusRule = append(statusRule, statusItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "ValidationPeriodEnded", validationIDRule, statusRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerValidationPeriodEndedIterator{contract: _ERC20TokenStakingManager.contract, event: "ValidationPeriodEnded", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodEnded is a free log subscription operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchValidationPeriodEnded(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerValidationPeriodEnded, validationID [][32]byte, status []uint8) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var statusRule []interface{} + for _, statusItem := range status { + statusRule = append(statusRule, statusItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "ValidationPeriodEnded", validationIDRule, statusRule) + 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(ERC20TokenStakingManagerValidationPeriodEnded) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidationPeriodEnded", 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 +} + +// ParseValidationPeriodEnded is a log parse operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseValidationPeriodEnded(log types.Log) (*ERC20TokenStakingManagerValidationPeriodEnded, error) { + event := new(ERC20TokenStakingManagerValidationPeriodEnded) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidationPeriodEnded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerValidationPeriodRegisteredIterator is returned from FilterValidationPeriodRegistered and is used to iterate over the raw logs and unpacked data for ValidationPeriodRegistered events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidationPeriodRegisteredIterator struct { + Event *ERC20TokenStakingManagerValidationPeriodRegistered // 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 interfaces.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 *ERC20TokenStakingManagerValidationPeriodRegisteredIterator) 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(ERC20TokenStakingManagerValidationPeriodRegistered) + 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(ERC20TokenStakingManagerValidationPeriodRegistered) + 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 *ERC20TokenStakingManagerValidationPeriodRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerValidationPeriodRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerValidationPeriodRegistered represents a ValidationPeriodRegistered event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidationPeriodRegistered struct { + ValidationID [32]byte + Weight *big.Int + Timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodRegistered is a free log retrieval operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterValidationPeriodRegistered(opts *bind.FilterOpts, validationID [][32]byte) (*ERC20TokenStakingManagerValidationPeriodRegisteredIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "ValidationPeriodRegistered", validationIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerValidationPeriodRegisteredIterator{contract: _ERC20TokenStakingManager.contract, event: "ValidationPeriodRegistered", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodRegistered is a free log subscription operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchValidationPeriodRegistered(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerValidationPeriodRegistered, validationID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "ValidationPeriodRegistered", validationIDRule) + 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(ERC20TokenStakingManagerValidationPeriodRegistered) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidationPeriodRegistered", 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 +} + +// ParseValidationPeriodRegistered is a log parse operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseValidationPeriodRegistered(log types.Log) (*ERC20TokenStakingManagerValidationPeriodRegistered, error) { + event := new(ERC20TokenStakingManagerValidationPeriodRegistered) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidationPeriodRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerValidatorRemovalInitializedIterator is returned from FilterValidatorRemovalInitialized and is used to iterate over the raw logs and unpacked data for ValidatorRemovalInitialized events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidatorRemovalInitializedIterator struct { + Event *ERC20TokenStakingManagerValidatorRemovalInitialized // 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 interfaces.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 *ERC20TokenStakingManagerValidatorRemovalInitializedIterator) 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(ERC20TokenStakingManagerValidatorRemovalInitialized) + 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(ERC20TokenStakingManagerValidatorRemovalInitialized) + 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 *ERC20TokenStakingManagerValidatorRemovalInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerValidatorRemovalInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerValidatorRemovalInitialized represents a ValidatorRemovalInitialized event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidatorRemovalInitialized struct { + ValidationID [32]byte + SetWeightMessageID [32]byte + Weight *big.Int + EndTime *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorRemovalInitialized is a free log retrieval operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterValidatorRemovalInitialized(opts *bind.FilterOpts, validationID [][32]byte, setWeightMessageID [][32]byte) (*ERC20TokenStakingManagerValidatorRemovalInitializedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var setWeightMessageIDRule []interface{} + for _, setWeightMessageIDItem := range setWeightMessageID { + setWeightMessageIDRule = append(setWeightMessageIDRule, setWeightMessageIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "ValidatorRemovalInitialized", validationIDRule, setWeightMessageIDRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerValidatorRemovalInitializedIterator{contract: _ERC20TokenStakingManager.contract, event: "ValidatorRemovalInitialized", logs: logs, sub: sub}, nil +} + +// WatchValidatorRemovalInitialized is a free log subscription operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchValidatorRemovalInitialized(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerValidatorRemovalInitialized, validationID [][32]byte, setWeightMessageID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var setWeightMessageIDRule []interface{} + for _, setWeightMessageIDItem := range setWeightMessageID { + setWeightMessageIDRule = append(setWeightMessageIDRule, setWeightMessageIDItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "ValidatorRemovalInitialized", validationIDRule, setWeightMessageIDRule) + 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(ERC20TokenStakingManagerValidatorRemovalInitialized) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidatorRemovalInitialized", 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 +} + +// ParseValidatorRemovalInitialized is a log parse operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseValidatorRemovalInitialized(log types.Log) (*ERC20TokenStakingManagerValidatorRemovalInitialized, error) { + event := new(ERC20TokenStakingManagerValidatorRemovalInitialized) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidatorRemovalInitialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20TokenStakingManagerValidatorWeightUpdateIterator is returned from FilterValidatorWeightUpdate and is used to iterate over the raw logs and unpacked data for ValidatorWeightUpdate events raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidatorWeightUpdateIterator struct { + Event *ERC20TokenStakingManagerValidatorWeightUpdate // 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 interfaces.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 *ERC20TokenStakingManagerValidatorWeightUpdateIterator) 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(ERC20TokenStakingManagerValidatorWeightUpdate) + 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(ERC20TokenStakingManagerValidatorWeightUpdate) + 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 *ERC20TokenStakingManagerValidatorWeightUpdateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TokenStakingManagerValidatorWeightUpdateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TokenStakingManagerValidatorWeightUpdate represents a ValidatorWeightUpdate event raised by the ERC20TokenStakingManager contract. +type ERC20TokenStakingManagerValidatorWeightUpdate struct { + ValidationID [32]byte + Nonce uint64 + ValidatorWeight uint64 + SetWeightMessageID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorWeightUpdate is a free log retrieval operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) FilterValidatorWeightUpdate(opts *bind.FilterOpts, validationID [][32]byte, nonce []uint64) (*ERC20TokenStakingManagerValidatorWeightUpdateIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.FilterLogs(opts, "ValidatorWeightUpdate", validationIDRule, nonceRule) + if err != nil { + return nil, err + } + return &ERC20TokenStakingManagerValidatorWeightUpdateIterator{contract: _ERC20TokenStakingManager.contract, event: "ValidatorWeightUpdate", logs: logs, sub: sub}, nil +} + +// WatchValidatorWeightUpdate is a free log subscription operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) WatchValidatorWeightUpdate(opts *bind.WatchOpts, sink chan<- *ERC20TokenStakingManagerValidatorWeightUpdate, validationID [][32]byte, nonce []uint64) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + + logs, sub, err := _ERC20TokenStakingManager.contract.WatchLogs(opts, "ValidatorWeightUpdate", validationIDRule, nonceRule) + 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(ERC20TokenStakingManagerValidatorWeightUpdate) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidatorWeightUpdate", 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 +} + +// ParseValidatorWeightUpdate is a log parse operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_ERC20TokenStakingManager *ERC20TokenStakingManagerFilterer) ParseValidatorWeightUpdate(log types.Log) (*ERC20TokenStakingManagerValidatorWeightUpdate, error) { + event := new(ERC20TokenStakingManagerValidatorWeightUpdate) + if err := _ERC20TokenStakingManager.contract.UnpackLog(event, "ValidatorWeightUpdate", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/abi-bindings/go/validator-manager/ExampleRewardCalculator/ExampleRewardCalculator.go b/abi-bindings/go/validator-manager/ExampleRewardCalculator/ExampleRewardCalculator.go new file mode 100644 index 000000000..ab51fdaa6 --- /dev/null +++ b/abi-bindings/go/validator-manager/ExampleRewardCalculator/ExampleRewardCalculator.go @@ -0,0 +1,358 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package examplerewardcalculator + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ExampleRewardCalculatorMetaData contains all meta data concerning the ExampleRewardCalculator contract. +var ExampleRewardCalculatorMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"rewardBasisPoints_\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"BIPS_CONVERSION_FACTOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SECONDS_IN_YEAR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPTIME_REWARDS_THRESHOLD_PERCENTAGE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"calculateReward\",\"inputs\":[{\"name\":\"stakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"validatorStartTime\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"stakingStartTime\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"stakingEndTime\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"uptimeSeconds\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"rewardBasisPoints\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"}]", + Bin: "0x60a0604052348015600e575f80fd5b50604051610362380380610362833981016040819052602b91603b565b6001600160401b03166080526066565b5f60208284031215604a575f80fd5b81516001600160401b0381168114605f575f80fd5b9392505050565b6080516102de6100845f395f818160c5015261015d01526102de5ff3fe608060405234801561000f575f80fd5b5060043610610055575f3560e01c80634f22429f146100595780635dcc93911461007f578063a9778a7a1461008a578063afba878a146100a6578063bb65b242146100c0575b5f80fd5b61006c6100673660046101d5565b6100ff565b6040519081526020015b60405180910390f35b61006c6301e1338081565b61009361271081565b60405161ffff9091168152602001610076565b6100ae605081565b60405160ff9091168152602001610076565b6100e77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b039091168152602001610076565b5f605061010c8685610243565b610116919061026a565b6001600160401b031661012a83606461026a565b6001600160401b0316101561014057505f6101b1565b6127106301e133806101528686610243565b6001600160401b03167f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316896101909190610295565b61019a9190610295565b6101a491906102b2565b6101ae91906102b2565b90505b95945050505050565b80356001600160401b03811681146101d0575f80fd5b919050565b5f805f805f60a086880312156101e9575f80fd5b853594506101f9602087016101ba565b9350610207604087016101ba565b9250610215606087016101ba565b9150610223608087016101ba565b90509295509295909350565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b038281168282160390808211156102635761026361022f565b5092915050565b6001600160401b0381811683821602808216919082811461028d5761028d61022f565b505092915050565b80820281158282048414176102ac576102ac61022f565b92915050565b5f826102cc57634e487b7160e01b5f52601260045260245ffd5b50049056fea164736f6c6343000819000a", +} + +// ExampleRewardCalculatorABI is the input ABI used to generate the binding from. +// Deprecated: Use ExampleRewardCalculatorMetaData.ABI instead. +var ExampleRewardCalculatorABI = ExampleRewardCalculatorMetaData.ABI + +// ExampleRewardCalculatorBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ExampleRewardCalculatorMetaData.Bin instead. +var ExampleRewardCalculatorBin = ExampleRewardCalculatorMetaData.Bin + +// DeployExampleRewardCalculator deploys a new Ethereum contract, binding an instance of ExampleRewardCalculator to it. +func DeployExampleRewardCalculator(auth *bind.TransactOpts, backend bind.ContractBackend, rewardBasisPoints_ uint64) (common.Address, *types.Transaction, *ExampleRewardCalculator, error) { + parsed, err := ExampleRewardCalculatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ExampleRewardCalculatorBin), backend, rewardBasisPoints_) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ExampleRewardCalculator{ExampleRewardCalculatorCaller: ExampleRewardCalculatorCaller{contract: contract}, ExampleRewardCalculatorTransactor: ExampleRewardCalculatorTransactor{contract: contract}, ExampleRewardCalculatorFilterer: ExampleRewardCalculatorFilterer{contract: contract}}, nil +} + +// ExampleRewardCalculator is an auto generated Go binding around an Ethereum contract. +type ExampleRewardCalculator struct { + ExampleRewardCalculatorCaller // Read-only binding to the contract + ExampleRewardCalculatorTransactor // Write-only binding to the contract + ExampleRewardCalculatorFilterer // Log filterer for contract events +} + +// ExampleRewardCalculatorCaller is an auto generated read-only Go binding around an Ethereum contract. +type ExampleRewardCalculatorCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExampleRewardCalculatorTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ExampleRewardCalculatorTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExampleRewardCalculatorFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ExampleRewardCalculatorFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExampleRewardCalculatorSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ExampleRewardCalculatorSession struct { + Contract *ExampleRewardCalculator // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ExampleRewardCalculatorCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ExampleRewardCalculatorCallerSession struct { + Contract *ExampleRewardCalculatorCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ExampleRewardCalculatorTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ExampleRewardCalculatorTransactorSession struct { + Contract *ExampleRewardCalculatorTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ExampleRewardCalculatorRaw is an auto generated low-level Go binding around an Ethereum contract. +type ExampleRewardCalculatorRaw struct { + Contract *ExampleRewardCalculator // Generic contract binding to access the raw methods on +} + +// ExampleRewardCalculatorCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ExampleRewardCalculatorCallerRaw struct { + Contract *ExampleRewardCalculatorCaller // Generic read-only contract binding to access the raw methods on +} + +// ExampleRewardCalculatorTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ExampleRewardCalculatorTransactorRaw struct { + Contract *ExampleRewardCalculatorTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewExampleRewardCalculator creates a new instance of ExampleRewardCalculator, bound to a specific deployed contract. +func NewExampleRewardCalculator(address common.Address, backend bind.ContractBackend) (*ExampleRewardCalculator, error) { + contract, err := bindExampleRewardCalculator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ExampleRewardCalculator{ExampleRewardCalculatorCaller: ExampleRewardCalculatorCaller{contract: contract}, ExampleRewardCalculatorTransactor: ExampleRewardCalculatorTransactor{contract: contract}, ExampleRewardCalculatorFilterer: ExampleRewardCalculatorFilterer{contract: contract}}, nil +} + +// NewExampleRewardCalculatorCaller creates a new read-only instance of ExampleRewardCalculator, bound to a specific deployed contract. +func NewExampleRewardCalculatorCaller(address common.Address, caller bind.ContractCaller) (*ExampleRewardCalculatorCaller, error) { + contract, err := bindExampleRewardCalculator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ExampleRewardCalculatorCaller{contract: contract}, nil +} + +// NewExampleRewardCalculatorTransactor creates a new write-only instance of ExampleRewardCalculator, bound to a specific deployed contract. +func NewExampleRewardCalculatorTransactor(address common.Address, transactor bind.ContractTransactor) (*ExampleRewardCalculatorTransactor, error) { + contract, err := bindExampleRewardCalculator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ExampleRewardCalculatorTransactor{contract: contract}, nil +} + +// NewExampleRewardCalculatorFilterer creates a new log filterer instance of ExampleRewardCalculator, bound to a specific deployed contract. +func NewExampleRewardCalculatorFilterer(address common.Address, filterer bind.ContractFilterer) (*ExampleRewardCalculatorFilterer, error) { + contract, err := bindExampleRewardCalculator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ExampleRewardCalculatorFilterer{contract: contract}, nil +} + +// bindExampleRewardCalculator binds a generic wrapper to an already deployed contract. +func bindExampleRewardCalculator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ExampleRewardCalculatorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ExampleRewardCalculator *ExampleRewardCalculatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExampleRewardCalculator.Contract.ExampleRewardCalculatorCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ExampleRewardCalculator *ExampleRewardCalculatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExampleRewardCalculator.Contract.ExampleRewardCalculatorTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ExampleRewardCalculator *ExampleRewardCalculatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExampleRewardCalculator.Contract.ExampleRewardCalculatorTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ExampleRewardCalculator *ExampleRewardCalculatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExampleRewardCalculator.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ExampleRewardCalculator *ExampleRewardCalculatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExampleRewardCalculator.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ExampleRewardCalculator *ExampleRewardCalculatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExampleRewardCalculator.Contract.contract.Transact(opts, method, params...) +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCaller) BIPSCONVERSIONFACTOR(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _ExampleRewardCalculator.contract.Call(opts, &out, "BIPS_CONVERSION_FACTOR") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_ExampleRewardCalculator *ExampleRewardCalculatorSession) BIPSCONVERSIONFACTOR() (uint16, error) { + return _ExampleRewardCalculator.Contract.BIPSCONVERSIONFACTOR(&_ExampleRewardCalculator.CallOpts) +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCallerSession) BIPSCONVERSIONFACTOR() (uint16, error) { + return _ExampleRewardCalculator.Contract.BIPSCONVERSIONFACTOR(&_ExampleRewardCalculator.CallOpts) +} + +// SECONDSINYEAR is a free data retrieval call binding the contract method 0x5dcc9391. +// +// Solidity: function SECONDS_IN_YEAR() view returns(uint256) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCaller) SECONDSINYEAR(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _ExampleRewardCalculator.contract.Call(opts, &out, "SECONDS_IN_YEAR") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SECONDSINYEAR is a free data retrieval call binding the contract method 0x5dcc9391. +// +// Solidity: function SECONDS_IN_YEAR() view returns(uint256) +func (_ExampleRewardCalculator *ExampleRewardCalculatorSession) SECONDSINYEAR() (*big.Int, error) { + return _ExampleRewardCalculator.Contract.SECONDSINYEAR(&_ExampleRewardCalculator.CallOpts) +} + +// SECONDSINYEAR is a free data retrieval call binding the contract method 0x5dcc9391. +// +// Solidity: function SECONDS_IN_YEAR() view returns(uint256) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCallerSession) SECONDSINYEAR() (*big.Int, error) { + return _ExampleRewardCalculator.Contract.SECONDSINYEAR(&_ExampleRewardCalculator.CallOpts) +} + +// UPTIMEREWARDSTHRESHOLDPERCENTAGE is a free data retrieval call binding the contract method 0xafba878a. +// +// Solidity: function UPTIME_REWARDS_THRESHOLD_PERCENTAGE() view returns(uint8) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCaller) UPTIMEREWARDSTHRESHOLDPERCENTAGE(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ExampleRewardCalculator.contract.Call(opts, &out, "UPTIME_REWARDS_THRESHOLD_PERCENTAGE") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// UPTIMEREWARDSTHRESHOLDPERCENTAGE is a free data retrieval call binding the contract method 0xafba878a. +// +// Solidity: function UPTIME_REWARDS_THRESHOLD_PERCENTAGE() view returns(uint8) +func (_ExampleRewardCalculator *ExampleRewardCalculatorSession) UPTIMEREWARDSTHRESHOLDPERCENTAGE() (uint8, error) { + return _ExampleRewardCalculator.Contract.UPTIMEREWARDSTHRESHOLDPERCENTAGE(&_ExampleRewardCalculator.CallOpts) +} + +// UPTIMEREWARDSTHRESHOLDPERCENTAGE is a free data retrieval call binding the contract method 0xafba878a. +// +// Solidity: function UPTIME_REWARDS_THRESHOLD_PERCENTAGE() view returns(uint8) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCallerSession) UPTIMEREWARDSTHRESHOLDPERCENTAGE() (uint8, error) { + return _ExampleRewardCalculator.Contract.UPTIMEREWARDSTHRESHOLDPERCENTAGE(&_ExampleRewardCalculator.CallOpts) +} + +// CalculateReward is a free data retrieval call binding the contract method 0x4f22429f. +// +// Solidity: function calculateReward(uint256 stakeAmount, uint64 validatorStartTime, uint64 stakingStartTime, uint64 stakingEndTime, uint64 uptimeSeconds) view returns(uint256) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCaller) CalculateReward(opts *bind.CallOpts, stakeAmount *big.Int, validatorStartTime uint64, stakingStartTime uint64, stakingEndTime uint64, uptimeSeconds uint64) (*big.Int, error) { + var out []interface{} + err := _ExampleRewardCalculator.contract.Call(opts, &out, "calculateReward", stakeAmount, validatorStartTime, stakingStartTime, stakingEndTime, uptimeSeconds) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CalculateReward is a free data retrieval call binding the contract method 0x4f22429f. +// +// Solidity: function calculateReward(uint256 stakeAmount, uint64 validatorStartTime, uint64 stakingStartTime, uint64 stakingEndTime, uint64 uptimeSeconds) view returns(uint256) +func (_ExampleRewardCalculator *ExampleRewardCalculatorSession) CalculateReward(stakeAmount *big.Int, validatorStartTime uint64, stakingStartTime uint64, stakingEndTime uint64, uptimeSeconds uint64) (*big.Int, error) { + return _ExampleRewardCalculator.Contract.CalculateReward(&_ExampleRewardCalculator.CallOpts, stakeAmount, validatorStartTime, stakingStartTime, stakingEndTime, uptimeSeconds) +} + +// CalculateReward is a free data retrieval call binding the contract method 0x4f22429f. +// +// Solidity: function calculateReward(uint256 stakeAmount, uint64 validatorStartTime, uint64 stakingStartTime, uint64 stakingEndTime, uint64 uptimeSeconds) view returns(uint256) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCallerSession) CalculateReward(stakeAmount *big.Int, validatorStartTime uint64, stakingStartTime uint64, stakingEndTime uint64, uptimeSeconds uint64) (*big.Int, error) { + return _ExampleRewardCalculator.Contract.CalculateReward(&_ExampleRewardCalculator.CallOpts, stakeAmount, validatorStartTime, stakingStartTime, stakingEndTime, uptimeSeconds) +} + +// RewardBasisPoints is a free data retrieval call binding the contract method 0xbb65b242. +// +// Solidity: function rewardBasisPoints() view returns(uint64) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCaller) RewardBasisPoints(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _ExampleRewardCalculator.contract.Call(opts, &out, "rewardBasisPoints") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// RewardBasisPoints is a free data retrieval call binding the contract method 0xbb65b242. +// +// Solidity: function rewardBasisPoints() view returns(uint64) +func (_ExampleRewardCalculator *ExampleRewardCalculatorSession) RewardBasisPoints() (uint64, error) { + return _ExampleRewardCalculator.Contract.RewardBasisPoints(&_ExampleRewardCalculator.CallOpts) +} + +// RewardBasisPoints is a free data retrieval call binding the contract method 0xbb65b242. +// +// Solidity: function rewardBasisPoints() view returns(uint64) +func (_ExampleRewardCalculator *ExampleRewardCalculatorCallerSession) RewardBasisPoints() (uint64, error) { + return _ExampleRewardCalculator.Contract.RewardBasisPoints(&_ExampleRewardCalculator.CallOpts) +} diff --git a/abi-bindings/go/validator-manager/NativeTokenStakingManager/NativeTokenStakingManager.go b/abi-bindings/go/validator-manager/NativeTokenStakingManager/NativeTokenStakingManager.go new file mode 100644 index 000000000..eb53a49c9 --- /dev/null +++ b/abi-bindings/go/validator-manager/NativeTokenStakingManager/NativeTokenStakingManager.go @@ -0,0 +1,2981 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package nativetokenstakingmanager + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// InitialValidator is an auto generated low-level Go binding around an user-defined struct. +type InitialValidator struct { + NodeID []byte + BlsPublicKey []byte + Weight uint64 +} + +// PChainOwner is an auto generated low-level Go binding around an user-defined struct. +type PChainOwner struct { + Threshold uint32 + Addresses []common.Address +} + +// PoSValidatorManagerSettings is an auto generated low-level Go binding around an user-defined struct. +type PoSValidatorManagerSettings struct { + BaseSettings ValidatorManagerSettings + MinimumStakeAmount *big.Int + MaximumStakeAmount *big.Int + MinimumStakeDuration uint64 + MinimumDelegationFeeBips uint16 + MaximumStakeMultiplier uint8 + WeightToValueFactor *big.Int + RewardCalculator common.Address +} + +// SubnetConversionData is an auto generated low-level Go binding around an user-defined struct. +type SubnetConversionData struct { + SubnetID [32]byte + ValidatorManagerBlockchainID [32]byte + ValidatorManagerAddress common.Address + InitialValidators []InitialValidator +} + +// Validator is an auto generated low-level Go binding around an user-defined struct. +type Validator struct { + Status uint8 + NodeID []byte + StartingWeight uint64 + MessageNonce uint64 + Weight uint64 + StartedAt uint64 + EndedAt uint64 +} + +// ValidatorManagerSettings is an auto generated low-level Go binding around an user-defined struct. +type ValidatorManagerSettings struct { + SubnetID [32]byte + ChurnPeriodSeconds uint64 + MaximumChurnPercentage uint8 +} + +// ValidatorRegistrationInput is an auto generated low-level Go binding around an user-defined struct. +type ValidatorRegistrationInput struct { + NodeID []byte + BlsPublicKey []byte + RegistrationExpiry uint64 + RemainingBalanceOwner PChainOwner + DisableOwner PChainOwner +} + +// NativeTokenStakingManagerMetaData contains all meta data concerning the NativeTokenStakingManager contract. +var NativeTokenStakingManagerMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ADDRESS_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"BIPS_CONVERSION_FACTOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"BLS_PUBLIC_KEY_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_CHURN_PERCENTAGE_LIMIT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_DELEGATION_FEE_BIPS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_REGISTRATION_EXPIRY_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_STAKE_MULTIPLIER_LIMIT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"NATIVE_MINTER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractINativeMinter\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"POS_VALIDATOR_MANAGER_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"P_CHAIN_BLOCKCHAIN_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VALIDATOR_MANAGER_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimDelegationFees\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeDelegatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndDelegation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"forceInitializeEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"forceInitializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getValidator\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structValidator\",\"components\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumValidatorStatus\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"startingWeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageNonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"startedAt\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"endedAt\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structPoSValidatorManagerSettings\",\"components\":[{\"name\":\"baseSettings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"churnPeriodSeconds\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maximumChurnPercentage\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"minimumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maximumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimumStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"minimumDelegationFeeBips\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"weightToValueFactor\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"rewardCalculator\",\"type\":\"address\",\"internalType\":\"contractIRewardCalculator\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeDelegatorRegistration\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"initializeEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"includeUptimeProof\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"registrationInput\",\"type\":\"tuple\",\"internalType\":\"structValidatorRegistrationInput\",\"components\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remainingBalanceOwner\",\"type\":\"tuple\",\"internalType\":\"structPChainOwner\",\"components\":[{\"name\":\"threshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"addresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]},{\"name\":\"disableOwner\",\"type\":\"tuple\",\"internalType\":\"structPChainOwner\",\"components\":[{\"name\":\"threshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"addresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}]},{\"name\":\"delegationFeeBips\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"minStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"initializeValidatorSet\",\"inputs\":[{\"name\":\"subnetConversionData\",\"type\":\"tuple\",\"internalType\":\"structSubnetConversionData\",\"components\":[{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorManagerBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"initialValidators\",\"type\":\"tuple[]\",\"internalType\":\"structInitialValidator[]\",\"components\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}]},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registeredValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendUpdateDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitUptimeProof\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"valueToWeight\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"weightToValue\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"DelegationEnded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"rewards\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"fees\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorAdded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"delegatorAddress\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"delegatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRegistered\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"startTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRemovalInitialized\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitialValidatorCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UptimeUpdated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"uptime\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorWeightUpdate\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AddressInsufficientBalance\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"DelegatorIneligibleForRewards\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBLSKeyLength\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidBLSPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodecID\",\"inputs\":[{\"name\":\"id\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidDelegationFee\",\"inputs\":[{\"name\":\"delegationFeeBips\",\"type\":\"uint16\",\"internalType\":\"uint16\"}]},{\"type\":\"error\",\"name\":\"InvalidDelegationID\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidDelegatorStatus\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumDelegatorStatus\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitializationStatus\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMaximumChurnPercentage\",\"inputs\":[{\"name\":\"maximumChurnPercentage\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageLength\",\"inputs\":[{\"name\":\"actual\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"expected\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageType\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMinStakeDuration\",\"inputs\":[{\"name\":\"minStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidNodeID\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidNonce\",\"inputs\":[{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidPChainOwnerThreshold\",\"inputs\":[{\"name\":\"threshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"addressesLength\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidRegistrationExpiry\",\"inputs\":[{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidStakeAmount\",\"inputs\":[{\"name\":\"stakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidStakeMultiplier\",\"inputs\":[{\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidSubnetConversionID\",\"inputs\":[{\"name\":\"encodedSubnetConversionID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"expectedSubnetConversionID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidTotalWeight\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidValidationID\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorManagerAddress\",\"inputs\":[{\"name\":\"validatorManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorManagerBlockchainID\",\"inputs\":[{\"name\":\"blockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorStatus\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumValidatorStatus\"}]},{\"type\":\"error\",\"name\":\"InvalidWarpMessage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidWarpOriginSenderAddress\",\"inputs\":[{\"name\":\"senderAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidWarpSourceChainID\",\"inputs\":[{\"name\":\"sourceChainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"MaxChurnRateExceeded\",\"inputs\":[{\"name\":\"churnAmount\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MaxWeightExceeded\",\"inputs\":[{\"name\":\"newValidatorWeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MinStakeDurationNotPassed\",\"inputs\":[{\"name\":\"endTime\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"NodeAlreadyRegistered\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PChainOwnerAddressesNotSorted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnauthorizedOwner\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnexpectedRegistrationStatus\",\"inputs\":[{\"name\":\"validRegistration\",\"type\":\"bool\",\"internalType\":\"bool\"}]},{\"type\":\"error\",\"name\":\"ValidatorIneligibleForRewards\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ValidatorNotPoS\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ZeroWeightToValueFactor\",\"inputs\":[]}]", + Bin: "0x608060405234801561000f575f80fd5b50604051615c4c380380615c4c83398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b615aff8061014d5f395ff3fe6080604052600436106101b5575f3560e01c80638280a25a116100ea578063ba3a4b971161008e578063ba3a4b97146104dc578063bc5fbfec146104fb578063bee0a03f1461052e578063c257a0f51461054d578063c599e24f1461056c578063c974d1b61461057f578063d5f20ff614610593578063df93d8de146105bf578063fd7ac5e7146105d5575f80fd5b80638280a25a1461040b57806393e245981461041f57806398f3e2b41461043e578063a3a65e481461045d578063a9778a7a146102df578063af2f5feb1461047c578063afb980961461048f578063b771b3bc146104c2575f80fd5b806335455ded1161015c57806335455ded146102df5780633a1cfff614610307578063467ef06f146103265780635297fae61461034557806360305d6214610364578063620658561461038d57806366435abf146103ba578063732214f8146103d957806376f78621146103ec575f80fd5b80630118acc4146101b95780630322ed98146101da578063151d30d1146101f95780631ec447241461022457806320d91b7a1461024357806325e1c776146102625780632e2194d814610281578063329c3e12146102b8575b5f80fd5b3480156101c4575f80fd5b506101d86101d3366004614e19565b6105f4565b005b3480156101e5575f80fd5b506101d86101f4366004614e54565b610629565b348015610204575f80fd5b5061020d600a81565b60405160ff90911681526020015b60405180910390f35b34801561022f575f80fd5b506101d861023e366004614e19565b61082c565b34801561024e575f80fd5b506101d861025d366004614e6b565b610837565b34801561026d575f80fd5b506101d861027c366004614eb9565b610d35565b34801561028c575f80fd5b506102a061029b366004614e54565b610da9565b6040516001600160401b03909116815260200161021b565b3480156102c3575f80fd5b506102d26001600160991b0181565b60405161021b9190614eda565b3480156102ea575f80fd5b506102f461271081565b60405161ffff909116815260200161021b565b348015610312575f80fd5b506101d8610321366004614e19565b610dfd565b348015610331575f80fd5b506101d8610340366004614eee565b610e08565b348015610350575f80fd5b506101d861035f366004614f07565b610eb8565b34801561036f575f80fd5b50610378601481565b60405163ffffffff909116815260200161021b565b348015610398575f80fd5b506103ac6103a7366004614f45565b611113565b60405190815260200161021b565b3480156103c5575f80fd5b506102a06103d4366004614e54565b611133565b3480156103e4575f80fd5b506103ac5f81565b3480156103f7575f80fd5b506101d8610406366004614e19565b611147565b348015610416575f80fd5b5061020d603081565b34801561042a575f80fd5b506101d8610439366004614e54565b611172565b348015610449575f80fd5b506101d8610458366004614f07565b61122f565b348015610468575f80fd5b506101d8610477366004614eee565b6113ee565b6103ac61048a366004614f6f565b611574565b34801561049a575f80fd5b506103ac7f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0081565b3480156104cd575f80fd5b506102d26005600160991b0181565b3480156104e7575f80fd5b506101d86104f6366004614e54565b61159a565b348015610506575f80fd5b506103ac7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0081565b348015610539575f80fd5b506101d8610548366004614e54565b611778565b348015610558575f80fd5b506101d8610567366004614fc3565b611895565b6103ac61057a366004614e54565b611972565b34801561058a575f80fd5b5061020d601481565b34801561059e575f80fd5b506105b26105ad366004614e54565b611995565b60405161021b919061504f565b3480156105ca575f80fd5b506102a06202a30081565b3480156105e0575f80fd5b506103ac6105ef3660046150cf565b611ad7565b6105ff838383611b0f565b61062457604051631036cf9160e11b8152600481018490526024015b60405180910390fd5b505050565b5f610632611e55565b5f838152600782016020526040808220815160e0810190925280549394509192909190829060ff16600581111561066b5761066b614fda565b600581111561067c5761067c614fda565b81526020016001820180546106909061513a565b80601f01602080910402602001604051908101604052809291908181526020018280546106bc9061513a565b80156107075780601f106106de57610100808354040283529160200191610707565b820191905f5260205f20905b8154815290600101906020018083116106ea57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561077257610772614fda565b146107a5575f8381526007830160205260409081902054905163170cc93360e21b815261061b9160ff169060040161516c565b6005600160991b016001600160a01b031663ee5b48eb6107ca8584606001515f611e79565b6040518263ffffffff1660e01b81526004016107e6919061517a565b6020604051808303815f875af1158015610802573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610826919061518c565b50505050565b610826838383611b0f565b5f610840611e55565b600981015490915060ff161561086957604051637fab81e560e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108ac573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108d0919061518c565b8360200135146108f9576040516372b0a7e760e11b81526020840135600482015260240161061b565b3061090a60608501604086016151b7565b6001600160a01b0316146109425761092860608401604085016151b7565b604051632f88120d60e21b815260040161061b9190614eda565b5f61095060608501856151d2565b905090505f805b828163ffffffff161015610c37575f61097360608801886151d2565b8363ffffffff1681811061098957610989615217565b905060200281019061099b919061522b565b6109a49061534f565b80516040519192505f9160088801916109bc916153c8565b908152602001604051809103902054146109ec57805160405163a41f772f60e01b815261061b919060040161517a565b5f6002885f013584604051602001610a1b92919091825260e01b6001600160e01b031916602082015260240190565b60408051601f1981840301815290829052610a35916153c8565b602060405180830381855afa158015610a50573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610a73919061518c565b90508086600801835f0151604051610a8b91906153c8565b90815260408051602092819003830181209390935560e0830181526002835284518284015284810180516001600160401b03908116858401525f60608601819052915181166080860152421660a085015260c0840181905284815260078a01909252902081518154829060ff19166001836005811115610b0d57610b0d614fda565b021790555060208201516001820190610b26908261541d565b506040828101516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090930151600390920180546001600160401b03191692841692909217909155830151610bca9116856154ec565b8251604051919550610bdb916153c8565b60408051918290038220908401516001600160401b031682529082907f9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf9060200160405180910390a3505080610c30906154ff565b9050610957565b50600483018190556001830154606490610c5b90600160401b900460ff1683615521565b1015610c7d57604051635943317f60e01b81526004810182905260240161061b565b5f610c93610c8a86611ec8565b60400151611fd3565b90505f610c9f87612160565b90505f600282604051610cb291906153c8565b602060405180830381855afa158015610ccd573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610cf0919061518c565b9050828114610d1c57604051631872fc8d60e01b8152600481018290526024810184905260440161061b565b5050506009909201805460ff1916600117905550505050565b610d3e82612335565b610d5e576040516330efa98b60e01b81526004810183905260240161061b565b5f610d6883611995565b5190506002816005811115610d7f57610d7f614fda565b14610d9f578060405163170cc93360e21b815260040161061b919061516c565b610826838361235e565b5f80610db36125ac565b60030154610dc19084615538565b9050801580610dd657506001600160401b0381115b15610df75760405163222d164360e21b81526004810184905260240161061b565b92915050565b6108268383836125d0565b610e1061279b565b5f610e196125ac565b90505f80610e26846127e5565b91509150610e3382612335565b610e3f57505050610ead565b5f8281526005840160205260409020546001600160a01b0316600482516005811115610e6d57610e6d614fda565b03610e92575f83815260088501602052604081208054919055610e908282612b1f565b505b610ea881610ea38460400151611113565b612b7d565b505050505b610eb5612b90565b50565b5f610ec16125ac565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff166003811115610efa57610efa614fda565b6003811115610f0b57610f0b614fda565b8152815461010090046001600160a01b0316602082015260018201546040808301919091526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0909101528101519091505f610f8182611995565b9050600183516003811115610f9857610f98614fda565b14610fb9578251604051633b0d540d60e21b815261061b9190600401615557565b600481516005811115610fce57610fce614fda565b03610fe457610fdc85612bb6565b505050505050565b5f80610ffb610ff289611ec8565b60400151612dd6565b509150915081841461102857846040015160405163089938b360e11b815260040161061b91815260200190565b806001600160401b031683606001516001600160401b031610806110615750806001600160401b03168560a001516001600160401b0316115b1561108a57604051632e19bc2d60e11b81526001600160401b038216600482015260240161061b565b5f878152600687016020908152604091829020805460ff1916600290811782550180546001600160401b034216600160401b810267ffffffffffffffff60401b19909216919091179091559151918252859189917f047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6910160405180910390a35050505050505050565b5f61111c6125ac565b60030154610df7906001600160401b038416615521565b5f61113d82611995565b6080015192915050565b6111528383836125d0565b61062457604051635bff683f60e11b81526004810184905260240161061b565b5f61117b6125ac565b90505f61118783611995565b519050600481600581111561119e5761119e614fda565b146111be578060405163170cc93360e21b815260040161061b919061516c565b5f8381526005830160205260409020546001600160a01b031633146111f957335b604051636e2ccd7560e11b815260040161061b9190614eda565b5f83815260088301602090815260408083208054908490556005860190925290912054610826906001600160a01b031682612b1f565b61123761279b565b5f6112406125ac565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff16600381111561127957611279614fda565b600381111561128a5761128a614fda565b8152815461010090046001600160a01b03166020820152600182015460408201526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c090910152905060038151600381111561130357611303614fda565b14611324578051604051633b0d540d60e21b815261061b9190600401615557565b60046113338260400151611995565b51600581111561134557611345614fda565b146113d7575f61135485611ec8565b90505f806113658360400151612dd6565b5091509150818460400151146113915760405163089938b360e11b81526004810183905260240161061b565b806001600160401b03168460c001516001600160401b031611156113d357604051632e19bc2d60e11b81526001600160401b038216600482015260240161061b565b5050505b6113e083612bb6565b50506113ea612b90565b5050565b5f6113f7611e55565b90505f8061141061140785611ec8565b6040015161302c565b915091508061143657604051632d07135360e01b8152811515600482015260240161061b565b5f828152600684016020526040902080546114509061513a565b90505f036114745760405163089938b360e11b81526004810183905260240161061b565b60015f83815260078501602052604090205460ff16600581111561149a5761149a614fda565b146114cd575f8281526007840160205260409081902054905163170cc93360e21b815261061b9160ff169060040161516c565b5f82815260068401602052604081206114e591614d6d565b5f828152600784016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160c01b026001600160c01b0390931692909217928390558451600160801b9093041682529181019190915283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a250505050565b5f61157d61279b565b611589848484346131e8565b9050611593612b90565b9392505050565b5f6115a36125ac565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff1660038111156115dc576115dc614fda565b60038111156115ed576115ed614fda565b8152815461010090046001600160a01b0316602082015260018083015460408301526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0909101529091508151600381111561166657611666614fda565b14158015611687575060038151600381111561168457611684614fda565b14155b156116a8578051604051633b0d540d60e21b815261061b9190600401615557565b5f6116b68260400151611995565b905080606001516001600160401b03165f036116e8576040516339b894f960e21b81526004810185905260240161061b565b6005600160991b016001600160a01b031663ee5b48eb611715846040015184606001518560800151611e79565b6040518263ffffffff1660e01b8152600401611731919061517a565b6020604051808303815f875af115801561174d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611771919061518c565b5050505050565b5f611781611e55565b5f838152600682016020526040902080549192509061179f9061513a565b90505f036117c35760405163089938b360e11b81526004810183905260240161061b565b60015f83815260078301602052604090205460ff1660058111156117e9576117e9614fda565b1461181c575f8281526007820160205260409081902054905163170cc93360e21b815261061b9160ff169060040161516c565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb916118559190600401615571565b6020604051808303815f875af1158015611871573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610624919061518c565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806118de575080546001600160401b03808416911610155b156118fc5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b17815561192683613394565b805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b5f61197b61279b565b6119868233346133a5565b9050611990612b90565b919050565b61199d614da4565b5f6119a6611e55565b5f84815260078201602052604090819020815160e0810190925280549293509091829060ff1660058111156119dd576119dd614fda565b60058111156119ee576119ee614fda565b8152602001600182018054611a029061513a565b80601f0160208091040260200160405190810160405280929190818152602001828054611a2e9061513a565b8015611a795780601f10611a5057610100808354040283529160200191611a79565b820191905f5260205f20905b815481529060010190602001808311611a5c57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b9091048116608083015260039092015490911660a0909101529392505050565b5f80611ae1611e55565b9050806008018484604051611af79291906155fb565b90815260200160405180910390205491505092915050565b5f80611b196125ac565b5f868152600682016020526040808220815160e0810190925280549394509192909190829060ff166003811115611b5257611b52614fda565b6003811115611b6357611b63614fda565b8152815461010090046001600160a01b0316602082015260018201546040808301919091526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0909101528101519091505f611bd982611995565b9050600283516003811115611bf057611bf0614fda565b14611c11578251604051633b0d540d60e21b815261061b9190600401615557565b60208301516001600160a01b03163314611cad575f8281526005850160205260409020546001600160a01b03163314611c4a57336111df565b5f82815260058501602052604090205460a0820151611c7991600160b01b90046001600160401b03169061560a565b6001600160401b0316421015611cad5760405163fb6ce63f60e01b81526001600160401b034216600482015260240161061b565b600281516005811115611cc257611cc2614fda565b03611df05760028401546080840151611ce4916001600160401b03169061560a565b6001600160401b0316421015611d185760405163fb6ce63f60e01b81526001600160401b034216600482015260240161061b565b8615611d2a57611d28828761235e565b505b5f8881526006850160205260409020805460ff1916600317905560608301516080820151611d63918491611d5e919061562a565b613677565b505f898152600686016020526040812060020180546001600160401b03909316600160c01b026001600160c01b0390931692909217909155611da4846137c1565b5f8a81526007870160205260408082208390555191925084918b917f366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed5791a3151594506115939350505050565b600481516005811115611e0557611e05614fda565b03611e3957611e13836137c1565b5f898152600786016020526040902055611e2c88612bb6565b6001945050505050611593565b805160405163170cc93360e21b815261061b919060040161516c565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0090565b604080515f6020820152600360e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b60408051606080820183525f8083526020830152918101919091526040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611f2c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611f539190810190615655565b9150915080611f7557604051636b2f19e960e01b815260040160405180910390fd5b815115611f9b578151604051636ba589a560e01b8152600481019190915260240161061b565b60208201516001600160a01b031615611fcc578160200151604051624de75d60e31b815260040161061b9190614eda565b5092915050565b5f815160261461200857815160405163cc92daa160e01b815263ffffffff90911660048201526026602482015260440161061b565b5f805b60028110156120575761201f816001615727565b61202a906008615521565b61ffff1684828151811061204057612040615217565b016020015160f81c901b919091179060010161200b565b5061ffff8116156120815760405163407b587360e01b815261ffff8216600482015260240161061b565b5f805b60048110156120dc57612098816003615727565b6120a3906008615521565b63ffffffff16856120b58360026154ec565b815181106120c5576120c5615217565b016020015160f81c901b9190911790600101612084565b5063ffffffff81161561210257604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156121575761211981601f615727565b612124906008615521565b866121308360066154ec565b8151811061214057612140615217565b016020015160f81c901b9190911790600101612105565b50949350505050565b60605f8083356020850135601461217c878701604089016151b7565b61218960608901896151d2565b60405160f09790971b6001600160f01b0319166020880152602287019590955250604285019290925260e090811b6001600160e01b0319908116606286015260609290921b6001600160601b03191660668501529190911b16607a820152607e0160405160208183030381529060405290505f5b61220a60608501856151d2565b9050811015611fcc578161222160608601866151d2565b8381811061223157612231615217565b9050602002810190612243919061522b565b61224d908061573a565b905061225c60608701876151d2565b8481811061226c5761226c615217565b905060200281019061227e919061522b565b612288908061573a565b61229560608901896151d2565b868181106122a5576122a5615217565b90506020028101906122b7919061522b565b6122c590602081019061573a565b6122d260608b018b6151d2565b888181106122e2576122e2615217565b90506020028101906122f4919061522b565b612305906060810190604001614f45565b60405160200161231b979695949392919061577c565b60408051601f1981840301815291905291506001016121fd565b5f8061233f6125ac565b5f938452600501602052505060409020546001600160a01b0316151590565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa1580156123a9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526123d09190810190615655565b91509150806123f257604051636b2f19e960e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612435573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612459919061518c565b82511461247f578151604051636ba589a560e01b8152600481019190915260240161061b565b60208201516001600160a01b0316156124b0578160200151604051624de75d60e31b815260040161061b9190614eda565b5f806124bf8460400151613944565b915091508187146124e65760405163089938b360e11b81526004810188905260240161061b565b5f6124ef6125ac565b5f8981526005820160205260409020600101549091506001600160401b039081169083161115612582575f88815260058201602090815260409182902060010180546001600160401b0319166001600160401b038616908117909155915191825289917fec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435910160405180910390a26125a1565b5f8881526005820160205260409020600101546001600160401b031691505b509695505050505050565b7f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0090565b5f806125da6125ac565b90505f6125e686613b35565b90506125f186612335565b61260057600192505050611593565b5f8681526005830160205260409020546001600160a01b0316331461262557336111df565b5f86815260058301602052604090205460a082015161265491600160b01b90046001600160401b03169061560a565b6001600160401b03168160c001516001600160401b0316101561269b5760c081015160405163fb6ce63f60e01b81526001600160401b03909116600482015260240161061b565b5f85156126b3576126ac878661235e565b90506126d1565b505f8681526005830160205260409020600101546001600160401b03165b600483015460408301515f916001600160a01b031690634f22429f906126f690611113565b60a086015160c08701516040516001600160e01b031960e086901b168152612726939291829189906004016157e5565b602060405180830381865afa158015612741573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612765919061518c565b905080846008015f8a81526020019081526020015f205f82825461278991906154ec565b90915550501515979650505050505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f008054600119016127df57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f6127ee614da4565b5f6127f7611e55565b90505f8061280761140787611ec8565b91509150801561282e57604051632d07135360e01b8152811515600482015260240161061b565b5f828152600784016020526040808220815160e081019092528054829060ff16600581111561285f5761285f614fda565b600581111561287057612870614fda565b81526020016001820180546128849061513a565b80601f01602080910402602001604051908101604052809291908181526020018280546128b09061513a565b80156128fb5780601f106128d2576101008083540402835291602001916128fb565b820191905f5260205f20905b8154815290600101906020018083116128de57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561296657612966614fda565b14158015612987575060018151600581111561298457612984614fda565b14155b156129a857805160405163170cc93360e21b815261061b919060040161516c565b6003815160058111156129bd576129bd614fda565b036129cb57600481526129d0565b600581525b8360080181602001516040516129e691906153c8565b90815260408051602092819003830190205f908190558581526007870190925290208151815483929190829060ff19166001836005811115612a2a57612a2a614fda565b021790555060208201516001820190612a43908261541d565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b0319169190921617905580516005811115612ae857612ae8614fda565b60405184907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a39196919550909350505050565b6040516327ad555d60e11b81526001600160a01b0383166004820152602481018290526001600160991b0190634f5aaaba906044015f604051808303815f87803b158015612b6b575f80fd5b505af1158015610fdc573d5f803e3d5ffd5b6113ea6001600160a01b03831682613e0d565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f612bbf6125ac565b5f838152600682016020526040808220815160e0810190925280549394509192909190829060ff166003811115612bf857612bf8614fda565b6003811115612c0957612c09614fda565b8152815461010090046001600160a01b0316602082015260018201546040808301919091526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c090910152810151909150612c7d613ea0565b8260800151612c8c919061560a565b6001600160401b0316421015612cc05760405163fb6ce63f60e01b81526001600160401b034216600482015260240161061b565b5f848152600684016020908152604080832080546001600160a81b03191681556001810184905560020183905560078601909152812080549082905590808215612d7b575f84815260058701602052604090205461271090612d2d90600160a01b900461ffff1685615521565b612d379190615538565b915081866008015f8681526020019081526020015f205f828254612d5b91906154ec565b90915550612d6b90508284615727565b9050612d7b856020015182612b1f565b612d908560200151610ea38760600151611113565b6040805182815260208101849052859189917f8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993910160405180910390a350505050505050565b5f805f8351603614612e0d57835160405163cc92daa160e01b815263ffffffff90911660048201526036602482015260440161061b565b5f805b6002811015612e5c57612e24816001615727565b612e2f906008615521565b61ffff16868281518110612e4557612e45615217565b016020015160f81c901b9190911790600101612e10565b5061ffff811615612e865760405163407b587360e01b815261ffff8216600482015260240161061b565b5f805b6004811015612ee157612e9d816003615727565b612ea8906008615521565b63ffffffff1687612eba8360026154ec565b81518110612eca57612eca615217565b016020015160f81c901b9190911790600101612e89565b5063ffffffff8116600314612f0957604051635b60892f60e01b815260040160405180910390fd5b5f805b6020811015612f5e57612f2081601f615727565b612f2b906008615521565b88612f378360066154ec565b81518110612f4757612f47615217565b016020015160f81c901b9190911790600101612f0c565b505f805b6008811015612fbd57612f76816007615727565b612f81906008615521565b6001600160401b031689612f968360266154ec565b81518110612fa657612fa6615217565b016020015160f81c901b9190911790600101612f62565b505f805b600881101561301c57612fd5816007615727565b612fe0906008615521565b6001600160401b03168a612ff583602e6154ec565b8151811061300557613005615217565b016020015160f81c901b9190911790600101612fc1565b5091989097509095509350505050565b5f80825160271461306257825160405163cc92daa160e01b815263ffffffff90911660048201526027602482015260440161061b565b5f805b60028110156130b157613079816001615727565b613084906008615521565b61ffff1685828151811061309a5761309a615217565b016020015160f81c901b9190911790600101613065565b5061ffff8116156130db5760405163407b587360e01b815261ffff8216600482015260240161061b565b5f805b6004811015613136576130f2816003615727565b6130fd906008615521565b63ffffffff168661310f8360026154ec565b8151811061311f5761311f615217565b016020015160f81c901b91909117906001016130de565b5063ffffffff811660021461315e57604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156131b35761317581601f615727565b613180906008615521565b8761318c8360066154ec565b8151811061319c5761319c615217565b016020015160f81c901b9190911790600101613161565b505f866026815181106131c8576131c8615217565b016020015191976001600160f81b03199092161515965090945050505050565b5f806131f26125ac565b600281015490915061ffff600160401b9091048116908616108061321b575061271061ffff8616115b1561323f57604051635f12e6c360e11b815261ffff8616600482015260240161061b565b60028101546001600160401b03908116908516101561327b576040516202a06d60e11b81526001600160401b038516600482015260240161061b565b805483108061328d5750806001015483115b156132ae5760405163222d164360e21b81526004810184905260240161061b565b825f6132b982610da9565b90505f6132c68983613ebb565b905060405180608001604052806132da3390565b6001600160a01b03908116825261ffff808c166020808501919091526001600160401b03808d166040808701919091525f60609687018190528881526005909b018352998a902086518154938801519b8801518316600160b01b0267ffffffffffffffff60b01b199c909516600160a01b026001600160b01b0319909416951694909417919091179890981617815591015160019091018054919095166001600160401b0319909116179093555090915050949350505050565b61339c614418565b610eb581614463565b5f806133af6125ac565b90505f6133bb84610da9565b90505f6133c787611995565b90506133d287612335565b6133f2576040516330efa98b60e01b81526004810188905260240161061b565b60028151600581111561340757613407614fda565b1461342857805160405163170cc93360e21b815261061b919060040161516c565b5f828260800151613439919061560a565b905083600201600a9054906101000a90046001600160401b031682604001516134629190615813565b6001600160401b0316816001600160401b0316111561349f57604051636d51fe0560e11b81526001600160401b038216600482015260240161061b565b5f806134ab8a84613677565b915091505f8a836040516020016134d992919091825260c01b6001600160c01b031916602082015260280190565b60408051601f19818403018152828252805160209091012060e08301909152915080600181526001600160a01b038c1660208083019190915260408083018f90526001600160401b03808b1660608501525f6080850181905290881660a085015260c090930183905284835260068b01909152902081518154829060ff1916600183600381111561356c5761356c614fda565b02179055506020828101518254610100600160a81b0319166101006001600160a01b039283160217835560408085015160018501556060808601516002909501805460808089015160a08a015160c0909a01516001600160401b03998a166001600160801b031990941693909317600160401b918a1691909102176001600160801b0316600160801b998916999099026001600160c01b031698909817600160c01b91881691909102179055815189861681528a861694810194909452938b1690830152918101859052908c16918d9184917fb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426910160405180910390a49a9950505050505050505050565b5f805f613682611e55565b5f868152600782016020526040902060020154909150600160801b90046001600160401b03166136b285826144d7565b5f6136bc876146fc565b5f8881526007850160205260408120600201805467ffffffffffffffff60801b1916600160801b6001600160401b038b16021790559091506005600160991b0163ee5b48eb61370c8a858b611e79565b6040518263ffffffff1660e01b8152600401613728919061517a565b6020604051808303815f875af1158015613744573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613768919061518c565b604080516001600160401b038a811682526020820184905282519394508516928b927f07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df928290030190a3909450925050505b9250929050565b5f806137cb6125ac565b90505f6137db8460400151611995565b90505f6003825160058111156137f3576137f3614fda565b1480613811575060048251600581111561380f5761380f614fda565b145b15613821575060c081015161385e565b60028251600581111561383657613836614fda565b0361384257504261385e565b815160405163170cc93360e21b815261061b919060040161516c565b84608001516001600160401b0316816001600160401b03161161388557505f949350505050565b600483015460608601516001600160a01b0390911690634f22429f906138aa90611113565b60a085015160808901516040808b01515f90815260058a016020528190206001015490516001600160e01b031960e087901b1681526138fc9493929188916001600160401b03909116906004016157e5565b602060405180830381865afa158015613917573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061393b919061518c565b95945050505050565b5f808251602e1461397a57825160405163cc92daa160e01b815263ffffffff9091166004820152602e602482015260440161061b565b5f805b60028110156139c957613991816001615727565b61399c906008615521565b61ffff168582815181106139b2576139b2615217565b016020015160f81c901b919091179060010161397d565b5061ffff8116156139f35760405163407b587360e01b815261ffff8216600482015260240161061b565b5f805b6004811015613a4e57613a0a816003615727565b613a15906008615521565b63ffffffff1686613a278360026154ec565b81518110613a3757613a37615217565b016020015160f81c901b91909117906001016139f6565b5063ffffffff811615613a7457604051635b60892f60e01b815260040160405180910390fd5b5f805b6020811015613ac957613a8b81601f615727565b613a96906008615521565b87613aa28360066154ec565b81518110613ab257613ab2615217565b016020015160f81c901b9190911790600101613a77565b505f805b6008811015613b2857613ae1816007615727565b613aec906008615521565b6001600160401b031688613b018360266154ec565b81518110613b1157613b11615217565b016020015160f81c901b9190911790600101613acd565b5090969095509350505050565b613b3d614da4565b5f613b46611e55565b5f848152600782016020526040808220815160e0810190925280549394509192909190829060ff166005811115613b7f57613b7f614fda565b6005811115613b9057613b90614fda565b8152602001600182018054613ba49061513a565b80601f0160208091040260200160405190810160405280929190818152602001828054613bd09061513a565b8015613c1b5780601f10613bf257610100808354040283529160200191613c1b565b820191905f5260205f20905b815481529060010190602001808311613bfe57829003601f168201915b50505091835250506002828101546001600160401b038082166020850152600160401b820481166040850152600160801b820481166060850152600160c01b9091048116608084015260039093015490921660a09091015290915081516005811115613c8957613c89614fda565b14613cbc575f8481526007830160205260409081902054905163170cc93360e21b815261061b9160ff169060040161516c565b60038152426001600160401b031660c08201525f84815260078301602052604090208151815483929190829060ff19166001836005811115613d0057613d00614fda565b021790555060208201516001820190613d19908261541d565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b031916919092161790555f613db68582613677565b6080840151604080516001600160401b03909216825242602083015291935083925087917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a3509392505050565b80471015613e30573060405163cd78605960e01b815260040161061b9190614eda565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613e79576040519150601f19603f3d011682016040523d82523d5f602084013e613e7e565b606091505b505090508061062457604051630a12f52160e11b815260040160405180910390fd5b5f613ea9611e55565b600101546001600160401b0316919050565b5f613ec4611e55565b6009015460ff16613ee857604051637fab81e560e01b815260040160405180910390fd5b5f613ef1611e55565b905042613f046060860160408701614f45565b6001600160401b0316111580613f3e5750613f226202a300426154ec565b613f326060860160408701614f45565b6001600160401b031610155b15613f7857613f536060850160408601614f45565b604051635879da1360e11b81526001600160401b03909116600482015260240161061b565b613f8d613f88606086018661583e565b614765565b613f9d613f88608086018661583e565b6030613fac602086018661573a565b905014613fde57613fc0602085018561573a565b6040516326475b2f60e11b815261061b925060040190815260200190565b613fe8848061573a565b90505f0361401557613ffa848061573a565b604051633e08a12560e11b815260040161061b929190615852565b5f60088201614024868061573a565b6040516140329291906155fb565b9081526020016040518091039020541461406b57614050848061573a565b60405163a41f772f60e01b815260040161061b929190615852565b614075835f6144d7565b6040805160e08101909152815481525f908190614181906020810161409a898061573a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050908252506020908101906140e2908a018a61573a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060200161412b60608a0160408b01614f45565b6001600160401b0316815260200161414660608a018a61583e565b61414f90615880565b815260200161416160808a018a61583e565b61416a90615880565b8152602001876001600160401b03168152506148ce565b5f8281526006860160205260409020919350915061419f828261541d565b5081600884016141af888061573a565b6040516141bd9291906155fb565b9081526040519081900360200181209190915563ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906141f990859060040161517a565b6020604051808303815f875af1158015614215573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614239919061518c565b6040805160e081019091529091508060018152602001614259898061573a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509385525050506001600160401b0389166020808401829052604080850184905260608501929092526080840183905260a0909301829052868252600788019092522081518154829060ff191660018360058111156142e8576142e8614fda565b021790555060208201516001820190614301908261541d565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b031916919092161790558061439e888061573a565b6040516143ac9291906155fb565b6040518091039020847fb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430898b60400160208101906143ea9190614f45565b604080516001600160401b0393841681529290911660208301520160405180910390a4509095945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661446157604051631afcd79f60e31b815260040160405180910390fd5b565b61446b614418565b61447481614abb565b61447c614ad4565b610eb56060820135608083013561449960c0850160a08601614f45565b6144a960e0860160c08701615947565b6144ba610100870160e08801615960565b6101008701356144d261014089016101208a016151b7565b614ae4565b5f6144e0611e55565b90505f826001600160401b0316846001600160401b0316111561450e57614507838561562a565b905061451b565b614518848461562a565b90505b6040805160808101825260028401548082526003850154602083015260048501549282019290925260058401546001600160401b031660608201524291158061457d575060018401548151614579916001600160401b0316906154ec565b8210155b156145a3576001600160401b0383166060820152818152604081015160208201526145c2565b82816060018181516145b5919061560a565b6001600160401b03169052505b60608101516145d2906064615813565b602082015160018601546001600160401b0392909216916145fd9190600160401b900460ff16615521565b101561462d57606081015160405163dfae880160e01b81526001600160401b03909116600482015260240161061b565b856001600160401b03168160400181815161464891906154ec565b9052506040810180516001600160401b0387169190614668908390615727565b9052506001840154604082015160649161468d91600160401b90910460ff1690615521565b10156146b4578060400151604051635943317f60e01b815260040161061b91815260200190565b80516002850155602081015160038501556040810151600485015560600151600590930180546001600160401b0319166001600160401b039094169390931790925550505050565b5f80614706611e55565b5f848152600782016020526040902060020180549192509060089061473a90600160401b90046001600160401b0316615980565b91906101000a8154816001600160401b0302191690836001600160401b031602179055915050919050565b6147726020820182614eee565b63ffffffff16158015614792575061478d60208201826151d2565b151590505b156147d9576147a46020820182614eee565b6147b160208301836151d2565b60405163c08a0f1d60e01b815263ffffffff909316600484015260248301525060440161061b565b6147e660208201826151d2565b90506147f56020830183614eee565b63ffffffff16111561480e576147a46020820182614eee565b60015b61481e60208301836151d2565b90508110156113ea5761483460208301836151d2565b61483f600184615727565b81811061484e5761484e615217565b905060200201602081019061486391906151b7565b6001600160a01b031661487960208401846151d2565b8381811061488957614889615217565b905060200201602081019061489e91906151b7565b6001600160a01b031610156148c657604051630dbc8d5f60e31b815260040160405180910390fd5b600101614811565b5f60608260400151516030146148f75760405163180ffa0d60e01b815260040160405180910390fd5b82516020808501518051604080880151606089015160808a01518051908701515193515f98614938988a98600198929792969095909490939092910161599b565b60405160208183030381529060405290505f5b846080015160200151518110156149aa5781856080015160200151828151811061497757614977615217565b6020026020010151604051602001614990929190615a55565b60408051601f19818403018152919052915060010161494b565b5060a08401518051602091820151516040516149ca938593929101615a86565b60405160208183030381529060405290505f5b8460a001516020015151811015614a3c57818560a00151602001518281518110614a0957614a09615217565b6020026020010151604051602001614a22929190615a55565b60408051601f1981840301815291905291506001016149dd565b5060c0840151604051614a53918391602001615ac1565b6040516020818303038152906040529050600281604051614a7491906153c8565b602060405180830381855afa158015614a8f573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190614ab2919061518c565b94909350915050565b614ac3614418565b614acb614c7a565b610eb581614c82565b614adc614418565b614461614d65565b614aec614418565b5f614af56125ac565b905061ffff85161580614b0d575061271061ffff8616115b15614b3157604051635f12e6c360e11b815261ffff8616600482015260240161061b565b86881115614b555760405163222d164360e21b81526004810189905260240161061b565b60ff84161580614b685750600a60ff8516115b15614b8b5760405163170db35960e31b815260ff8516600482015260240161061b565b614b93613ea0565b6001600160401b0316866001600160401b03161015614bcf576040516202a06d60e11b81526001600160401b038716600482015260240161061b565b825f03614bef5760405163a733007160e01b815260040160405180910390fd5b96875560018701959095556002860180546001600160401b039590951669ffffffffffffffffffff1990951694909417600160401b61ffff94909416939093029290921767ffffffffffffffff60501b191660ff91909116600160501b02179091556003830155600490910180546001600160a01b0319166001600160a01b03909216919091179055565b614461614418565b614c8a614418565b5f614c93611e55565b8235815590506014614cab6060840160408501615960565b60ff161180614cca5750614cc56060830160408401615960565b60ff16155b15614cfe57614cdf6060830160408401615960565b604051634a59bbff60e11b815260ff909116600482015260240161061b565b614d0e6060830160408401615960565b60018201805460ff92909216600160401b0260ff60401b19909216919091179055614d3f6040830160208401614f45565b60019190910180546001600160401b0319166001600160401b0390921691909117905550565b612b90614418565b508054614d799061513a565b5f825580601f10614d88575050565b601f0160209004905f5260205f2090810190610eb59190614de1565b6040805160e08101909152805f81526060602082018190525f604083018190529082018190526080820181905260a0820181905260c09091015290565b5b80821115614df5575f8155600101614de2565b5090565b8015158114610eb5575f80fd5b803563ffffffff81168114611990575f80fd5b5f805f60608486031215614e2b575f80fd5b833592506020840135614e3d81614df9565b9150614e4b60408501614e06565b90509250925092565b5f60208284031215614e64575f80fd5b5035919050565b5f8060408385031215614e7c575f80fd5b82356001600160401b03811115614e91575f80fd5b830160808186031215614ea2575f80fd5b9150614eb060208401614e06565b90509250929050565b5f8060408385031215614eca575f80fd5b82359150614eb060208401614e06565b6001600160a01b0391909116815260200190565b5f60208284031215614efe575f80fd5b61159382614e06565b5f8060408385031215614f18575f80fd5b614f2183614e06565b946020939093013593505050565b80356001600160401b0381168114611990575f80fd5b5f60208284031215614f55575f80fd5b61159382614f2f565b803561ffff81168114611990575f80fd5b5f805f60608486031215614f81575f80fd5b83356001600160401b03811115614f96575f80fd5b840160a08187031215614fa7575f80fd5b9250614fb560208501614f5e565b9150614e4b60408501614f2f565b5f6101408284031215614fd4575f80fd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b60068110614ffe57614ffe614fda565b9052565b5f5b8381101561501c578181015183820152602001615004565b50505f910152565b5f815180845261503b816020860160208601615002565b601f01601f19169290920160200192915050565b60208152615061602082018351614fee565b5f602083015160e0604084015261507c610100840182615024565b905060408401516001600160401b0380821660608601528060608701511660808601528060808701511660a08601528060a08701511660c08601528060c08701511660e086015250508091505092915050565b5f80602083850312156150e0575f80fd5b82356001600160401b03808211156150f6575f80fd5b818501915085601f830112615109575f80fd5b813581811115615117575f80fd5b866020828501011115615128575f80fd5b60209290920196919550909350505050565b600181811c9082168061514e57607f821691505b602082108103614fd457634e487b7160e01b5f52602260045260245ffd5b60208101610df78284614fee565b602081525f6115936020830184615024565b5f6020828403121561519c575f80fd5b5051919050565b6001600160a01b0381168114610eb5575f80fd5b5f602082840312156151c7575f80fd5b8135611593816151a3565b5f808335601e198436030181126151e7575f80fd5b8301803591506001600160401b03821115615200575f80fd5b6020019150600581901b36038213156137ba575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e1983360301811261523f575f80fd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561527f5761527f615249565b60405290565b604080519081016001600160401b038111828210171561527f5761527f615249565b604051601f8201601f191681016001600160401b03811182821017156152cf576152cf615249565b604052919050565b5f6001600160401b038211156152ef576152ef615249565b50601f01601f191660200190565b5f82601f83011261530c575f80fd5b813561531f61531a826152d7565b6152a7565b818152846020838601011115615333575f80fd5b816020850160208301375f918101602001919091529392505050565b5f6060823603121561535f575f80fd5b61536761525d565b82356001600160401b038082111561537d575f80fd5b615389368387016152fd565b8352602085013591508082111561539e575f80fd5b506153ab368286016152fd565b6020830152506153bd60408401614f2f565b604082015292915050565b5f825161523f818460208701615002565b601f82111561062457805f5260205f20601f840160051c810160208510156153fe5750805b601f840160051c820191505b81811015611771575f815560010161540a565b81516001600160401b0381111561543657615436615249565b61544a81615444845461513a565b846153d9565b602080601f83116001811461547d575f84156154665750858301515b5f19600386901b1c1916600185901b178555610fdc565b5f85815260208120601f198616915b828110156154ab5788860151825594840194600190910190840161548c565b50858210156154c857878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610df757610df76154d8565b5f63ffffffff808316818103615517576155176154d8565b6001019392505050565b8082028115828204841417610df757610df76154d8565b5f8261555257634e487b7160e01b5f52601260045260245ffd5b500490565b602081016004831061556b5761556b614fda565b91905290565b5f60208083525f84546155838161513a565b806020870152604060018084165f81146155a457600181146155c0576155ed565b60ff19851660408a0152604084151560051b8a010195506155ed565b895f5260205f205f5b858110156155e45781548b82018601529083019088016155c9565b8a016040019650505b509398975050505050505050565b818382375f9101908152919050565b6001600160401b03818116838216019080821115611fcc57611fcc6154d8565b6001600160401b03828116828216039080821115611fcc57611fcc6154d8565b805161199081614df9565b5f8060408385031215615666575f80fd5b82516001600160401b038082111561567c575f80fd5b908401906060828703121561568f575f80fd5b61569761525d565b825181526020808401516156aa816151a3565b828201526040840151838111156156bf575f80fd5b80850194505087601f8501126156d3575f80fd5b835192506156e361531a846152d7565b83815288828587010111156156f6575f80fd5b61570584838301848801615002565b8060408401525081955061571a81880161564a565b9450505050509250929050565b81810381811115610df757610df76154d8565b5f808335601e1984360301811261574f575f80fd5b8301803591506001600160401b03821115615768575f80fd5b6020019150368190038213156137ba575f80fd5b5f885161578d818460208d01615002565b60e089901b6001600160e01b031916908301908152868860048301378681019050600481015f8152858782375060c09390931b6001600160c01b0319166004939094019283019390935250600c019695505050505050565b9485526001600160401b03938416602086015291831660408501528216606084015216608082015260a00190565b6001600160401b03818116838216028082169190828114615836576158366154d8565b505092915050565b5f8235603e1983360301811261523f575f80fd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60408236031215615890575f80fd5b615898615285565b6158a183614e06565b81526020808401356001600160401b03808211156158bd575f80fd5b9085019036601f8301126158cf575f80fd5b8135818111156158e1576158e1615249565b8060051b91506158f28483016152a7565b818152918301840191848101903684111561590b575f80fd5b938501935b838510156159355784359250615925836151a3565b8282529385019390850190615910565b94860194909452509295945050505050565b5f60208284031215615957575f80fd5b61159382614f5e565b5f60208284031215615970575f80fd5b813560ff81168114611593575f80fd5b5f6001600160401b03808316818103615517576155176154d8565b61ffff60f01b8a60f01b1681525f63ffffffff60e01b808b60e01b166002840152896006840152808960e01b1660268401525086516159e181602a850160208b01615002565b8651908301906159f881602a840160208b01615002565b60c087901b6001600160c01b031916602a9290910191820152615a2a603282018660e01b6001600160e01b0319169052565b615a43603682018560e01b6001600160e01b0319169052565b603a019b9a5050505050505050505050565b5f8351615a66818460208801615002565b60609390931b6001600160601b0319169190920190815260140192915050565b5f8451615a97818460208901615002565b6001600160e01b031960e095861b8116919093019081529290931b16600482015260080192915050565b5f8351615ad2818460208801615002565b60c09390931b6001600160c01b031916919092019081526008019291505056fea164736f6c6343000819000a", +} + +// NativeTokenStakingManagerABI is the input ABI used to generate the binding from. +// Deprecated: Use NativeTokenStakingManagerMetaData.ABI instead. +var NativeTokenStakingManagerABI = NativeTokenStakingManagerMetaData.ABI + +// NativeTokenStakingManagerBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use NativeTokenStakingManagerMetaData.Bin instead. +var NativeTokenStakingManagerBin = NativeTokenStakingManagerMetaData.Bin + +// DeployNativeTokenStakingManager deploys a new Ethereum contract, binding an instance of NativeTokenStakingManager to it. +func DeployNativeTokenStakingManager(auth *bind.TransactOpts, backend bind.ContractBackend, init uint8) (common.Address, *types.Transaction, *NativeTokenStakingManager, error) { + parsed, err := NativeTokenStakingManagerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(NativeTokenStakingManagerBin), backend, init) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &NativeTokenStakingManager{NativeTokenStakingManagerCaller: NativeTokenStakingManagerCaller{contract: contract}, NativeTokenStakingManagerTransactor: NativeTokenStakingManagerTransactor{contract: contract}, NativeTokenStakingManagerFilterer: NativeTokenStakingManagerFilterer{contract: contract}}, nil +} + +// NativeTokenStakingManager is an auto generated Go binding around an Ethereum contract. +type NativeTokenStakingManager struct { + NativeTokenStakingManagerCaller // Read-only binding to the contract + NativeTokenStakingManagerTransactor // Write-only binding to the contract + NativeTokenStakingManagerFilterer // Log filterer for contract events +} + +// NativeTokenStakingManagerCaller is an auto generated read-only Go binding around an Ethereum contract. +type NativeTokenStakingManagerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// NativeTokenStakingManagerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type NativeTokenStakingManagerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// NativeTokenStakingManagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type NativeTokenStakingManagerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// NativeTokenStakingManagerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type NativeTokenStakingManagerSession struct { + Contract *NativeTokenStakingManager // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// NativeTokenStakingManagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type NativeTokenStakingManagerCallerSession struct { + Contract *NativeTokenStakingManagerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// NativeTokenStakingManagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type NativeTokenStakingManagerTransactorSession struct { + Contract *NativeTokenStakingManagerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// NativeTokenStakingManagerRaw is an auto generated low-level Go binding around an Ethereum contract. +type NativeTokenStakingManagerRaw struct { + Contract *NativeTokenStakingManager // Generic contract binding to access the raw methods on +} + +// NativeTokenStakingManagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type NativeTokenStakingManagerCallerRaw struct { + Contract *NativeTokenStakingManagerCaller // Generic read-only contract binding to access the raw methods on +} + +// NativeTokenStakingManagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type NativeTokenStakingManagerTransactorRaw struct { + Contract *NativeTokenStakingManagerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewNativeTokenStakingManager creates a new instance of NativeTokenStakingManager, bound to a specific deployed contract. +func NewNativeTokenStakingManager(address common.Address, backend bind.ContractBackend) (*NativeTokenStakingManager, error) { + contract, err := bindNativeTokenStakingManager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &NativeTokenStakingManager{NativeTokenStakingManagerCaller: NativeTokenStakingManagerCaller{contract: contract}, NativeTokenStakingManagerTransactor: NativeTokenStakingManagerTransactor{contract: contract}, NativeTokenStakingManagerFilterer: NativeTokenStakingManagerFilterer{contract: contract}}, nil +} + +// NewNativeTokenStakingManagerCaller creates a new read-only instance of NativeTokenStakingManager, bound to a specific deployed contract. +func NewNativeTokenStakingManagerCaller(address common.Address, caller bind.ContractCaller) (*NativeTokenStakingManagerCaller, error) { + contract, err := bindNativeTokenStakingManager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerCaller{contract: contract}, nil +} + +// NewNativeTokenStakingManagerTransactor creates a new write-only instance of NativeTokenStakingManager, bound to a specific deployed contract. +func NewNativeTokenStakingManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*NativeTokenStakingManagerTransactor, error) { + contract, err := bindNativeTokenStakingManager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerTransactor{contract: contract}, nil +} + +// NewNativeTokenStakingManagerFilterer creates a new log filterer instance of NativeTokenStakingManager, bound to a specific deployed contract. +func NewNativeTokenStakingManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*NativeTokenStakingManagerFilterer, error) { + contract, err := bindNativeTokenStakingManager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerFilterer{contract: contract}, nil +} + +// bindNativeTokenStakingManager binds a generic wrapper to an already deployed contract. +func bindNativeTokenStakingManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := NativeTokenStakingManagerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_NativeTokenStakingManager *NativeTokenStakingManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _NativeTokenStakingManager.Contract.NativeTokenStakingManagerCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_NativeTokenStakingManager *NativeTokenStakingManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.NativeTokenStakingManagerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_NativeTokenStakingManager *NativeTokenStakingManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.NativeTokenStakingManagerTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _NativeTokenStakingManager.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.contract.Transact(opts, method, params...) +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) ADDRESSLENGTH(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "ADDRESS_LENGTH") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ADDRESSLENGTH() (uint32, error) { + return _NativeTokenStakingManager.Contract.ADDRESSLENGTH(&_NativeTokenStakingManager.CallOpts) +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) ADDRESSLENGTH() (uint32, error) { + return _NativeTokenStakingManager.Contract.ADDRESSLENGTH(&_NativeTokenStakingManager.CallOpts) +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) BIPSCONVERSIONFACTOR(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "BIPS_CONVERSION_FACTOR") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) BIPSCONVERSIONFACTOR() (uint16, error) { + return _NativeTokenStakingManager.Contract.BIPSCONVERSIONFACTOR(&_NativeTokenStakingManager.CallOpts) +} + +// BIPSCONVERSIONFACTOR is a free data retrieval call binding the contract method 0xa9778a7a. +// +// Solidity: function BIPS_CONVERSION_FACTOR() view returns(uint16) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) BIPSCONVERSIONFACTOR() (uint16, error) { + return _NativeTokenStakingManager.Contract.BIPSCONVERSIONFACTOR(&_NativeTokenStakingManager.CallOpts) +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) BLSPUBLICKEYLENGTH(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "BLS_PUBLIC_KEY_LENGTH") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) BLSPUBLICKEYLENGTH() (uint8, error) { + return _NativeTokenStakingManager.Contract.BLSPUBLICKEYLENGTH(&_NativeTokenStakingManager.CallOpts) +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) BLSPUBLICKEYLENGTH() (uint8, error) { + return _NativeTokenStakingManager.Contract.BLSPUBLICKEYLENGTH(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) MAXIMUMCHURNPERCENTAGELIMIT(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "MAXIMUM_CHURN_PERCENTAGE_LIMIT") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) MAXIMUMCHURNPERCENTAGELIMIT() (uint8, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMCHURNPERCENTAGELIMIT(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) MAXIMUMCHURNPERCENTAGELIMIT() (uint8, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMCHURNPERCENTAGELIMIT(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMDELEGATIONFEEBIPS is a free data retrieval call binding the contract method 0x35455ded. +// +// Solidity: function MAXIMUM_DELEGATION_FEE_BIPS() view returns(uint16) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) MAXIMUMDELEGATIONFEEBIPS(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "MAXIMUM_DELEGATION_FEE_BIPS") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// MAXIMUMDELEGATIONFEEBIPS is a free data retrieval call binding the contract method 0x35455ded. +// +// Solidity: function MAXIMUM_DELEGATION_FEE_BIPS() view returns(uint16) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) MAXIMUMDELEGATIONFEEBIPS() (uint16, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMDELEGATIONFEEBIPS(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMDELEGATIONFEEBIPS is a free data retrieval call binding the contract method 0x35455ded. +// +// Solidity: function MAXIMUM_DELEGATION_FEE_BIPS() view returns(uint16) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) MAXIMUMDELEGATIONFEEBIPS() (uint16, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMDELEGATIONFEEBIPS(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) MAXIMUMREGISTRATIONEXPIRYLENGTH(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "MAXIMUM_REGISTRATION_EXPIRY_LENGTH") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) MAXIMUMREGISTRATIONEXPIRYLENGTH() (uint64, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMREGISTRATIONEXPIRYLENGTH(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) MAXIMUMREGISTRATIONEXPIRYLENGTH() (uint64, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMREGISTRATIONEXPIRYLENGTH(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMSTAKEMULTIPLIERLIMIT is a free data retrieval call binding the contract method 0x151d30d1. +// +// Solidity: function MAXIMUM_STAKE_MULTIPLIER_LIMIT() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) MAXIMUMSTAKEMULTIPLIERLIMIT(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "MAXIMUM_STAKE_MULTIPLIER_LIMIT") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// MAXIMUMSTAKEMULTIPLIERLIMIT is a free data retrieval call binding the contract method 0x151d30d1. +// +// Solidity: function MAXIMUM_STAKE_MULTIPLIER_LIMIT() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) MAXIMUMSTAKEMULTIPLIERLIMIT() (uint8, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMSTAKEMULTIPLIERLIMIT(&_NativeTokenStakingManager.CallOpts) +} + +// MAXIMUMSTAKEMULTIPLIERLIMIT is a free data retrieval call binding the contract method 0x151d30d1. +// +// Solidity: function MAXIMUM_STAKE_MULTIPLIER_LIMIT() view returns(uint8) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) MAXIMUMSTAKEMULTIPLIERLIMIT() (uint8, error) { + return _NativeTokenStakingManager.Contract.MAXIMUMSTAKEMULTIPLIERLIMIT(&_NativeTokenStakingManager.CallOpts) +} + +// NATIVEMINTER is a free data retrieval call binding the contract method 0x329c3e12. +// +// Solidity: function NATIVE_MINTER() view returns(address) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) NATIVEMINTER(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "NATIVE_MINTER") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// NATIVEMINTER is a free data retrieval call binding the contract method 0x329c3e12. +// +// Solidity: function NATIVE_MINTER() view returns(address) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) NATIVEMINTER() (common.Address, error) { + return _NativeTokenStakingManager.Contract.NATIVEMINTER(&_NativeTokenStakingManager.CallOpts) +} + +// NATIVEMINTER is a free data retrieval call binding the contract method 0x329c3e12. +// +// Solidity: function NATIVE_MINTER() view returns(address) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) NATIVEMINTER() (common.Address, error) { + return _NativeTokenStakingManager.Contract.NATIVEMINTER(&_NativeTokenStakingManager.CallOpts) +} + +// POSVALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xafb98096. +// +// Solidity: function POS_VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) POSVALIDATORMANAGERSTORAGELOCATION(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "POS_VALIDATOR_MANAGER_STORAGE_LOCATION") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// POSVALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xafb98096. +// +// Solidity: function POS_VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) POSVALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _NativeTokenStakingManager.Contract.POSVALIDATORMANAGERSTORAGELOCATION(&_NativeTokenStakingManager.CallOpts) +} + +// POSVALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xafb98096. +// +// Solidity: function POS_VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) POSVALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _NativeTokenStakingManager.Contract.POSVALIDATORMANAGERSTORAGELOCATION(&_NativeTokenStakingManager.CallOpts) +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) PCHAINBLOCKCHAINID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "P_CHAIN_BLOCKCHAIN_ID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) PCHAINBLOCKCHAINID() ([32]byte, error) { + return _NativeTokenStakingManager.Contract.PCHAINBLOCKCHAINID(&_NativeTokenStakingManager.CallOpts) +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) PCHAINBLOCKCHAINID() ([32]byte, error) { + return _NativeTokenStakingManager.Contract.PCHAINBLOCKCHAINID(&_NativeTokenStakingManager.CallOpts) +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) VALIDATORMANAGERSTORAGELOCATION(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "VALIDATOR_MANAGER_STORAGE_LOCATION") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) VALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _NativeTokenStakingManager.Contract.VALIDATORMANAGERSTORAGELOCATION(&_NativeTokenStakingManager.CallOpts) +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) VALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _NativeTokenStakingManager.Contract.VALIDATORMANAGERSTORAGELOCATION(&_NativeTokenStakingManager.CallOpts) +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) WARPMESSENGER(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "WARP_MESSENGER") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) WARPMESSENGER() (common.Address, error) { + return _NativeTokenStakingManager.Contract.WARPMESSENGER(&_NativeTokenStakingManager.CallOpts) +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) WARPMESSENGER() (common.Address, error) { + return _NativeTokenStakingManager.Contract.WARPMESSENGER(&_NativeTokenStakingManager.CallOpts) +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) GetValidator(opts *bind.CallOpts, validationID [32]byte) (Validator, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "getValidator", validationID) + + if err != nil { + return *new(Validator), err + } + + out0 := *abi.ConvertType(out[0], new(Validator)).(*Validator) + + return out0, err + +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) GetValidator(validationID [32]byte) (Validator, error) { + return _NativeTokenStakingManager.Contract.GetValidator(&_NativeTokenStakingManager.CallOpts, validationID) +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) GetValidator(validationID [32]byte) (Validator, error) { + return _NativeTokenStakingManager.Contract.GetValidator(&_NativeTokenStakingManager.CallOpts, validationID) +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) GetWeight(opts *bind.CallOpts, validationID [32]byte) (uint64, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "getWeight", validationID) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) GetWeight(validationID [32]byte) (uint64, error) { + return _NativeTokenStakingManager.Contract.GetWeight(&_NativeTokenStakingManager.CallOpts, validationID) +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) GetWeight(validationID [32]byte) (uint64, error) { + return _NativeTokenStakingManager.Contract.GetWeight(&_NativeTokenStakingManager.CallOpts, validationID) +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) RegisteredValidators(opts *bind.CallOpts, nodeID []byte) ([32]byte, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "registeredValidators", nodeID) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) RegisteredValidators(nodeID []byte) ([32]byte, error) { + return _NativeTokenStakingManager.Contract.RegisteredValidators(&_NativeTokenStakingManager.CallOpts, nodeID) +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) RegisteredValidators(nodeID []byte) ([32]byte, error) { + return _NativeTokenStakingManager.Contract.RegisteredValidators(&_NativeTokenStakingManager.CallOpts, nodeID) +} + +// ValueToWeight is a free data retrieval call binding the contract method 0x2e2194d8. +// +// Solidity: function valueToWeight(uint256 value) view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) ValueToWeight(opts *bind.CallOpts, value *big.Int) (uint64, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "valueToWeight", value) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// ValueToWeight is a free data retrieval call binding the contract method 0x2e2194d8. +// +// Solidity: function valueToWeight(uint256 value) view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ValueToWeight(value *big.Int) (uint64, error) { + return _NativeTokenStakingManager.Contract.ValueToWeight(&_NativeTokenStakingManager.CallOpts, value) +} + +// ValueToWeight is a free data retrieval call binding the contract method 0x2e2194d8. +// +// Solidity: function valueToWeight(uint256 value) view returns(uint64) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) ValueToWeight(value *big.Int) (uint64, error) { + return _NativeTokenStakingManager.Contract.ValueToWeight(&_NativeTokenStakingManager.CallOpts, value) +} + +// WeightToValue is a free data retrieval call binding the contract method 0x62065856. +// +// Solidity: function weightToValue(uint64 weight) view returns(uint256) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCaller) WeightToValue(opts *bind.CallOpts, weight uint64) (*big.Int, error) { + var out []interface{} + err := _NativeTokenStakingManager.contract.Call(opts, &out, "weightToValue", weight) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// WeightToValue is a free data retrieval call binding the contract method 0x62065856. +// +// Solidity: function weightToValue(uint64 weight) view returns(uint256) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) WeightToValue(weight uint64) (*big.Int, error) { + return _NativeTokenStakingManager.Contract.WeightToValue(&_NativeTokenStakingManager.CallOpts, weight) +} + +// WeightToValue is a free data retrieval call binding the contract method 0x62065856. +// +// Solidity: function weightToValue(uint64 weight) view returns(uint256) +func (_NativeTokenStakingManager *NativeTokenStakingManagerCallerSession) WeightToValue(weight uint64) (*big.Int, error) { + return _NativeTokenStakingManager.Contract.WeightToValue(&_NativeTokenStakingManager.CallOpts, weight) +} + +// ClaimDelegationFees is a paid mutator transaction binding the contract method 0x93e24598. +// +// Solidity: function claimDelegationFees(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) ClaimDelegationFees(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "claimDelegationFees", validationID) +} + +// ClaimDelegationFees is a paid mutator transaction binding the contract method 0x93e24598. +// +// Solidity: function claimDelegationFees(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ClaimDelegationFees(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ClaimDelegationFees(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// ClaimDelegationFees is a paid mutator transaction binding the contract method 0x93e24598. +// +// Solidity: function claimDelegationFees(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) ClaimDelegationFees(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ClaimDelegationFees(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// CompleteDelegatorRegistration is a paid mutator transaction binding the contract method 0x5297fae6. +// +// Solidity: function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) CompleteDelegatorRegistration(opts *bind.TransactOpts, messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "completeDelegatorRegistration", messageIndex, delegationID) +} + +// CompleteDelegatorRegistration is a paid mutator transaction binding the contract method 0x5297fae6. +// +// Solidity: function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) CompleteDelegatorRegistration(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteDelegatorRegistration(&_NativeTokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteDelegatorRegistration is a paid mutator transaction binding the contract method 0x5297fae6. +// +// Solidity: function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) CompleteDelegatorRegistration(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteDelegatorRegistration(&_NativeTokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteEndDelegation is a paid mutator transaction binding the contract method 0x98f3e2b4. +// +// Solidity: function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) CompleteEndDelegation(opts *bind.TransactOpts, messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "completeEndDelegation", messageIndex, delegationID) +} + +// CompleteEndDelegation is a paid mutator transaction binding the contract method 0x98f3e2b4. +// +// Solidity: function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) CompleteEndDelegation(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteEndDelegation(&_NativeTokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteEndDelegation is a paid mutator transaction binding the contract method 0x98f3e2b4. +// +// Solidity: function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) CompleteEndDelegation(messageIndex uint32, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteEndDelegation(&_NativeTokenStakingManager.TransactOpts, messageIndex, delegationID) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) CompleteEndValidation(opts *bind.TransactOpts, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "completeEndValidation", messageIndex) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) CompleteEndValidation(messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteEndValidation(&_NativeTokenStakingManager.TransactOpts, messageIndex) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) CompleteEndValidation(messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteEndValidation(&_NativeTokenStakingManager.TransactOpts, messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) CompleteValidatorRegistration(opts *bind.TransactOpts, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "completeValidatorRegistration", messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) CompleteValidatorRegistration(messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteValidatorRegistration(&_NativeTokenStakingManager.TransactOpts, messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) CompleteValidatorRegistration(messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.CompleteValidatorRegistration(&_NativeTokenStakingManager.TransactOpts, messageIndex) +} + +// ForceInitializeEndDelegation is a paid mutator transaction binding the contract method 0x1ec44724. +// +// Solidity: function forceInitializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) ForceInitializeEndDelegation(opts *bind.TransactOpts, delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "forceInitializeEndDelegation", delegationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndDelegation is a paid mutator transaction binding the contract method 0x1ec44724. +// +// Solidity: function forceInitializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ForceInitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ForceInitializeEndDelegation(&_NativeTokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndDelegation is a paid mutator transaction binding the contract method 0x1ec44724. +// +// Solidity: function forceInitializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) ForceInitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ForceInitializeEndDelegation(&_NativeTokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndValidation is a paid mutator transaction binding the contract method 0x3a1cfff6. +// +// Solidity: function forceInitializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) ForceInitializeEndValidation(opts *bind.TransactOpts, validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "forceInitializeEndValidation", validationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndValidation is a paid mutator transaction binding the contract method 0x3a1cfff6. +// +// Solidity: function forceInitializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ForceInitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ForceInitializeEndValidation(&_NativeTokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// ForceInitializeEndValidation is a paid mutator transaction binding the contract method 0x3a1cfff6. +// +// Solidity: function forceInitializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) ForceInitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ForceInitializeEndValidation(&_NativeTokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc257a0f5. +// +// Solidity: function initialize(((bytes32,uint64,uint8),uint256,uint256,uint64,uint16,uint8,uint256,address) settings) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) Initialize(opts *bind.TransactOpts, settings PoSValidatorManagerSettings) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "initialize", settings) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc257a0f5. +// +// Solidity: function initialize(((bytes32,uint64,uint8),uint256,uint256,uint64,uint16,uint8,uint256,address) settings) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) Initialize(settings PoSValidatorManagerSettings) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.Initialize(&_NativeTokenStakingManager.TransactOpts, settings) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc257a0f5. +// +// Solidity: function initialize(((bytes32,uint64,uint8),uint256,uint256,uint64,uint16,uint8,uint256,address) settings) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) Initialize(settings PoSValidatorManagerSettings) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.Initialize(&_NativeTokenStakingManager.TransactOpts, settings) +} + +// InitializeDelegatorRegistration is a paid mutator transaction binding the contract method 0xc599e24f. +// +// Solidity: function initializeDelegatorRegistration(bytes32 validationID) payable returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) InitializeDelegatorRegistration(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "initializeDelegatorRegistration", validationID) +} + +// InitializeDelegatorRegistration is a paid mutator transaction binding the contract method 0xc599e24f. +// +// Solidity: function initializeDelegatorRegistration(bytes32 validationID) payable returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) InitializeDelegatorRegistration(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeDelegatorRegistration(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// InitializeDelegatorRegistration is a paid mutator transaction binding the contract method 0xc599e24f. +// +// Solidity: function initializeDelegatorRegistration(bytes32 validationID) payable returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) InitializeDelegatorRegistration(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeDelegatorRegistration(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// InitializeEndDelegation is a paid mutator transaction binding the contract method 0x0118acc4. +// +// Solidity: function initializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) InitializeEndDelegation(opts *bind.TransactOpts, delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "initializeEndDelegation", delegationID, includeUptimeProof, messageIndex) +} + +// InitializeEndDelegation is a paid mutator transaction binding the contract method 0x0118acc4. +// +// Solidity: function initializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) InitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeEndDelegation(&_NativeTokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// InitializeEndDelegation is a paid mutator transaction binding the contract method 0x0118acc4. +// +// Solidity: function initializeEndDelegation(bytes32 delegationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) InitializeEndDelegation(delegationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeEndDelegation(&_NativeTokenStakingManager.TransactOpts, delegationID, includeUptimeProof, messageIndex) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x76f78621. +// +// Solidity: function initializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) InitializeEndValidation(opts *bind.TransactOpts, validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "initializeEndValidation", validationID, includeUptimeProof, messageIndex) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x76f78621. +// +// Solidity: function initializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) InitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeEndValidation(&_NativeTokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x76f78621. +// +// Solidity: function initializeEndValidation(bytes32 validationID, bool includeUptimeProof, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) InitializeEndValidation(validationID [32]byte, includeUptimeProof bool, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeEndValidation(&_NativeTokenStakingManager.TransactOpts, validationID, includeUptimeProof, messageIndex) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0xaf2f5feb. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint16 delegationFeeBips, uint64 minStakeDuration) payable returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) InitializeValidatorRegistration(opts *bind.TransactOpts, registrationInput ValidatorRegistrationInput, delegationFeeBips uint16, minStakeDuration uint64) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "initializeValidatorRegistration", registrationInput, delegationFeeBips, minStakeDuration) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0xaf2f5feb. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint16 delegationFeeBips, uint64 minStakeDuration) payable returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) InitializeValidatorRegistration(registrationInput ValidatorRegistrationInput, delegationFeeBips uint16, minStakeDuration uint64) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeValidatorRegistration(&_NativeTokenStakingManager.TransactOpts, registrationInput, delegationFeeBips, minStakeDuration) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0xaf2f5feb. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint16 delegationFeeBips, uint64 minStakeDuration) payable returns(bytes32) +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) InitializeValidatorRegistration(registrationInput ValidatorRegistrationInput, delegationFeeBips uint16, minStakeDuration uint64) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeValidatorRegistration(&_NativeTokenStakingManager.TransactOpts, registrationInput, delegationFeeBips, minStakeDuration) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) InitializeValidatorSet(opts *bind.TransactOpts, subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "initializeValidatorSet", subnetConversionData, messageIndex) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) InitializeValidatorSet(subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeValidatorSet(&_NativeTokenStakingManager.TransactOpts, subnetConversionData, messageIndex) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) InitializeValidatorSet(subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.InitializeValidatorSet(&_NativeTokenStakingManager.TransactOpts, subnetConversionData, messageIndex) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) ResendEndValidatorMessage(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "resendEndValidatorMessage", validationID) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ResendEndValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ResendEndValidatorMessage(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) ResendEndValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ResendEndValidatorMessage(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) ResendRegisterValidatorMessage(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "resendRegisterValidatorMessage", validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ResendRegisterValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ResendRegisterValidatorMessage(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) ResendRegisterValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ResendRegisterValidatorMessage(&_NativeTokenStakingManager.TransactOpts, validationID) +} + +// ResendUpdateDelegation is a paid mutator transaction binding the contract method 0xba3a4b97. +// +// Solidity: function resendUpdateDelegation(bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) ResendUpdateDelegation(opts *bind.TransactOpts, delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "resendUpdateDelegation", delegationID) +} + +// ResendUpdateDelegation is a paid mutator transaction binding the contract method 0xba3a4b97. +// +// Solidity: function resendUpdateDelegation(bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) ResendUpdateDelegation(delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ResendUpdateDelegation(&_NativeTokenStakingManager.TransactOpts, delegationID) +} + +// ResendUpdateDelegation is a paid mutator transaction binding the contract method 0xba3a4b97. +// +// Solidity: function resendUpdateDelegation(bytes32 delegationID) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) ResendUpdateDelegation(delegationID [32]byte) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.ResendUpdateDelegation(&_NativeTokenStakingManager.TransactOpts, delegationID) +} + +// SubmitUptimeProof is a paid mutator transaction binding the contract method 0x25e1c776. +// +// Solidity: function submitUptimeProof(bytes32 validationID, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactor) SubmitUptimeProof(opts *bind.TransactOpts, validationID [32]byte, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.contract.Transact(opts, "submitUptimeProof", validationID, messageIndex) +} + +// SubmitUptimeProof is a paid mutator transaction binding the contract method 0x25e1c776. +// +// Solidity: function submitUptimeProof(bytes32 validationID, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerSession) SubmitUptimeProof(validationID [32]byte, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.SubmitUptimeProof(&_NativeTokenStakingManager.TransactOpts, validationID, messageIndex) +} + +// SubmitUptimeProof is a paid mutator transaction binding the contract method 0x25e1c776. +// +// Solidity: function submitUptimeProof(bytes32 validationID, uint32 messageIndex) returns() +func (_NativeTokenStakingManager *NativeTokenStakingManagerTransactorSession) SubmitUptimeProof(validationID [32]byte, messageIndex uint32) (*types.Transaction, error) { + return _NativeTokenStakingManager.Contract.SubmitUptimeProof(&_NativeTokenStakingManager.TransactOpts, validationID, messageIndex) +} + +// NativeTokenStakingManagerDelegationEndedIterator is returned from FilterDelegationEnded and is used to iterate over the raw logs and unpacked data for DelegationEnded events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegationEndedIterator struct { + Event *NativeTokenStakingManagerDelegationEnded // 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 interfaces.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 *NativeTokenStakingManagerDelegationEndedIterator) 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(NativeTokenStakingManagerDelegationEnded) + 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(NativeTokenStakingManagerDelegationEnded) + 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 *NativeTokenStakingManagerDelegationEndedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerDelegationEndedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerDelegationEnded represents a DelegationEnded event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegationEnded struct { + DelegationID [32]byte + ValidationID [32]byte + Rewards *big.Int + Fees *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegationEnded is a free log retrieval operation binding the contract event 0x8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993. +// +// Solidity: event DelegationEnded(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterDelegationEnded(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte) (*NativeTokenStakingManagerDelegationEndedIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "DelegationEnded", delegationIDRule, validationIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerDelegationEndedIterator{contract: _NativeTokenStakingManager.contract, event: "DelegationEnded", logs: logs, sub: sub}, nil +} + +// WatchDelegationEnded is a free log subscription operation binding the contract event 0x8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993. +// +// Solidity: event DelegationEnded(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchDelegationEnded(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerDelegationEnded, delegationID [][32]byte, validationID [][32]byte) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "DelegationEnded", delegationIDRule, validationIDRule) + 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(NativeTokenStakingManagerDelegationEnded) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegationEnded", 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 +} + +// ParseDelegationEnded is a log parse operation binding the contract event 0x8ececf510070c320d9a55323ffabe350e294ae505fc0c509dc5736da6f5cc993. +// +// Solidity: event DelegationEnded(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseDelegationEnded(log types.Log) (*NativeTokenStakingManagerDelegationEnded, error) { + event := new(NativeTokenStakingManagerDelegationEnded) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegationEnded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerDelegatorAddedIterator is returned from FilterDelegatorAdded and is used to iterate over the raw logs and unpacked data for DelegatorAdded events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegatorAddedIterator struct { + Event *NativeTokenStakingManagerDelegatorAdded // 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 interfaces.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 *NativeTokenStakingManagerDelegatorAddedIterator) 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(NativeTokenStakingManagerDelegatorAdded) + 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(NativeTokenStakingManagerDelegatorAdded) + 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 *NativeTokenStakingManagerDelegatorAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerDelegatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerDelegatorAdded represents a DelegatorAdded event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegatorAdded struct { + DelegationID [32]byte + ValidationID [32]byte + DelegatorAddress common.Address + Nonce uint64 + ValidatorWeight uint64 + DelegatorWeight uint64 + SetWeightMessageID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegatorAdded is a free log retrieval operation binding the contract event 0xb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426. +// +// Solidity: event DelegatorAdded(bytes32 indexed delegationID, bytes32 indexed validationID, address indexed delegatorAddress, uint64 nonce, uint64 validatorWeight, uint64 delegatorWeight, bytes32 setWeightMessageID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterDelegatorAdded(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte, delegatorAddress []common.Address) (*NativeTokenStakingManagerDelegatorAddedIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var delegatorAddressRule []interface{} + for _, delegatorAddressItem := range delegatorAddress { + delegatorAddressRule = append(delegatorAddressRule, delegatorAddressItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "DelegatorAdded", delegationIDRule, validationIDRule, delegatorAddressRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerDelegatorAddedIterator{contract: _NativeTokenStakingManager.contract, event: "DelegatorAdded", logs: logs, sub: sub}, nil +} + +// WatchDelegatorAdded is a free log subscription operation binding the contract event 0xb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426. +// +// Solidity: event DelegatorAdded(bytes32 indexed delegationID, bytes32 indexed validationID, address indexed delegatorAddress, uint64 nonce, uint64 validatorWeight, uint64 delegatorWeight, bytes32 setWeightMessageID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchDelegatorAdded(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerDelegatorAdded, delegationID [][32]byte, validationID [][32]byte, delegatorAddress []common.Address) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var delegatorAddressRule []interface{} + for _, delegatorAddressItem := range delegatorAddress { + delegatorAddressRule = append(delegatorAddressRule, delegatorAddressItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "DelegatorAdded", delegationIDRule, validationIDRule, delegatorAddressRule) + 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(NativeTokenStakingManagerDelegatorAdded) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegatorAdded", 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 +} + +// ParseDelegatorAdded is a log parse operation binding the contract event 0xb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426. +// +// Solidity: event DelegatorAdded(bytes32 indexed delegationID, bytes32 indexed validationID, address indexed delegatorAddress, uint64 nonce, uint64 validatorWeight, uint64 delegatorWeight, bytes32 setWeightMessageID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseDelegatorAdded(log types.Log) (*NativeTokenStakingManagerDelegatorAdded, error) { + event := new(NativeTokenStakingManagerDelegatorAdded) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerDelegatorRegisteredIterator is returned from FilterDelegatorRegistered and is used to iterate over the raw logs and unpacked data for DelegatorRegistered events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegatorRegisteredIterator struct { + Event *NativeTokenStakingManagerDelegatorRegistered // 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 interfaces.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 *NativeTokenStakingManagerDelegatorRegisteredIterator) 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(NativeTokenStakingManagerDelegatorRegistered) + 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(NativeTokenStakingManagerDelegatorRegistered) + 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 *NativeTokenStakingManagerDelegatorRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerDelegatorRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerDelegatorRegistered represents a DelegatorRegistered event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegatorRegistered struct { + DelegationID [32]byte + ValidationID [32]byte + StartTime *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegatorRegistered is a free log retrieval operation binding the contract event 0x047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6. +// +// Solidity: event DelegatorRegistered(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterDelegatorRegistered(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte) (*NativeTokenStakingManagerDelegatorRegisteredIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "DelegatorRegistered", delegationIDRule, validationIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerDelegatorRegisteredIterator{contract: _NativeTokenStakingManager.contract, event: "DelegatorRegistered", logs: logs, sub: sub}, nil +} + +// WatchDelegatorRegistered is a free log subscription operation binding the contract event 0x047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6. +// +// Solidity: event DelegatorRegistered(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchDelegatorRegistered(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerDelegatorRegistered, delegationID [][32]byte, validationID [][32]byte) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "DelegatorRegistered", delegationIDRule, validationIDRule) + 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(NativeTokenStakingManagerDelegatorRegistered) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegatorRegistered", 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 +} + +// ParseDelegatorRegistered is a log parse operation binding the contract event 0x047059b465069b8b751836b41f9f1d83daff583d2238cc7fbb461437ec23a4f6. +// +// Solidity: event DelegatorRegistered(bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseDelegatorRegistered(log types.Log) (*NativeTokenStakingManagerDelegatorRegistered, error) { + event := new(NativeTokenStakingManagerDelegatorRegistered) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegatorRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerDelegatorRemovalInitializedIterator is returned from FilterDelegatorRemovalInitialized and is used to iterate over the raw logs and unpacked data for DelegatorRemovalInitialized events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegatorRemovalInitializedIterator struct { + Event *NativeTokenStakingManagerDelegatorRemovalInitialized // 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 interfaces.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 *NativeTokenStakingManagerDelegatorRemovalInitializedIterator) 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(NativeTokenStakingManagerDelegatorRemovalInitialized) + 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(NativeTokenStakingManagerDelegatorRemovalInitialized) + 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 *NativeTokenStakingManagerDelegatorRemovalInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerDelegatorRemovalInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerDelegatorRemovalInitialized represents a DelegatorRemovalInitialized event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerDelegatorRemovalInitialized struct { + DelegationID [32]byte + ValidationID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDelegatorRemovalInitialized is a free log retrieval operation binding the contract event 0x366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed57. +// +// Solidity: event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterDelegatorRemovalInitialized(opts *bind.FilterOpts, delegationID [][32]byte, validationID [][32]byte) (*NativeTokenStakingManagerDelegatorRemovalInitializedIterator, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "DelegatorRemovalInitialized", delegationIDRule, validationIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerDelegatorRemovalInitializedIterator{contract: _NativeTokenStakingManager.contract, event: "DelegatorRemovalInitialized", logs: logs, sub: sub}, nil +} + +// WatchDelegatorRemovalInitialized is a free log subscription operation binding the contract event 0x366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed57. +// +// Solidity: event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchDelegatorRemovalInitialized(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerDelegatorRemovalInitialized, delegationID [][32]byte, validationID [][32]byte) (event.Subscription, error) { + + var delegationIDRule []interface{} + for _, delegationIDItem := range delegationID { + delegationIDRule = append(delegationIDRule, delegationIDItem) + } + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "DelegatorRemovalInitialized", delegationIDRule, validationIDRule) + 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(NativeTokenStakingManagerDelegatorRemovalInitialized) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegatorRemovalInitialized", 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 +} + +// ParseDelegatorRemovalInitialized is a log parse operation binding the contract event 0x366d336c0ab380dc799f095a6f82a26326585c52909cc698b09ba4540709ed57. +// +// Solidity: event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseDelegatorRemovalInitialized(log types.Log) (*NativeTokenStakingManagerDelegatorRemovalInitialized, error) { + event := new(NativeTokenStakingManagerDelegatorRemovalInitialized) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "DelegatorRemovalInitialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerInitialValidatorCreatedIterator is returned from FilterInitialValidatorCreated and is used to iterate over the raw logs and unpacked data for InitialValidatorCreated events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerInitialValidatorCreatedIterator struct { + Event *NativeTokenStakingManagerInitialValidatorCreated // 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 interfaces.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 *NativeTokenStakingManagerInitialValidatorCreatedIterator) 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(NativeTokenStakingManagerInitialValidatorCreated) + 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(NativeTokenStakingManagerInitialValidatorCreated) + 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 *NativeTokenStakingManagerInitialValidatorCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerInitialValidatorCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerInitialValidatorCreated represents a InitialValidatorCreated event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerInitialValidatorCreated struct { + ValidationID [32]byte + NodeID common.Hash + Weight *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialValidatorCreated is a free log retrieval operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterInitialValidatorCreated(opts *bind.FilterOpts, validationID [][32]byte, nodeID [][]byte) (*NativeTokenStakingManagerInitialValidatorCreatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "InitialValidatorCreated", validationIDRule, nodeIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerInitialValidatorCreatedIterator{contract: _NativeTokenStakingManager.contract, event: "InitialValidatorCreated", logs: logs, sub: sub}, nil +} + +// WatchInitialValidatorCreated is a free log subscription operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchInitialValidatorCreated(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerInitialValidatorCreated, validationID [][32]byte, nodeID [][]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "InitialValidatorCreated", validationIDRule, nodeIDRule) + 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(NativeTokenStakingManagerInitialValidatorCreated) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "InitialValidatorCreated", 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 +} + +// ParseInitialValidatorCreated is a log parse operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseInitialValidatorCreated(log types.Log) (*NativeTokenStakingManagerInitialValidatorCreated, error) { + event := new(NativeTokenStakingManagerInitialValidatorCreated) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "InitialValidatorCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerInitializedIterator struct { + Event *NativeTokenStakingManagerInitialized // 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 interfaces.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 *NativeTokenStakingManagerInitializedIterator) 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(NativeTokenStakingManagerInitialized) + 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(NativeTokenStakingManagerInitialized) + 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 *NativeTokenStakingManagerInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerInitialized represents a Initialized event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterInitialized(opts *bind.FilterOpts) (*NativeTokenStakingManagerInitializedIterator, error) { + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerInitializedIterator{contract: _NativeTokenStakingManager.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerInitialized) (event.Subscription, error) { + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "Initialized") + 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(NativeTokenStakingManagerInitialized) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseInitialized(log types.Log) (*NativeTokenStakingManagerInitialized, error) { + event := new(NativeTokenStakingManagerInitialized) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerUptimeUpdatedIterator is returned from FilterUptimeUpdated and is used to iterate over the raw logs and unpacked data for UptimeUpdated events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerUptimeUpdatedIterator struct { + Event *NativeTokenStakingManagerUptimeUpdated // 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 interfaces.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 *NativeTokenStakingManagerUptimeUpdatedIterator) 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(NativeTokenStakingManagerUptimeUpdated) + 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(NativeTokenStakingManagerUptimeUpdated) + 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 *NativeTokenStakingManagerUptimeUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerUptimeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerUptimeUpdated represents a UptimeUpdated event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerUptimeUpdated struct { + ValidationID [32]byte + Uptime uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUptimeUpdated is a free log retrieval operation binding the contract event 0xec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435. +// +// Solidity: event UptimeUpdated(bytes32 indexed validationID, uint64 uptime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterUptimeUpdated(opts *bind.FilterOpts, validationID [][32]byte) (*NativeTokenStakingManagerUptimeUpdatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "UptimeUpdated", validationIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerUptimeUpdatedIterator{contract: _NativeTokenStakingManager.contract, event: "UptimeUpdated", logs: logs, sub: sub}, nil +} + +// WatchUptimeUpdated is a free log subscription operation binding the contract event 0xec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435. +// +// Solidity: event UptimeUpdated(bytes32 indexed validationID, uint64 uptime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchUptimeUpdated(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerUptimeUpdated, validationID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "UptimeUpdated", validationIDRule) + 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(NativeTokenStakingManagerUptimeUpdated) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "UptimeUpdated", 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 +} + +// ParseUptimeUpdated is a log parse operation binding the contract event 0xec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435. +// +// Solidity: event UptimeUpdated(bytes32 indexed validationID, uint64 uptime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseUptimeUpdated(log types.Log) (*NativeTokenStakingManagerUptimeUpdated, error) { + event := new(NativeTokenStakingManagerUptimeUpdated) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "UptimeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerValidationPeriodCreatedIterator is returned from FilterValidationPeriodCreated and is used to iterate over the raw logs and unpacked data for ValidationPeriodCreated events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidationPeriodCreatedIterator struct { + Event *NativeTokenStakingManagerValidationPeriodCreated // 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 interfaces.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 *NativeTokenStakingManagerValidationPeriodCreatedIterator) 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(NativeTokenStakingManagerValidationPeriodCreated) + 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(NativeTokenStakingManagerValidationPeriodCreated) + 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 *NativeTokenStakingManagerValidationPeriodCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerValidationPeriodCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerValidationPeriodCreated represents a ValidationPeriodCreated event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidationPeriodCreated struct { + ValidationID [32]byte + NodeID common.Hash + RegisterValidationMessageID [32]byte + Weight *big.Int + RegistrationExpiry uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodCreated is a free log retrieval operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterValidationPeriodCreated(opts *bind.FilterOpts, validationID [][32]byte, nodeID [][]byte, registerValidationMessageID [][32]byte) (*NativeTokenStakingManagerValidationPeriodCreatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + var registerValidationMessageIDRule []interface{} + for _, registerValidationMessageIDItem := range registerValidationMessageID { + registerValidationMessageIDRule = append(registerValidationMessageIDRule, registerValidationMessageIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "ValidationPeriodCreated", validationIDRule, nodeIDRule, registerValidationMessageIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerValidationPeriodCreatedIterator{contract: _NativeTokenStakingManager.contract, event: "ValidationPeriodCreated", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodCreated is a free log subscription operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchValidationPeriodCreated(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerValidationPeriodCreated, validationID [][32]byte, nodeID [][]byte, registerValidationMessageID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + var registerValidationMessageIDRule []interface{} + for _, registerValidationMessageIDItem := range registerValidationMessageID { + registerValidationMessageIDRule = append(registerValidationMessageIDRule, registerValidationMessageIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "ValidationPeriodCreated", validationIDRule, nodeIDRule, registerValidationMessageIDRule) + 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(NativeTokenStakingManagerValidationPeriodCreated) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidationPeriodCreated", 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 +} + +// ParseValidationPeriodCreated is a log parse operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseValidationPeriodCreated(log types.Log) (*NativeTokenStakingManagerValidationPeriodCreated, error) { + event := new(NativeTokenStakingManagerValidationPeriodCreated) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidationPeriodCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerValidationPeriodEndedIterator is returned from FilterValidationPeriodEnded and is used to iterate over the raw logs and unpacked data for ValidationPeriodEnded events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidationPeriodEndedIterator struct { + Event *NativeTokenStakingManagerValidationPeriodEnded // 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 interfaces.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 *NativeTokenStakingManagerValidationPeriodEndedIterator) 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(NativeTokenStakingManagerValidationPeriodEnded) + 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(NativeTokenStakingManagerValidationPeriodEnded) + 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 *NativeTokenStakingManagerValidationPeriodEndedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerValidationPeriodEndedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerValidationPeriodEnded represents a ValidationPeriodEnded event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidationPeriodEnded struct { + ValidationID [32]byte + Status uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodEnded is a free log retrieval operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterValidationPeriodEnded(opts *bind.FilterOpts, validationID [][32]byte, status []uint8) (*NativeTokenStakingManagerValidationPeriodEndedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var statusRule []interface{} + for _, statusItem := range status { + statusRule = append(statusRule, statusItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "ValidationPeriodEnded", validationIDRule, statusRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerValidationPeriodEndedIterator{contract: _NativeTokenStakingManager.contract, event: "ValidationPeriodEnded", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodEnded is a free log subscription operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchValidationPeriodEnded(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerValidationPeriodEnded, validationID [][32]byte, status []uint8) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var statusRule []interface{} + for _, statusItem := range status { + statusRule = append(statusRule, statusItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "ValidationPeriodEnded", validationIDRule, statusRule) + 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(NativeTokenStakingManagerValidationPeriodEnded) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidationPeriodEnded", 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 +} + +// ParseValidationPeriodEnded is a log parse operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseValidationPeriodEnded(log types.Log) (*NativeTokenStakingManagerValidationPeriodEnded, error) { + event := new(NativeTokenStakingManagerValidationPeriodEnded) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidationPeriodEnded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerValidationPeriodRegisteredIterator is returned from FilterValidationPeriodRegistered and is used to iterate over the raw logs and unpacked data for ValidationPeriodRegistered events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidationPeriodRegisteredIterator struct { + Event *NativeTokenStakingManagerValidationPeriodRegistered // 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 interfaces.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 *NativeTokenStakingManagerValidationPeriodRegisteredIterator) 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(NativeTokenStakingManagerValidationPeriodRegistered) + 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(NativeTokenStakingManagerValidationPeriodRegistered) + 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 *NativeTokenStakingManagerValidationPeriodRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerValidationPeriodRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerValidationPeriodRegistered represents a ValidationPeriodRegistered event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidationPeriodRegistered struct { + ValidationID [32]byte + Weight *big.Int + Timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodRegistered is a free log retrieval operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterValidationPeriodRegistered(opts *bind.FilterOpts, validationID [][32]byte) (*NativeTokenStakingManagerValidationPeriodRegisteredIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "ValidationPeriodRegistered", validationIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerValidationPeriodRegisteredIterator{contract: _NativeTokenStakingManager.contract, event: "ValidationPeriodRegistered", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodRegistered is a free log subscription operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchValidationPeriodRegistered(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerValidationPeriodRegistered, validationID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "ValidationPeriodRegistered", validationIDRule) + 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(NativeTokenStakingManagerValidationPeriodRegistered) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidationPeriodRegistered", 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 +} + +// ParseValidationPeriodRegistered is a log parse operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseValidationPeriodRegistered(log types.Log) (*NativeTokenStakingManagerValidationPeriodRegistered, error) { + event := new(NativeTokenStakingManagerValidationPeriodRegistered) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidationPeriodRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerValidatorRemovalInitializedIterator is returned from FilterValidatorRemovalInitialized and is used to iterate over the raw logs and unpacked data for ValidatorRemovalInitialized events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidatorRemovalInitializedIterator struct { + Event *NativeTokenStakingManagerValidatorRemovalInitialized // 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 interfaces.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 *NativeTokenStakingManagerValidatorRemovalInitializedIterator) 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(NativeTokenStakingManagerValidatorRemovalInitialized) + 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(NativeTokenStakingManagerValidatorRemovalInitialized) + 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 *NativeTokenStakingManagerValidatorRemovalInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerValidatorRemovalInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerValidatorRemovalInitialized represents a ValidatorRemovalInitialized event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidatorRemovalInitialized struct { + ValidationID [32]byte + SetWeightMessageID [32]byte + Weight *big.Int + EndTime *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorRemovalInitialized is a free log retrieval operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterValidatorRemovalInitialized(opts *bind.FilterOpts, validationID [][32]byte, setWeightMessageID [][32]byte) (*NativeTokenStakingManagerValidatorRemovalInitializedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var setWeightMessageIDRule []interface{} + for _, setWeightMessageIDItem := range setWeightMessageID { + setWeightMessageIDRule = append(setWeightMessageIDRule, setWeightMessageIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "ValidatorRemovalInitialized", validationIDRule, setWeightMessageIDRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerValidatorRemovalInitializedIterator{contract: _NativeTokenStakingManager.contract, event: "ValidatorRemovalInitialized", logs: logs, sub: sub}, nil +} + +// WatchValidatorRemovalInitialized is a free log subscription operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchValidatorRemovalInitialized(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerValidatorRemovalInitialized, validationID [][32]byte, setWeightMessageID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var setWeightMessageIDRule []interface{} + for _, setWeightMessageIDItem := range setWeightMessageID { + setWeightMessageIDRule = append(setWeightMessageIDRule, setWeightMessageIDItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "ValidatorRemovalInitialized", validationIDRule, setWeightMessageIDRule) + 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(NativeTokenStakingManagerValidatorRemovalInitialized) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidatorRemovalInitialized", 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 +} + +// ParseValidatorRemovalInitialized is a log parse operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseValidatorRemovalInitialized(log types.Log) (*NativeTokenStakingManagerValidatorRemovalInitialized, error) { + event := new(NativeTokenStakingManagerValidatorRemovalInitialized) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidatorRemovalInitialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// NativeTokenStakingManagerValidatorWeightUpdateIterator is returned from FilterValidatorWeightUpdate and is used to iterate over the raw logs and unpacked data for ValidatorWeightUpdate events raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidatorWeightUpdateIterator struct { + Event *NativeTokenStakingManagerValidatorWeightUpdate // 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 interfaces.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 *NativeTokenStakingManagerValidatorWeightUpdateIterator) 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(NativeTokenStakingManagerValidatorWeightUpdate) + 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(NativeTokenStakingManagerValidatorWeightUpdate) + 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 *NativeTokenStakingManagerValidatorWeightUpdateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *NativeTokenStakingManagerValidatorWeightUpdateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// NativeTokenStakingManagerValidatorWeightUpdate represents a ValidatorWeightUpdate event raised by the NativeTokenStakingManager contract. +type NativeTokenStakingManagerValidatorWeightUpdate struct { + ValidationID [32]byte + Nonce uint64 + ValidatorWeight uint64 + SetWeightMessageID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorWeightUpdate is a free log retrieval operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) FilterValidatorWeightUpdate(opts *bind.FilterOpts, validationID [][32]byte, nonce []uint64) (*NativeTokenStakingManagerValidatorWeightUpdateIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.FilterLogs(opts, "ValidatorWeightUpdate", validationIDRule, nonceRule) + if err != nil { + return nil, err + } + return &NativeTokenStakingManagerValidatorWeightUpdateIterator{contract: _NativeTokenStakingManager.contract, event: "ValidatorWeightUpdate", logs: logs, sub: sub}, nil +} + +// WatchValidatorWeightUpdate is a free log subscription operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) WatchValidatorWeightUpdate(opts *bind.WatchOpts, sink chan<- *NativeTokenStakingManagerValidatorWeightUpdate, validationID [][32]byte, nonce []uint64) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + + logs, sub, err := _NativeTokenStakingManager.contract.WatchLogs(opts, "ValidatorWeightUpdate", validationIDRule, nonceRule) + 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(NativeTokenStakingManagerValidatorWeightUpdate) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidatorWeightUpdate", 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 +} + +// ParseValidatorWeightUpdate is a log parse operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_NativeTokenStakingManager *NativeTokenStakingManagerFilterer) ParseValidatorWeightUpdate(log types.Log) (*NativeTokenStakingManagerValidatorWeightUpdate, error) { + event := new(NativeTokenStakingManagerValidatorWeightUpdate) + if err := _NativeTokenStakingManager.contract.UnpackLog(event, "ValidatorWeightUpdate", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/abi-bindings/go/validator-manager/PoAValidatorManager/PoAValidatorManager.go b/abi-bindings/go/validator-manager/PoAValidatorManager/PoAValidatorManager.go new file mode 100644 index 000000000..26d2e2aa7 --- /dev/null +++ b/abi-bindings/go/validator-manager/PoAValidatorManager/PoAValidatorManager.go @@ -0,0 +1,2016 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package poavalidatormanager + +import ( + "errors" + "math/big" + "strings" + + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = interfaces.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// InitialValidator is an auto generated low-level Go binding around an user-defined struct. +type InitialValidator struct { + NodeID []byte + BlsPublicKey []byte + Weight uint64 +} + +// PChainOwner is an auto generated low-level Go binding around an user-defined struct. +type PChainOwner struct { + Threshold uint32 + Addresses []common.Address +} + +// SubnetConversionData is an auto generated low-level Go binding around an user-defined struct. +type SubnetConversionData struct { + SubnetID [32]byte + ValidatorManagerBlockchainID [32]byte + ValidatorManagerAddress common.Address + InitialValidators []InitialValidator +} + +// Validator is an auto generated low-level Go binding around an user-defined struct. +type Validator struct { + Status uint8 + NodeID []byte + StartingWeight uint64 + MessageNonce uint64 + Weight uint64 + StartedAt uint64 + EndedAt uint64 +} + +// ValidatorManagerSettings is an auto generated low-level Go binding around an user-defined struct. +type ValidatorManagerSettings struct { + SubnetID [32]byte + ChurnPeriodSeconds uint64 + MaximumChurnPercentage uint8 +} + +// ValidatorRegistrationInput is an auto generated low-level Go binding around an user-defined struct. +type ValidatorRegistrationInput struct { + NodeID []byte + BlsPublicKey []byte + RegistrationExpiry uint64 + RemainingBalanceOwner PChainOwner + DisableOwner PChainOwner +} + +// PoAValidatorManagerMetaData contains all meta data concerning the PoAValidatorManager contract. +var PoAValidatorManagerMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ADDRESS_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"BLS_PUBLIC_KEY_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_CHURN_PERCENTAGE_LIMIT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAXIMUM_REGISTRATION_EXPIRY_LENGTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"P_CHAIN_BLOCKCHAIN_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VALIDATOR_MANAGER_STORAGE_LOCATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getValidator\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structValidator\",\"components\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumValidatorStatus\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"startingWeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"messageNonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"startedAt\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"endedAt\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"churnPeriodSeconds\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"maximumChurnPercentage\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"initialOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"registrationInput\",\"type\":\"tuple\",\"internalType\":\"structValidatorRegistrationInput\",\"components\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remainingBalanceOwner\",\"type\":\"tuple\",\"internalType\":\"structPChainOwner\",\"components\":[{\"name\":\"threshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"addresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]},{\"name\":\"disableOwner\",\"type\":\"tuple\",\"internalType\":\"structPChainOwner\",\"components\":[{\"name\":\"threshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"addresses\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}]},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorSet\",\"inputs\":[{\"name\":\"subnetConversionData\",\"type\":\"tuple\",\"internalType\":\"structSubnetConversionData\",\"components\":[{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorManagerBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"validatorManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"initialValidators\",\"type\":\"tuple[]\",\"internalType\":\"structInitialValidator[]\",\"components\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}]},{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registeredValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"InitialValidatorCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorWeightUpdate\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidBLSKeyLength\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidBLSPublicKey\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodecID\",\"inputs\":[{\"name\":\"id\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitializationStatus\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMaximumChurnPercentage\",\"inputs\":[{\"name\":\"maximumChurnPercentage\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageLength\",\"inputs\":[{\"name\":\"actual\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"expected\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidMessageType\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidNodeID\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidPChainOwnerThreshold\",\"inputs\":[{\"name\":\"threshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"addressesLength\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidRegistrationExpiry\",\"inputs\":[{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidSubnetConversionID\",\"inputs\":[{\"name\":\"encodedSubnetConversionID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"expectedSubnetConversionID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidTotalWeight\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidValidationID\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorManagerAddress\",\"inputs\":[{\"name\":\"validatorManagerAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorManagerBlockchainID\",\"inputs\":[{\"name\":\"blockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidValidatorStatus\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumValidatorStatus\"}]},{\"type\":\"error\",\"name\":\"InvalidWarpMessage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidWarpOriginSenderAddress\",\"inputs\":[{\"name\":\"senderAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidWarpSourceChainID\",\"inputs\":[{\"name\":\"sourceChainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"MaxChurnRateExceeded\",\"inputs\":[{\"name\":\"churnAmount\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"NodeAlreadyRegistered\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"PChainOwnerAddressesNotSorted\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedRegistrationStatus\",\"inputs\":[{\"name\":\"validRegistration\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]", + Bin: "0x608060405234801561000f575f80fd5b5060405161395638038061395683398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b6138098061014d5f395ff3fe608060405234801561000f575f80fd5b5060043610610132575f3560e01c80639ba96b86116100b4578063c974d1b611610079578063c974d1b61461028b578063d588c18f14610293578063d5f20ff6146102a6578063df93d8de146102c6578063f2fde38b146102d0578063fd7ac5e7146102e3575f80fd5b80639ba96b861461021d578063a3a65e4814610230578063b771b3bc14610243578063bc5fbfec14610251578063bee0a03f14610278575f80fd5b8063715018a6116100fa578063715018a6146101be578063732214f8146101c65780638280a25a146101db5780638da5cb5b146101f557806397fb70d41461020a575f80fd5b80630322ed981461013657806320d91b7a1461014b578063467ef06f1461015e57806360305d621461017157806366435abf14610193575b5f80fd5b610149610144366004612be2565b6102f6565b005b610149610159366004612c11565b610502565b61014961016c366004612c5f565b610a00565b610179601481565b60405163ffffffff90911681526020015b60405180910390f35b6101a66101a1366004612be2565b610a0e565b6040516001600160401b03909116815260200161018a565b610149610a22565b6101cd5f81565b60405190815260200161018a565b6101e3603081565b60405160ff909116815260200161018a565b6101fd610a35565b60405161018a9190612c78565b610149610218366004612be2565b610a63565b6101cd61022b366004612ca2565b610a78565b61014961023e366004612c5f565b610a94565b6101fd6005600160991b0181565b6101cd7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0081565b610149610286366004612be2565b610c1a565b6101e3601481565b6101496102a1366004612cfb565b610d37565b6102b96102b4366004612be2565b610e44565b60405161018a9190612db8565b6101a66202a30081565b6101496102de366004612e38565b610f86565b6101cd6102f1366004612e5a565b610fc3565b5f6102ff610ffb565b5f838152600782016020526040808220815160e0810190925280549394509192909190829060ff16600581111561033857610338612d37565b600581111561034957610349612d37565b815260200160018201805461035d90612ec5565b80601f016020809104026020016040519081016040528092919081815260200182805461038990612ec5565b80156103d45780601f106103ab576101008083540402835291602001916103d4565b820191905f5260205f20905b8154815290600101906020018083116103b757829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561043f5761043f612d37565b1461047b575f8381526007830160205260409081902054905163170cc93360e21b81526104729160ff1690600401612efd565b60405180910390fd5b6005600160991b016001600160a01b031663ee5b48eb6104a08584606001515f61101f565b6040518263ffffffff1660e01b81526004016104bc9190612f0b565b6020604051808303815f875af11580156104d8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fc9190612f1d565b50505050565b5f61050b610ffb565b600981015490915060ff161561053457604051637fab81e560e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610577573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061059b9190612f1d565b8360200135146105c4576040516372b0a7e760e11b815260208401356004820152602401610472565b306105d56060850160408601612e38565b6001600160a01b03161461060d576105f36060840160408501612e38565b604051632f88120d60e21b81526004016104729190612c78565b5f61061b6060850185612f34565b905090505f805b828163ffffffff161015610902575f61063e6060880188612f34565b8363ffffffff1681811061065457610654612f79565b90506020028101906106669190612f8d565b61066f906130b1565b80516040519192505f9160088801916106879161312a565b908152602001604051809103902054146106b757805160405163a41f772f60e01b81526104729190600401612f0b565b5f6002885f0135846040516020016106e692919091825260e01b6001600160e01b031916602082015260240190565b60408051601f19818403018152908290526107009161312a565b602060405180830381855afa15801561071b573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061073e9190612f1d565b90508086600801835f0151604051610756919061312a565b90815260408051602092819003830181209390935560e0830181526002835284518284015284810180516001600160401b03908116858401525f60608601819052915181166080860152421660a085015260c0840181905284815260078a01909252902081518154829060ff191660018360058111156107d8576107d8612d37565b0217905550602082015160018201906107f19082613186565b506040828101516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090930151600390920180546001600160401b03191692841692909217909155830151610895911685613259565b82516040519195506108a69161312a565b60408051918290038220908401516001600160401b031682529082907f9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf9060200160405180910390a35050806108fb9061326c565b9050610622565b5060048301819055600183015460649061092690600160401b900460ff168361328e565b101561094857604051635943317f60e01b815260048101829052602401610472565b5f61095e6109558661106e565b60400151611179565b90505f61096a87611306565b90505f60028260405161097d919061312a565b602060405180830381855afa158015610998573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906109bb9190612f1d565b90508281146109e757604051631872fc8d60e01b81526004810182905260248101849052604401610472565b5050506009909201805460ff1916600117905550505050565b610a09816114db565b505050565b5f610a1882610e44565b6080015192915050565b610a2a611815565b610a335f611847565b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b610a6b611815565b610a74816118b7565b5050565b5f610a81611815565b610a8b8383611b8f565b90505b92915050565b5f610a9d610ffb565b90505f80610ab6610aad8561106e565b604001516120ec565b9150915080610adc57604051632d07135360e01b81528115156004820152602401610472565b5f82815260068401602052604090208054610af690612ec5565b90505f03610b1a5760405163089938b360e11b815260048101839052602401610472565b60015f83815260078501602052604090205460ff166005811115610b4057610b40612d37565b14610b73575f8281526007840160205260409081902054905163170cc93360e21b81526104729160ff1690600401612efd565b5f8281526006840160205260408120610b8b91612b56565b5f828152600784016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160c01b026001600160c01b0390931692909217928390558451600160801b9093041682529181019190915283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a250505050565b5f610c23610ffb565b5f8381526006820160205260409020805491925090610c4190612ec5565b90505f03610c655760405163089938b360e11b815260048101839052602401610472565b60015f83815260078301602052604090205460ff166005811115610c8b57610c8b612d37565b14610cbe575f8281526007820160205260409081902054905163170cc93360e21b81526104729160ff1690600401612efd565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610cf791906004016132a5565b6020604051808303815f875af1158015610d13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a099190612f1d565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610d7b5750825b90505f826001600160401b03166001148015610d965750303b155b905081158015610da4575080155b15610dc25760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b03191660011785558315610deb57845460ff60401b1916600160401b1785555b610df587876122a8565b8315610e3b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b610e4c612b8d565b5f610e55610ffb565b5f84815260078201602052604090819020815160e0810190925280549293509091829060ff166005811115610e8c57610e8c612d37565b6005811115610e9d57610e9d612d37565b8152602001600182018054610eb190612ec5565b80601f0160208091040260200160405190810160405280929190818152602001828054610edd90612ec5565b8015610f285780601f10610eff57610100808354040283529160200191610f28565b820191905f5260205f20905b815481529060010190602001808311610f0b57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b9091048116608083015260039092015490911660a0909101529392505050565b610f8e611815565b6001600160a01b038116610fb7575f604051631e4fbdf760e01b81526004016104729190612c78565b610fc081611847565b50565b5f80610fcd610ffb565b9050806008018484604051610fe392919061332f565b90815260200160405180910390205491505092915050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0090565b604080515f6020820152600360e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b60408051606080820183525f8083526020830152918101919091526040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156110d2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110f9919081019061334d565b915091508061111b57604051636b2f19e960e01b815260040160405180910390fd5b815115611141578151604051636ba589a560e01b81526004810191909152602401610472565b60208201516001600160a01b031615611172578160200151604051624de75d60e31b81526004016104729190612c78565b5092915050565b5f81516026146111ae57815160405163cc92daa160e01b815263ffffffff909116600482015260266024820152604401610472565b5f805b60028110156111fd576111c581600161341f565b6111d090600861328e565b61ffff168482815181106111e6576111e6612f79565b016020015160f81c901b91909117906001016111b1565b5061ffff8116156112275760405163407b587360e01b815261ffff82166004820152602401610472565b5f805b60048110156112825761123e81600361341f565b61124990600861328e565b63ffffffff168561125b836002613259565b8151811061126b5761126b612f79565b016020015160f81c901b919091179060010161122a565b5063ffffffff8116156112a857604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156112fd576112bf81601f61341f565b6112ca90600861328e565b866112d6836006613259565b815181106112e6576112e6612f79565b016020015160f81c901b91909117906001016112ab565b50949350505050565b60605f8083356020850135601461132287870160408901612e38565b61132f6060890189612f34565b60405160f09790971b6001600160f01b0319166020880152602287019590955250604285019290925260e090811b6001600160e01b0319908116606286015260609290921b6001600160601b03191660668501529190911b16607a820152607e0160405160208183030381529060405290505f5b6113b06060850185612f34565b905081101561117257816113c76060860186612f34565b838181106113d7576113d7612f79565b90506020028101906113e99190612f8d565b6113f39080613432565b90506114026060870187612f34565b8481811061141257611412612f79565b90506020028101906114249190612f8d565b61142e9080613432565b61143b6060890189612f34565b8681811061144b5761144b612f79565b905060200281019061145d9190612f8d565b61146b906020810190613432565b61147860608b018b612f34565b8881811061148857611488612f79565b905060200281019061149a9190612f8d565b6114ab906060810190604001613474565b6040516020016114c1979695949392919061348d565b60408051601f1981840301815291905291506001016113a3565b5f6114e4612b8d565b5f6114ed610ffb565b90505f806114fd610aad8761106e565b91509150801561152457604051632d07135360e01b81528115156004820152602401610472565b5f828152600784016020526040808220815160e081019092528054829060ff16600581111561155557611555612d37565b600581111561156657611566612d37565b815260200160018201805461157a90612ec5565b80601f01602080910402602001604051908101604052809291908181526020018280546115a690612ec5565b80156115f15780601f106115c8576101008083540402835291602001916115f1565b820191905f5260205f20905b8154815290600101906020018083116115d457829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561165c5761165c612d37565b1415801561167d575060018151600581111561167a5761167a612d37565b14155b1561169e57805160405163170cc93360e21b81526104729190600401612efd565b6003815160058111156116b3576116b3612d37565b036116c157600481526116c6565b600581525b8360080181602001516040516116dc919061312a565b90815260408051602092819003830190205f908190558581526007870190925290208151815483929190829060ff1916600183600581111561172057611720612d37565b0217905550602082015160018201906117399082613186565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b03191691909216179055805160058111156117de576117de612d37565b60405184907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a39196919550909350505050565b3361181e610a35565b6001600160a01b031614610a33573360405163118cdaa760e01b81526004016104729190612c78565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b6118bf612b8d565b5f6118c8610ffb565b5f848152600782016020526040808220815160e0810190925280549394509192909190829060ff16600581111561190157611901612d37565b600581111561191257611912612d37565b815260200160018201805461192690612ec5565b80601f016020809104026020016040519081016040528092919081815260200182805461195290612ec5565b801561199d5780601f106119745761010080835404028352916020019161199d565b820191905f5260205f20905b81548152906001019060200180831161198057829003601f168201915b50505091835250506002828101546001600160401b038082166020850152600160401b820481166040850152600160801b820481166060850152600160c01b9091048116608084015260039093015490921660a09091015290915081516005811115611a0b57611a0b612d37565b14611a3e575f8481526007830160205260409081902054905163170cc93360e21b81526104729160ff1690600401612efd565b60038152426001600160401b031660c08201525f84815260078301602052604090208151815483929190829060ff19166001836005811115611a8257611a82612d37565b021790555060208201516001820190611a9b9082613186565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b031916919092161790555f611b3885826122c2565b6080840151604080516001600160401b03909216825242602083015291935083925087917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a3509392505050565b5f611b98610ffb565b6009015460ff16611bbc57604051637fab81e560e01b815260040160405180910390fd5b5f611bc5610ffb565b905042611bd86060860160408701613474565b6001600160401b0316111580611c125750611bf66202a30042613259565b611c066060860160408701613474565b6001600160401b031610155b15611c4c57611c276060850160408601613474565b604051635879da1360e11b81526001600160401b039091166004820152602401610472565b611c61611c5c60608601866134f6565b61240c565b611c71611c5c60808601866134f6565b6030611c806020860186613432565b905014611cb257611c946020850185613432565b6040516326475b2f60e11b8152610472925060040190815260200190565b611cbc8480613432565b90505f03611ce957611cce8480613432565b604051633e08a12560e11b815260040161047292919061350a565b5f60088201611cf88680613432565b604051611d0692919061332f565b90815260200160405180910390205414611d3f57611d248480613432565b60405163a41f772f60e01b815260040161047292919061350a565b611d49835f612575565b6040805160e08101909152815481525f908190611e559060208101611d6e8980613432565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250602090810190611db6908a018a613432565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250602001611dff60608a0160408b01613474565b6001600160401b03168152602001611e1a60608a018a6134f6565b611e2390613538565b8152602001611e3560808a018a6134f6565b611e3e90613538565b8152602001876001600160401b031681525061279a565b5f82815260068601602052604090209193509150611e738282613186565b508160088401611e838880613432565b604051611e9192919061332f565b9081526040519081900360200181209190915563ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90611ecd908590600401612f0b565b6020604051808303815f875af1158015611ee9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f0d9190612f1d565b6040805160e081019091529091508060018152602001611f2d8980613432565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509385525050506001600160401b0389166020808401829052604080850184905260608501929092526080840183905260a0909301829052868252600788019092522081518154829060ff19166001836005811115611fbc57611fbc612d37565b021790555060208201516001820190611fd59082613186565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c090920151600390910180546001600160401b03191691909216179055806120728880613432565b60405161208092919061332f565b6040518091039020847fb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430898b60400160208101906120be9190613474565b604080516001600160401b0393841681529290911660208301520160405180910390a4509095945050505050565b5f80825160271461212257825160405163cc92daa160e01b815263ffffffff909116600482015260276024820152604401610472565b5f805b60028110156121715761213981600161341f565b61214490600861328e565b61ffff1685828151811061215a5761215a612f79565b016020015160f81c901b9190911790600101612125565b5061ffff81161561219b5760405163407b587360e01b815261ffff82166004820152602401610472565b5f805b60048110156121f6576121b281600361341f565b6121bd90600861328e565b63ffffffff16866121cf836002613259565b815181106121df576121df612f79565b016020015160f81c901b919091179060010161219e565b5063ffffffff811660021461221e57604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156122735761223581601f61341f565b61224090600861328e565b8761224c836006613259565b8151811061225c5761225c612f79565b016020015160f81c901b9190911790600101612221565b505f8660268151811061228857612288612f79565b016020015191976001600160f81b03199092161515965090945050505050565b6122b0612987565b6122b9826129d0565b610a74816129e9565b5f805f6122cd610ffb565b5f868152600782016020526040902060020154909150600160801b90046001600160401b03166122fd8582612575565b5f612307876129fa565b5f8881526007850160205260408120600201805467ffffffffffffffff60801b1916600160801b6001600160401b038b16021790559091506005600160991b0163ee5b48eb6123578a858b61101f565b6040518263ffffffff1660e01b81526004016123739190612f0b565b6020604051808303815f875af115801561238f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123b39190612f1d565b604080516001600160401b038a811682526020820184905282519394508516928b927f07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df928290030190a3909450925050505b9250929050565b6124196020820182612c5f565b63ffffffff1615801561243957506124346020820182612f34565b151590505b156124805761244b6020820182612c5f565b6124586020830183612f34565b60405163c08a0f1d60e01b815263ffffffff9093166004840152602483015250604401610472565b61248d6020820182612f34565b905061249c6020830183612c5f565b63ffffffff1611156124b55761244b6020820182612c5f565b60015b6124c56020830183612f34565b9050811015610a74576124db6020830183612f34565b6124e660018461341f565b8181106124f5576124f5612f79565b905060200201602081019061250a9190612e38565b6001600160a01b03166125206020840184612f34565b8381811061253057612530612f79565b90506020020160208101906125459190612e38565b6001600160a01b0316101561256d57604051630dbc8d5f60e31b815260040160405180910390fd5b6001016124b8565b5f61257e610ffb565b90505f826001600160401b0316846001600160401b031611156125ac576125a583856135ff565b90506125b9565b6125b684846135ff565b90505b6040805160808101825260028401548082526003850154602083015260048501549282019290925260058401546001600160401b031660608201524291158061261b575060018401548151612617916001600160401b031690613259565b8210155b15612641576001600160401b038316606082015281815260408101516020820152612660565b8281606001818151612653919061361f565b6001600160401b03169052505b606081015161267090606461363f565b602082015160018601546001600160401b03929092169161269b9190600160401b900460ff1661328e565b10156126cb57606081015160405163dfae880160e01b81526001600160401b039091166004820152602401610472565b856001600160401b0316816040018181516126e69190613259565b9052506040810180516001600160401b038716919061270690839061341f565b9052506001840154604082015160649161272b91600160401b90910460ff169061328e565b1015612752578060400151604051635943317f60e01b815260040161047291815260200190565b80516002850155602081015160038501556040810151600485015560600151600590930180546001600160401b0319166001600160401b039094169390931790925550505050565b5f60608260400151516030146127c35760405163180ffa0d60e01b815260040160405180910390fd5b82516020808501518051604080880151606089015160808a01518051908701515193515f98612804988a98600198929792969095909490939092910161366a565b60405160208183030381529060405290505f5b846080015160200151518110156128765781856080015160200151828151811061284357612843612f79565b602002602001015160405160200161285c929190613724565b60408051601f198184030181529190529150600101612817565b5060a0840151805160209182015151604051612896938593929101613755565b60405160208183030381529060405290505f5b8460a00151602001515181101561290857818560a001516020015182815181106128d5576128d5612f79565b60200260200101516040516020016128ee929190613724565b60408051601f1981840301815291905291506001016128a9565b5060c084015160405161291f918391602001613790565b6040516020818303038152906040529050600281604051612940919061312a565b602060405180830381855afa15801561295b573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061297e9190612f1d565b94909350915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610a3357604051631afcd79f60e31b815260040160405180910390fd5b6129d8612987565b6129e0612a63565b610fc081612a6b565b6129f1612987565b610fc081612b4e565b5f80612a04610ffb565b5f8481526007820160205260409020600201805491925090600890612a3890600160401b90046001600160401b03166137c1565b91906101000a8154816001600160401b0302191690836001600160401b031602179055915050919050565b610a33612987565b612a73612987565b5f612a7c610ffb565b8235815590506014612a9460608401604085016137dc565b60ff161180612ab35750612aae60608301604084016137dc565b60ff16155b15612ae757612ac860608301604084016137dc565b604051634a59bbff60e11b815260ff9091166004820152602401610472565b612af760608301604084016137dc565b60018201805460ff92909216600160401b0260ff60401b19909216919091179055612b286040830160208401613474565b60019190910180546001600160401b0319166001600160401b0390921691909117905550565b610f8e612987565b508054612b6290612ec5565b5f825580601f10612b71575050565b601f0160209004905f5260205f2090810190610fc09190612bca565b6040805160e08101909152805f81526060602082018190525f604083018190529082018190526080820181905260a0820181905260c09091015290565b5b80821115612bde575f8155600101612bcb565b5090565b5f60208284031215612bf2575f80fd5b5035919050565b803563ffffffff81168114612c0c575f80fd5b919050565b5f8060408385031215612c22575f80fd5b82356001600160401b03811115612c37575f80fd5b830160808186031215612c48575f80fd5b9150612c5660208401612bf9565b90509250929050565b5f60208284031215612c6f575f80fd5b610a8b82612bf9565b6001600160a01b0391909116815260200190565b80356001600160401b0381168114612c0c575f80fd5b5f8060408385031215612cb3575f80fd5b82356001600160401b03811115612cc8575f80fd5b830160a08186031215612cd9575f80fd5b9150612c5660208401612c8c565b6001600160a01b0381168114610fc0575f80fd5b5f808284036080811215612d0d575f80fd5b6060811215612d1a575f80fd5b508291506060830135612d2c81612ce7565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b60068110612d6757634e487b7160e01b5f52602160045260245ffd5b9052565b5f5b83811015612d85578181015183820152602001612d6d565b50505f910152565b5f8151808452612da4816020860160208601612d6b565b601f01601f19169290920160200192915050565b60208152612dca602082018351612d4b565b5f602083015160e06040840152612de5610100840182612d8d565b905060408401516001600160401b0380821660608601528060608701511660808601528060808701511660a08601528060a08701511660c08601528060c08701511660e086015250508091505092915050565b5f60208284031215612e48575f80fd5b8135612e5381612ce7565b9392505050565b5f8060208385031215612e6b575f80fd5b82356001600160401b0380821115612e81575f80fd5b818501915085601f830112612e94575f80fd5b813581811115612ea2575f80fd5b866020828501011115612eb3575f80fd5b60209290920196919550909350505050565b600181811c90821680612ed957607f821691505b602082108103612ef757634e487b7160e01b5f52602260045260245ffd5b50919050565b60208101610a8e8284612d4b565b602081525f610a8b6020830184612d8d565b5f60208284031215612f2d575f80fd5b5051919050565b5f808335601e19843603018112612f49575f80fd5b8301803591506001600160401b03821115612f62575f80fd5b6020019150600581901b3603821315612405575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112612fa1575f80fd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715612fe157612fe1612fab565b60405290565b604080519081016001600160401b0381118282101715612fe157612fe1612fab565b604051601f8201601f191681016001600160401b038111828210171561303157613031612fab565b604052919050565b5f6001600160401b0382111561305157613051612fab565b50601f01601f191660200190565b5f82601f83011261306e575f80fd5b813561308161307c82613039565b613009565b818152846020838601011115613095575f80fd5b816020850160208301375f918101602001919091529392505050565b5f606082360312156130c1575f80fd5b6130c9612fbf565b82356001600160401b03808211156130df575f80fd5b6130eb3683870161305f565b83526020850135915080821115613100575f80fd5b5061310d3682860161305f565b60208301525061311f60408401612c8c565b604082015292915050565b5f8251612fa1818460208701612d6b565b601f821115610a0957805f5260205f20601f840160051c810160208510156131605750805b601f840160051c820191505b8181101561317f575f815560010161316c565b5050505050565b81516001600160401b0381111561319f5761319f612fab565b6131b3816131ad8454612ec5565b8461313b565b602080601f8311600181146131e6575f84156131cf5750858301515b5f19600386901b1c1916600185901b17855561323d565b5f85815260208120601f198616915b82811015613214578886015182559484019460019091019084016131f5565b508582101561323157878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610a8e57610a8e613245565b5f63ffffffff80831681810361328457613284613245565b6001019392505050565b8082028115828204841417610a8e57610a8e613245565b5f60208083525f84546132b781612ec5565b806020870152604060018084165f81146132d857600181146132f457613321565b60ff19851660408a0152604084151560051b8a01019550613321565b895f5260205f205f5b858110156133185781548b82018601529083019088016132fd565b8a016040019650505b509398975050505050505050565b818382375f9101908152919050565b80518015158114612c0c575f80fd5b5f806040838503121561335e575f80fd5b82516001600160401b0380821115613374575f80fd5b9084019060608287031215613387575f80fd5b61338f612fbf565b825181526020808401516133a281612ce7565b828201526040840151838111156133b7575f80fd5b80850194505087601f8501126133cb575f80fd5b835192506133db61307c84613039565b83815288828587010111156133ee575f80fd5b6133fd84838301848801612d6b565b8060408401525081955061341281880161333e565b9450505050509250929050565b81810381811115610a8e57610a8e613245565b5f808335601e19843603018112613447575f80fd5b8301803591506001600160401b03821115613460575f80fd5b602001915036819003821315612405575f80fd5b5f60208284031215613484575f80fd5b610a8b82612c8c565b5f885161349e818460208d01612d6b565b60e089901b6001600160e01b031916908301908152868860048301378681019050600481015f8152858782375060c09390931b6001600160c01b0319166004939094019283019390935250600c019695505050505050565b5f8235603e19833603018112612fa1575f80fd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60408236031215613548575f80fd5b613550612fe7565b61355983612bf9565b81526020808401356001600160401b0380821115613575575f80fd5b9085019036601f830112613587575f80fd5b81358181111561359957613599612fab565b8060051b91506135aa848301613009565b81815291830184019184810190368411156135c3575f80fd5b938501935b838510156135ed57843592506135dd83612ce7565b82825293850193908501906135c8565b94860194909452509295945050505050565b6001600160401b0382811682821603908082111561117257611172613245565b6001600160401b0381811683821601908082111561117257611172613245565b6001600160401b0381811683821602808216919082811461366257613662613245565b505092915050565b61ffff60f01b8a60f01b1681525f63ffffffff60e01b808b60e01b166002840152896006840152808960e01b1660268401525086516136b081602a850160208b01612d6b565b8651908301906136c781602a840160208b01612d6b565b60c087901b6001600160c01b031916602a92909101918201526136f9603282018660e01b6001600160e01b0319169052565b613712603682018560e01b6001600160e01b0319169052565b603a019b9a5050505050505050505050565b5f8351613735818460208801612d6b565b60609390931b6001600160601b0319169190920190815260140192915050565b5f8451613766818460208901612d6b565b6001600160e01b031960e095861b8116919093019081529290931b16600482015260080192915050565b5f83516137a1818460208801612d6b565b60c09390931b6001600160c01b0319169190920190815260080192915050565b5f6001600160401b0380831681810361328457613284613245565b5f602082840312156137ec575f80fd5b813560ff81168114612e53575f80fdfea164736f6c6343000819000a", +} + +// PoAValidatorManagerABI is the input ABI used to generate the binding from. +// Deprecated: Use PoAValidatorManagerMetaData.ABI instead. +var PoAValidatorManagerABI = PoAValidatorManagerMetaData.ABI + +// PoAValidatorManagerBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use PoAValidatorManagerMetaData.Bin instead. +var PoAValidatorManagerBin = PoAValidatorManagerMetaData.Bin + +// DeployPoAValidatorManager deploys a new Ethereum contract, binding an instance of PoAValidatorManager to it. +func DeployPoAValidatorManager(auth *bind.TransactOpts, backend bind.ContractBackend, init uint8) (common.Address, *types.Transaction, *PoAValidatorManager, error) { + parsed, err := PoAValidatorManagerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PoAValidatorManagerBin), backend, init) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &PoAValidatorManager{PoAValidatorManagerCaller: PoAValidatorManagerCaller{contract: contract}, PoAValidatorManagerTransactor: PoAValidatorManagerTransactor{contract: contract}, PoAValidatorManagerFilterer: PoAValidatorManagerFilterer{contract: contract}}, nil +} + +// PoAValidatorManager is an auto generated Go binding around an Ethereum contract. +type PoAValidatorManager struct { + PoAValidatorManagerCaller // Read-only binding to the contract + PoAValidatorManagerTransactor // Write-only binding to the contract + PoAValidatorManagerFilterer // Log filterer for contract events +} + +// PoAValidatorManagerCaller is an auto generated read-only Go binding around an Ethereum contract. +type PoAValidatorManagerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PoAValidatorManagerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PoAValidatorManagerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PoAValidatorManagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PoAValidatorManagerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PoAValidatorManagerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PoAValidatorManagerSession struct { + Contract *PoAValidatorManager // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PoAValidatorManagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PoAValidatorManagerCallerSession struct { + Contract *PoAValidatorManagerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PoAValidatorManagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PoAValidatorManagerTransactorSession struct { + Contract *PoAValidatorManagerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PoAValidatorManagerRaw is an auto generated low-level Go binding around an Ethereum contract. +type PoAValidatorManagerRaw struct { + Contract *PoAValidatorManager // Generic contract binding to access the raw methods on +} + +// PoAValidatorManagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PoAValidatorManagerCallerRaw struct { + Contract *PoAValidatorManagerCaller // Generic read-only contract binding to access the raw methods on +} + +// PoAValidatorManagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PoAValidatorManagerTransactorRaw struct { + Contract *PoAValidatorManagerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPoAValidatorManager creates a new instance of PoAValidatorManager, bound to a specific deployed contract. +func NewPoAValidatorManager(address common.Address, backend bind.ContractBackend) (*PoAValidatorManager, error) { + contract, err := bindPoAValidatorManager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &PoAValidatorManager{PoAValidatorManagerCaller: PoAValidatorManagerCaller{contract: contract}, PoAValidatorManagerTransactor: PoAValidatorManagerTransactor{contract: contract}, PoAValidatorManagerFilterer: PoAValidatorManagerFilterer{contract: contract}}, nil +} + +// NewPoAValidatorManagerCaller creates a new read-only instance of PoAValidatorManager, bound to a specific deployed contract. +func NewPoAValidatorManagerCaller(address common.Address, caller bind.ContractCaller) (*PoAValidatorManagerCaller, error) { + contract, err := bindPoAValidatorManager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PoAValidatorManagerCaller{contract: contract}, nil +} + +// NewPoAValidatorManagerTransactor creates a new write-only instance of PoAValidatorManager, bound to a specific deployed contract. +func NewPoAValidatorManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*PoAValidatorManagerTransactor, error) { + contract, err := bindPoAValidatorManager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PoAValidatorManagerTransactor{contract: contract}, nil +} + +// NewPoAValidatorManagerFilterer creates a new log filterer instance of PoAValidatorManager, bound to a specific deployed contract. +func NewPoAValidatorManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*PoAValidatorManagerFilterer, error) { + contract, err := bindPoAValidatorManager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PoAValidatorManagerFilterer{contract: contract}, nil +} + +// bindPoAValidatorManager binds a generic wrapper to an already deployed contract. +func bindPoAValidatorManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PoAValidatorManagerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_PoAValidatorManager *PoAValidatorManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _PoAValidatorManager.Contract.PoAValidatorManagerCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_PoAValidatorManager *PoAValidatorManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.PoAValidatorManagerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_PoAValidatorManager *PoAValidatorManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.PoAValidatorManagerTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_PoAValidatorManager *PoAValidatorManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _PoAValidatorManager.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_PoAValidatorManager *PoAValidatorManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_PoAValidatorManager *PoAValidatorManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.contract.Transact(opts, method, params...) +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_PoAValidatorManager *PoAValidatorManagerCaller) ADDRESSLENGTH(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "ADDRESS_LENGTH") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_PoAValidatorManager *PoAValidatorManagerSession) ADDRESSLENGTH() (uint32, error) { + return _PoAValidatorManager.Contract.ADDRESSLENGTH(&_PoAValidatorManager.CallOpts) +} + +// ADDRESSLENGTH is a free data retrieval call binding the contract method 0x60305d62. +// +// Solidity: function ADDRESS_LENGTH() view returns(uint32) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) ADDRESSLENGTH() (uint32, error) { + return _PoAValidatorManager.Contract.ADDRESSLENGTH(&_PoAValidatorManager.CallOpts) +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_PoAValidatorManager *PoAValidatorManagerCaller) BLSPUBLICKEYLENGTH(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "BLS_PUBLIC_KEY_LENGTH") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_PoAValidatorManager *PoAValidatorManagerSession) BLSPUBLICKEYLENGTH() (uint8, error) { + return _PoAValidatorManager.Contract.BLSPUBLICKEYLENGTH(&_PoAValidatorManager.CallOpts) +} + +// BLSPUBLICKEYLENGTH is a free data retrieval call binding the contract method 0x8280a25a. +// +// Solidity: function BLS_PUBLIC_KEY_LENGTH() view returns(uint8) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) BLSPUBLICKEYLENGTH() (uint8, error) { + return _PoAValidatorManager.Contract.BLSPUBLICKEYLENGTH(&_PoAValidatorManager.CallOpts) +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_PoAValidatorManager *PoAValidatorManagerCaller) MAXIMUMCHURNPERCENTAGELIMIT(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "MAXIMUM_CHURN_PERCENTAGE_LIMIT") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_PoAValidatorManager *PoAValidatorManagerSession) MAXIMUMCHURNPERCENTAGELIMIT() (uint8, error) { + return _PoAValidatorManager.Contract.MAXIMUMCHURNPERCENTAGELIMIT(&_PoAValidatorManager.CallOpts) +} + +// MAXIMUMCHURNPERCENTAGELIMIT is a free data retrieval call binding the contract method 0xc974d1b6. +// +// Solidity: function MAXIMUM_CHURN_PERCENTAGE_LIMIT() view returns(uint8) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) MAXIMUMCHURNPERCENTAGELIMIT() (uint8, error) { + return _PoAValidatorManager.Contract.MAXIMUMCHURNPERCENTAGELIMIT(&_PoAValidatorManager.CallOpts) +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_PoAValidatorManager *PoAValidatorManagerCaller) MAXIMUMREGISTRATIONEXPIRYLENGTH(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "MAXIMUM_REGISTRATION_EXPIRY_LENGTH") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_PoAValidatorManager *PoAValidatorManagerSession) MAXIMUMREGISTRATIONEXPIRYLENGTH() (uint64, error) { + return _PoAValidatorManager.Contract.MAXIMUMREGISTRATIONEXPIRYLENGTH(&_PoAValidatorManager.CallOpts) +} + +// MAXIMUMREGISTRATIONEXPIRYLENGTH is a free data retrieval call binding the contract method 0xdf93d8de. +// +// Solidity: function MAXIMUM_REGISTRATION_EXPIRY_LENGTH() view returns(uint64) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) MAXIMUMREGISTRATIONEXPIRYLENGTH() (uint64, error) { + return _PoAValidatorManager.Contract.MAXIMUMREGISTRATIONEXPIRYLENGTH(&_PoAValidatorManager.CallOpts) +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerCaller) PCHAINBLOCKCHAINID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "P_CHAIN_BLOCKCHAIN_ID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerSession) PCHAINBLOCKCHAINID() ([32]byte, error) { + return _PoAValidatorManager.Contract.PCHAINBLOCKCHAINID(&_PoAValidatorManager.CallOpts) +} + +// PCHAINBLOCKCHAINID is a free data retrieval call binding the contract method 0x732214f8. +// +// Solidity: function P_CHAIN_BLOCKCHAIN_ID() view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) PCHAINBLOCKCHAINID() ([32]byte, error) { + return _PoAValidatorManager.Contract.PCHAINBLOCKCHAINID(&_PoAValidatorManager.CallOpts) +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerCaller) VALIDATORMANAGERSTORAGELOCATION(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "VALIDATOR_MANAGER_STORAGE_LOCATION") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerSession) VALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _PoAValidatorManager.Contract.VALIDATORMANAGERSTORAGELOCATION(&_PoAValidatorManager.CallOpts) +} + +// VALIDATORMANAGERSTORAGELOCATION is a free data retrieval call binding the contract method 0xbc5fbfec. +// +// Solidity: function VALIDATOR_MANAGER_STORAGE_LOCATION() view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) VALIDATORMANAGERSTORAGELOCATION() ([32]byte, error) { + return _PoAValidatorManager.Contract.VALIDATORMANAGERSTORAGELOCATION(&_PoAValidatorManager.CallOpts) +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_PoAValidatorManager *PoAValidatorManagerCaller) WARPMESSENGER(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "WARP_MESSENGER") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_PoAValidatorManager *PoAValidatorManagerSession) WARPMESSENGER() (common.Address, error) { + return _PoAValidatorManager.Contract.WARPMESSENGER(&_PoAValidatorManager.CallOpts) +} + +// WARPMESSENGER is a free data retrieval call binding the contract method 0xb771b3bc. +// +// Solidity: function WARP_MESSENGER() view returns(address) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) WARPMESSENGER() (common.Address, error) { + return _PoAValidatorManager.Contract.WARPMESSENGER(&_PoAValidatorManager.CallOpts) +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_PoAValidatorManager *PoAValidatorManagerCaller) GetValidator(opts *bind.CallOpts, validationID [32]byte) (Validator, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "getValidator", validationID) + + if err != nil { + return *new(Validator), err + } + + out0 := *abi.ConvertType(out[0], new(Validator)).(*Validator) + + return out0, err + +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_PoAValidatorManager *PoAValidatorManagerSession) GetValidator(validationID [32]byte) (Validator, error) { + return _PoAValidatorManager.Contract.GetValidator(&_PoAValidatorManager.CallOpts, validationID) +} + +// GetValidator is a free data retrieval call binding the contract method 0xd5f20ff6. +// +// Solidity: function getValidator(bytes32 validationID) view returns((uint8,bytes,uint64,uint64,uint64,uint64,uint64)) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) GetValidator(validationID [32]byte) (Validator, error) { + return _PoAValidatorManager.Contract.GetValidator(&_PoAValidatorManager.CallOpts, validationID) +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_PoAValidatorManager *PoAValidatorManagerCaller) GetWeight(opts *bind.CallOpts, validationID [32]byte) (uint64, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "getWeight", validationID) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_PoAValidatorManager *PoAValidatorManagerSession) GetWeight(validationID [32]byte) (uint64, error) { + return _PoAValidatorManager.Contract.GetWeight(&_PoAValidatorManager.CallOpts, validationID) +} + +// GetWeight is a free data retrieval call binding the contract method 0x66435abf. +// +// Solidity: function getWeight(bytes32 validationID) view returns(uint64) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) GetWeight(validationID [32]byte) (uint64, error) { + return _PoAValidatorManager.Contract.GetWeight(&_PoAValidatorManager.CallOpts, validationID) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_PoAValidatorManager *PoAValidatorManagerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_PoAValidatorManager *PoAValidatorManagerSession) Owner() (common.Address, error) { + return _PoAValidatorManager.Contract.Owner(&_PoAValidatorManager.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) Owner() (common.Address, error) { + return _PoAValidatorManager.Contract.Owner(&_PoAValidatorManager.CallOpts) +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerCaller) RegisteredValidators(opts *bind.CallOpts, nodeID []byte) ([32]byte, error) { + var out []interface{} + err := _PoAValidatorManager.contract.Call(opts, &out, "registeredValidators", nodeID) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerSession) RegisteredValidators(nodeID []byte) ([32]byte, error) { + return _PoAValidatorManager.Contract.RegisteredValidators(&_PoAValidatorManager.CallOpts, nodeID) +} + +// RegisteredValidators is a free data retrieval call binding the contract method 0xfd7ac5e7. +// +// Solidity: function registeredValidators(bytes nodeID) view returns(bytes32) +func (_PoAValidatorManager *PoAValidatorManagerCallerSession) RegisteredValidators(nodeID []byte) ([32]byte, error) { + return _PoAValidatorManager.Contract.RegisteredValidators(&_PoAValidatorManager.CallOpts, nodeID) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) CompleteEndValidation(opts *bind.TransactOpts, messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "completeEndValidation", messageIndex) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) CompleteEndValidation(messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.CompleteEndValidation(&_PoAValidatorManager.TransactOpts, messageIndex) +} + +// CompleteEndValidation is a paid mutator transaction binding the contract method 0x467ef06f. +// +// Solidity: function completeEndValidation(uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) CompleteEndValidation(messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.CompleteEndValidation(&_PoAValidatorManager.TransactOpts, messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) CompleteValidatorRegistration(opts *bind.TransactOpts, messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "completeValidatorRegistration", messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) CompleteValidatorRegistration(messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.CompleteValidatorRegistration(&_PoAValidatorManager.TransactOpts, messageIndex) +} + +// CompleteValidatorRegistration is a paid mutator transaction binding the contract method 0xa3a65e48. +// +// Solidity: function completeValidatorRegistration(uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) CompleteValidatorRegistration(messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.CompleteValidatorRegistration(&_PoAValidatorManager.TransactOpts, messageIndex) +} + +// Initialize is a paid mutator transaction binding the contract method 0xd588c18f. +// +// Solidity: function initialize((bytes32,uint64,uint8) settings, address initialOwner) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) Initialize(opts *bind.TransactOpts, settings ValidatorManagerSettings, initialOwner common.Address) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "initialize", settings, initialOwner) +} + +// Initialize is a paid mutator transaction binding the contract method 0xd588c18f. +// +// Solidity: function initialize((bytes32,uint64,uint8) settings, address initialOwner) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) Initialize(settings ValidatorManagerSettings, initialOwner common.Address) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.Initialize(&_PoAValidatorManager.TransactOpts, settings, initialOwner) +} + +// Initialize is a paid mutator transaction binding the contract method 0xd588c18f. +// +// Solidity: function initialize((bytes32,uint64,uint8) settings, address initialOwner) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) Initialize(settings ValidatorManagerSettings, initialOwner common.Address) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.Initialize(&_PoAValidatorManager.TransactOpts, settings, initialOwner) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x97fb70d4. +// +// Solidity: function initializeEndValidation(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) InitializeEndValidation(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "initializeEndValidation", validationID) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x97fb70d4. +// +// Solidity: function initializeEndValidation(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) InitializeEndValidation(validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.InitializeEndValidation(&_PoAValidatorManager.TransactOpts, validationID) +} + +// InitializeEndValidation is a paid mutator transaction binding the contract method 0x97fb70d4. +// +// Solidity: function initializeEndValidation(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) InitializeEndValidation(validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.InitializeEndValidation(&_PoAValidatorManager.TransactOpts, validationID) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0x9ba96b86. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint64 weight) returns(bytes32 validationID) +func (_PoAValidatorManager *PoAValidatorManagerTransactor) InitializeValidatorRegistration(opts *bind.TransactOpts, registrationInput ValidatorRegistrationInput, weight uint64) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "initializeValidatorRegistration", registrationInput, weight) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0x9ba96b86. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint64 weight) returns(bytes32 validationID) +func (_PoAValidatorManager *PoAValidatorManagerSession) InitializeValidatorRegistration(registrationInput ValidatorRegistrationInput, weight uint64) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.InitializeValidatorRegistration(&_PoAValidatorManager.TransactOpts, registrationInput, weight) +} + +// InitializeValidatorRegistration is a paid mutator transaction binding the contract method 0x9ba96b86. +// +// Solidity: function initializeValidatorRegistration((bytes,bytes,uint64,(uint32,address[]),(uint32,address[])) registrationInput, uint64 weight) returns(bytes32 validationID) +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) InitializeValidatorRegistration(registrationInput ValidatorRegistrationInput, weight uint64) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.InitializeValidatorRegistration(&_PoAValidatorManager.TransactOpts, registrationInput, weight) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) InitializeValidatorSet(opts *bind.TransactOpts, subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "initializeValidatorSet", subnetConversionData, messageIndex) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) InitializeValidatorSet(subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.InitializeValidatorSet(&_PoAValidatorManager.TransactOpts, subnetConversionData, messageIndex) +} + +// InitializeValidatorSet is a paid mutator transaction binding the contract method 0x20d91b7a. +// +// Solidity: function initializeValidatorSet((bytes32,bytes32,address,(bytes,bytes,uint64)[]) subnetConversionData, uint32 messageIndex) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) InitializeValidatorSet(subnetConversionData SubnetConversionData, messageIndex uint32) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.InitializeValidatorSet(&_PoAValidatorManager.TransactOpts, subnetConversionData, messageIndex) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) RenounceOwnership() (*types.Transaction, error) { + return _PoAValidatorManager.Contract.RenounceOwnership(&_PoAValidatorManager.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _PoAValidatorManager.Contract.RenounceOwnership(&_PoAValidatorManager.TransactOpts) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) ResendEndValidatorMessage(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "resendEndValidatorMessage", validationID) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) ResendEndValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.ResendEndValidatorMessage(&_PoAValidatorManager.TransactOpts, validationID) +} + +// ResendEndValidatorMessage is a paid mutator transaction binding the contract method 0x0322ed98. +// +// Solidity: function resendEndValidatorMessage(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) ResendEndValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.ResendEndValidatorMessage(&_PoAValidatorManager.TransactOpts, validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) ResendRegisterValidatorMessage(opts *bind.TransactOpts, validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "resendRegisterValidatorMessage", validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) ResendRegisterValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.ResendRegisterValidatorMessage(&_PoAValidatorManager.TransactOpts, validationID) +} + +// ResendRegisterValidatorMessage is a paid mutator transaction binding the contract method 0xbee0a03f. +// +// Solidity: function resendRegisterValidatorMessage(bytes32 validationID) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) ResendRegisterValidatorMessage(validationID [32]byte) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.ResendRegisterValidatorMessage(&_PoAValidatorManager.TransactOpts, validationID) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _PoAValidatorManager.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_PoAValidatorManager *PoAValidatorManagerSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.TransferOwnership(&_PoAValidatorManager.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_PoAValidatorManager *PoAValidatorManagerTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _PoAValidatorManager.Contract.TransferOwnership(&_PoAValidatorManager.TransactOpts, newOwner) +} + +// PoAValidatorManagerInitialValidatorCreatedIterator is returned from FilterInitialValidatorCreated and is used to iterate over the raw logs and unpacked data for InitialValidatorCreated events raised by the PoAValidatorManager contract. +type PoAValidatorManagerInitialValidatorCreatedIterator struct { + Event *PoAValidatorManagerInitialValidatorCreated // 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 interfaces.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 *PoAValidatorManagerInitialValidatorCreatedIterator) 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(PoAValidatorManagerInitialValidatorCreated) + 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(PoAValidatorManagerInitialValidatorCreated) + 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 *PoAValidatorManagerInitialValidatorCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerInitialValidatorCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerInitialValidatorCreated represents a InitialValidatorCreated event raised by the PoAValidatorManager contract. +type PoAValidatorManagerInitialValidatorCreated struct { + ValidationID [32]byte + NodeID common.Hash + Weight *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialValidatorCreated is a free log retrieval operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterInitialValidatorCreated(opts *bind.FilterOpts, validationID [][32]byte, nodeID [][]byte) (*PoAValidatorManagerInitialValidatorCreatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "InitialValidatorCreated", validationIDRule, nodeIDRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerInitialValidatorCreatedIterator{contract: _PoAValidatorManager.contract, event: "InitialValidatorCreated", logs: logs, sub: sub}, nil +} + +// WatchInitialValidatorCreated is a free log subscription operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchInitialValidatorCreated(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerInitialValidatorCreated, validationID [][32]byte, nodeID [][]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "InitialValidatorCreated", validationIDRule, nodeIDRule) + 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(PoAValidatorManagerInitialValidatorCreated) + if err := _PoAValidatorManager.contract.UnpackLog(event, "InitialValidatorCreated", 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 +} + +// ParseInitialValidatorCreated is a log parse operation binding the contract event 0x9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf. +// +// Solidity: event InitialValidatorCreated(bytes32 indexed validationID, bytes indexed nodeID, uint256 weight) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseInitialValidatorCreated(log types.Log) (*PoAValidatorManagerInitialValidatorCreated, error) { + event := new(PoAValidatorManagerInitialValidatorCreated) + if err := _PoAValidatorManager.contract.UnpackLog(event, "InitialValidatorCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the PoAValidatorManager contract. +type PoAValidatorManagerInitializedIterator struct { + Event *PoAValidatorManagerInitialized // 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 interfaces.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 *PoAValidatorManagerInitializedIterator) 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(PoAValidatorManagerInitialized) + 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(PoAValidatorManagerInitialized) + 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 *PoAValidatorManagerInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerInitialized represents a Initialized event raised by the PoAValidatorManager contract. +type PoAValidatorManagerInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterInitialized(opts *bind.FilterOpts) (*PoAValidatorManagerInitializedIterator, error) { + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &PoAValidatorManagerInitializedIterator{contract: _PoAValidatorManager.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerInitialized) (event.Subscription, error) { + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "Initialized") + 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(PoAValidatorManagerInitialized) + if err := _PoAValidatorManager.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseInitialized(log types.Log) (*PoAValidatorManagerInitialized, error) { + event := new(PoAValidatorManagerInitialized) + if err := _PoAValidatorManager.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the PoAValidatorManager contract. +type PoAValidatorManagerOwnershipTransferredIterator struct { + Event *PoAValidatorManagerOwnershipTransferred // 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 interfaces.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 *PoAValidatorManagerOwnershipTransferredIterator) 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(PoAValidatorManagerOwnershipTransferred) + 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(PoAValidatorManagerOwnershipTransferred) + 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 *PoAValidatorManagerOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerOwnershipTransferred represents a OwnershipTransferred event raised by the PoAValidatorManager contract. +type PoAValidatorManagerOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*PoAValidatorManagerOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerOwnershipTransferredIterator{contract: _PoAValidatorManager.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(PoAValidatorManagerOwnershipTransferred) + if err := _PoAValidatorManager.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseOwnershipTransferred(log types.Log) (*PoAValidatorManagerOwnershipTransferred, error) { + event := new(PoAValidatorManagerOwnershipTransferred) + if err := _PoAValidatorManager.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerValidationPeriodCreatedIterator is returned from FilterValidationPeriodCreated and is used to iterate over the raw logs and unpacked data for ValidationPeriodCreated events raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidationPeriodCreatedIterator struct { + Event *PoAValidatorManagerValidationPeriodCreated // 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 interfaces.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 *PoAValidatorManagerValidationPeriodCreatedIterator) 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(PoAValidatorManagerValidationPeriodCreated) + 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(PoAValidatorManagerValidationPeriodCreated) + 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 *PoAValidatorManagerValidationPeriodCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerValidationPeriodCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerValidationPeriodCreated represents a ValidationPeriodCreated event raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidationPeriodCreated struct { + ValidationID [32]byte + NodeID common.Hash + RegisterValidationMessageID [32]byte + Weight *big.Int + RegistrationExpiry uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodCreated is a free log retrieval operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterValidationPeriodCreated(opts *bind.FilterOpts, validationID [][32]byte, nodeID [][]byte, registerValidationMessageID [][32]byte) (*PoAValidatorManagerValidationPeriodCreatedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + var registerValidationMessageIDRule []interface{} + for _, registerValidationMessageIDItem := range registerValidationMessageID { + registerValidationMessageIDRule = append(registerValidationMessageIDRule, registerValidationMessageIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "ValidationPeriodCreated", validationIDRule, nodeIDRule, registerValidationMessageIDRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerValidationPeriodCreatedIterator{contract: _PoAValidatorManager.contract, event: "ValidationPeriodCreated", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodCreated is a free log subscription operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchValidationPeriodCreated(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerValidationPeriodCreated, validationID [][32]byte, nodeID [][]byte, registerValidationMessageID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nodeIDRule []interface{} + for _, nodeIDItem := range nodeID { + nodeIDRule = append(nodeIDRule, nodeIDItem) + } + var registerValidationMessageIDRule []interface{} + for _, registerValidationMessageIDItem := range registerValidationMessageID { + registerValidationMessageIDRule = append(registerValidationMessageIDRule, registerValidationMessageIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "ValidationPeriodCreated", validationIDRule, nodeIDRule, registerValidationMessageIDRule) + 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(PoAValidatorManagerValidationPeriodCreated) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidationPeriodCreated", 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 +} + +// ParseValidationPeriodCreated is a log parse operation binding the contract event 0xb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430. +// +// Solidity: event ValidationPeriodCreated(bytes32 indexed validationID, bytes indexed nodeID, bytes32 indexed registerValidationMessageID, uint256 weight, uint64 registrationExpiry) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseValidationPeriodCreated(log types.Log) (*PoAValidatorManagerValidationPeriodCreated, error) { + event := new(PoAValidatorManagerValidationPeriodCreated) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidationPeriodCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerValidationPeriodEndedIterator is returned from FilterValidationPeriodEnded and is used to iterate over the raw logs and unpacked data for ValidationPeriodEnded events raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidationPeriodEndedIterator struct { + Event *PoAValidatorManagerValidationPeriodEnded // 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 interfaces.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 *PoAValidatorManagerValidationPeriodEndedIterator) 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(PoAValidatorManagerValidationPeriodEnded) + 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(PoAValidatorManagerValidationPeriodEnded) + 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 *PoAValidatorManagerValidationPeriodEndedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerValidationPeriodEndedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerValidationPeriodEnded represents a ValidationPeriodEnded event raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidationPeriodEnded struct { + ValidationID [32]byte + Status uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodEnded is a free log retrieval operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterValidationPeriodEnded(opts *bind.FilterOpts, validationID [][32]byte, status []uint8) (*PoAValidatorManagerValidationPeriodEndedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var statusRule []interface{} + for _, statusItem := range status { + statusRule = append(statusRule, statusItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "ValidationPeriodEnded", validationIDRule, statusRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerValidationPeriodEndedIterator{contract: _PoAValidatorManager.contract, event: "ValidationPeriodEnded", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodEnded is a free log subscription operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchValidationPeriodEnded(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerValidationPeriodEnded, validationID [][32]byte, status []uint8) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var statusRule []interface{} + for _, statusItem := range status { + statusRule = append(statusRule, statusItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "ValidationPeriodEnded", validationIDRule, statusRule) + 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(PoAValidatorManagerValidationPeriodEnded) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidationPeriodEnded", 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 +} + +// ParseValidationPeriodEnded is a log parse operation binding the contract event 0x1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16. +// +// Solidity: event ValidationPeriodEnded(bytes32 indexed validationID, uint8 indexed status) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseValidationPeriodEnded(log types.Log) (*PoAValidatorManagerValidationPeriodEnded, error) { + event := new(PoAValidatorManagerValidationPeriodEnded) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidationPeriodEnded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerValidationPeriodRegisteredIterator is returned from FilterValidationPeriodRegistered and is used to iterate over the raw logs and unpacked data for ValidationPeriodRegistered events raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidationPeriodRegisteredIterator struct { + Event *PoAValidatorManagerValidationPeriodRegistered // 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 interfaces.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 *PoAValidatorManagerValidationPeriodRegisteredIterator) 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(PoAValidatorManagerValidationPeriodRegistered) + 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(PoAValidatorManagerValidationPeriodRegistered) + 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 *PoAValidatorManagerValidationPeriodRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerValidationPeriodRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerValidationPeriodRegistered represents a ValidationPeriodRegistered event raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidationPeriodRegistered struct { + ValidationID [32]byte + Weight *big.Int + Timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidationPeriodRegistered is a free log retrieval operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterValidationPeriodRegistered(opts *bind.FilterOpts, validationID [][32]byte) (*PoAValidatorManagerValidationPeriodRegisteredIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "ValidationPeriodRegistered", validationIDRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerValidationPeriodRegisteredIterator{contract: _PoAValidatorManager.contract, event: "ValidationPeriodRegistered", logs: logs, sub: sub}, nil +} + +// WatchValidationPeriodRegistered is a free log subscription operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchValidationPeriodRegistered(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerValidationPeriodRegistered, validationID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "ValidationPeriodRegistered", validationIDRule) + 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(PoAValidatorManagerValidationPeriodRegistered) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidationPeriodRegistered", 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 +} + +// ParseValidationPeriodRegistered is a log parse operation binding the contract event 0xf8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568. +// +// Solidity: event ValidationPeriodRegistered(bytes32 indexed validationID, uint256 weight, uint256 timestamp) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseValidationPeriodRegistered(log types.Log) (*PoAValidatorManagerValidationPeriodRegistered, error) { + event := new(PoAValidatorManagerValidationPeriodRegistered) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidationPeriodRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerValidatorRemovalInitializedIterator is returned from FilterValidatorRemovalInitialized and is used to iterate over the raw logs and unpacked data for ValidatorRemovalInitialized events raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidatorRemovalInitializedIterator struct { + Event *PoAValidatorManagerValidatorRemovalInitialized // 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 interfaces.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 *PoAValidatorManagerValidatorRemovalInitializedIterator) 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(PoAValidatorManagerValidatorRemovalInitialized) + 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(PoAValidatorManagerValidatorRemovalInitialized) + 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 *PoAValidatorManagerValidatorRemovalInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerValidatorRemovalInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerValidatorRemovalInitialized represents a ValidatorRemovalInitialized event raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidatorRemovalInitialized struct { + ValidationID [32]byte + SetWeightMessageID [32]byte + Weight *big.Int + EndTime *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorRemovalInitialized is a free log retrieval operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterValidatorRemovalInitialized(opts *bind.FilterOpts, validationID [][32]byte, setWeightMessageID [][32]byte) (*PoAValidatorManagerValidatorRemovalInitializedIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var setWeightMessageIDRule []interface{} + for _, setWeightMessageIDItem := range setWeightMessageID { + setWeightMessageIDRule = append(setWeightMessageIDRule, setWeightMessageIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "ValidatorRemovalInitialized", validationIDRule, setWeightMessageIDRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerValidatorRemovalInitializedIterator{contract: _PoAValidatorManager.contract, event: "ValidatorRemovalInitialized", logs: logs, sub: sub}, nil +} + +// WatchValidatorRemovalInitialized is a free log subscription operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchValidatorRemovalInitialized(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerValidatorRemovalInitialized, validationID [][32]byte, setWeightMessageID [][32]byte) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var setWeightMessageIDRule []interface{} + for _, setWeightMessageIDItem := range setWeightMessageID { + setWeightMessageIDRule = append(setWeightMessageIDRule, setWeightMessageIDItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "ValidatorRemovalInitialized", validationIDRule, setWeightMessageIDRule) + 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(PoAValidatorManagerValidatorRemovalInitialized) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidatorRemovalInitialized", 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 +} + +// ParseValidatorRemovalInitialized is a log parse operation binding the contract event 0x13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67. +// +// Solidity: event ValidatorRemovalInitialized(bytes32 indexed validationID, bytes32 indexed setWeightMessageID, uint256 weight, uint256 endTime) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseValidatorRemovalInitialized(log types.Log) (*PoAValidatorManagerValidatorRemovalInitialized, error) { + event := new(PoAValidatorManagerValidatorRemovalInitialized) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidatorRemovalInitialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PoAValidatorManagerValidatorWeightUpdateIterator is returned from FilterValidatorWeightUpdate and is used to iterate over the raw logs and unpacked data for ValidatorWeightUpdate events raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidatorWeightUpdateIterator struct { + Event *PoAValidatorManagerValidatorWeightUpdate // 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 interfaces.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 *PoAValidatorManagerValidatorWeightUpdateIterator) 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(PoAValidatorManagerValidatorWeightUpdate) + 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(PoAValidatorManagerValidatorWeightUpdate) + 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 *PoAValidatorManagerValidatorWeightUpdateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PoAValidatorManagerValidatorWeightUpdateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PoAValidatorManagerValidatorWeightUpdate represents a ValidatorWeightUpdate event raised by the PoAValidatorManager contract. +type PoAValidatorManagerValidatorWeightUpdate struct { + ValidationID [32]byte + Nonce uint64 + ValidatorWeight uint64 + SetWeightMessageID [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorWeightUpdate is a free log retrieval operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) FilterValidatorWeightUpdate(opts *bind.FilterOpts, validationID [][32]byte, nonce []uint64) (*PoAValidatorManagerValidatorWeightUpdateIterator, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + + logs, sub, err := _PoAValidatorManager.contract.FilterLogs(opts, "ValidatorWeightUpdate", validationIDRule, nonceRule) + if err != nil { + return nil, err + } + return &PoAValidatorManagerValidatorWeightUpdateIterator{contract: _PoAValidatorManager.contract, event: "ValidatorWeightUpdate", logs: logs, sub: sub}, nil +} + +// WatchValidatorWeightUpdate is a free log subscription operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) WatchValidatorWeightUpdate(opts *bind.WatchOpts, sink chan<- *PoAValidatorManagerValidatorWeightUpdate, validationID [][32]byte, nonce []uint64) (event.Subscription, error) { + + var validationIDRule []interface{} + for _, validationIDItem := range validationID { + validationIDRule = append(validationIDRule, validationIDItem) + } + var nonceRule []interface{} + for _, nonceItem := range nonce { + nonceRule = append(nonceRule, nonceItem) + } + + logs, sub, err := _PoAValidatorManager.contract.WatchLogs(opts, "ValidatorWeightUpdate", validationIDRule, nonceRule) + 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(PoAValidatorManagerValidatorWeightUpdate) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidatorWeightUpdate", 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 +} + +// ParseValidatorWeightUpdate is a log parse operation binding the contract event 0x07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df. +// +// Solidity: event ValidatorWeightUpdate(bytes32 indexed validationID, uint64 indexed nonce, uint64 validatorWeight, bytes32 setWeightMessageID) +func (_PoAValidatorManager *PoAValidatorManagerFilterer) ParseValidatorWeightUpdate(log types.Log) (*PoAValidatorManagerValidatorWeightUpdate, error) { + event := new(PoAValidatorManagerValidatorWeightUpdate) + if err := _PoAValidatorManager.contract.UnpackLog(event, "ValidatorWeightUpdate", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/contracts/mocks/ExampleERC20.sol b/contracts/mocks/ExampleERC20.sol index db4d6cb92..d7d348702 100644 --- a/contracts/mocks/ExampleERC20.sol +++ b/contracts/mocks/ExampleERC20.sol @@ -13,12 +13,13 @@ import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts@5.0.2/token/ERC20/extensions/ERC20Burnable.sol"; +import {IERC20Mintable} from "../validator-manager/interfaces/IERC20Mintable.sol"; -contract ExampleERC20 is ERC20Burnable { +contract ExampleERC20 is ERC20Burnable, IERC20Mintable { string private constant _TOKEN_NAME = "Mock Token"; string private constant _TOKEN_SYMBOL = "EXMP"; - uint256 private constant _MAX_MINT = 1e16; + uint256 private constant _MAX_MINT = 1e19; constructor() ERC20(_TOKEN_NAME, _TOKEN_SYMBOL) { _mint(msg.sender, 1e28); @@ -30,4 +31,11 @@ contract ExampleERC20 is ERC20Burnable { _mint(msg.sender, amount); } + + function mint(address account, uint256 amount) external { + // Can only mint 10 at a time. + require(amount <= _MAX_MINT, "ExampleERC20: max mint exceeded"); + + _mint(account, amount); + } } diff --git a/contracts/teleporter/README.md b/contracts/teleporter/README.md index b0f38a3c3..c5ca8c236 100644 --- a/contracts/teleporter/README.md +++ b/contracts/teleporter/README.md @@ -69,7 +69,7 @@ Once sent on chain, Warp messages cannot be re-signed by a new validator set in **Do not deploy the `TeleporterMessenger` contract using `forge create`**. The `TeleporterMessenger` contract must be deployed to the same contract address on every chain. To achieve this, the contract can be deployed using a static transaction that uses Nick's method as documented in [this guide](../..//utils/contract-deployment/README.md). Alternatively, if creating a new Subnet, the contract can be pre-allocated with the proper address and state in the new chain's [genesis file](https://docs.avax.network/build/subnet/upgrade/customize-a-subnet#setting-the-genesis-allocation). -As an example, to include `TeleporterMessenger` `v1.0.0` in the genesis file, include the following values in the `alloc` settings, as documented at the link above. The `storage` values included below correspond to the two contract values that are initialized as part of the default constructor of `TeleporterMessenger`. These are the `ReentrancyGuard` values set in this [abstract contract](../utilities/ReentrancyGuards.sol). Future versions of `TeleporterMessenger` may require different storage value intializations. +As an example, to include `TeleporterMessenger` `v1.0.0` in the genesis file, include the following values in the `alloc` settings, as documented at the link above. The `storage` values included below correspond to the two contract values that are initialized as part of the default constructor of `TeleporterMessenger`. These are the `ReentrancyGuard` values set in this [abstract contract](../utilities/ReentrancyGuards.sol). Future versions of `TeleporterMessenger` may require different storage value initializations. ```json "alloc": { "0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf": { diff --git a/contracts/utilities/ICMInitializable.sol b/contracts/utilities/ICMInitializable.sol new file mode 100644 index 000000000..9e9c1ae88 --- /dev/null +++ b/contracts/utilities/ICMInitializable.sol @@ -0,0 +1,10 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem +pragma solidity 0.8.25; + +enum ICMInitializable { + Allowed, + Disallowed +} diff --git a/contracts/validator-manager/ERC20TokenStakingManager.sol b/contracts/validator-manager/ERC20TokenStakingManager.sol new file mode 100644 index 000000000..64e7fff2a --- /dev/null +++ b/contracts/validator-manager/ERC20TokenStakingManager.sol @@ -0,0 +1,145 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {PoSValidatorManager} from "./PoSValidatorManager.sol"; +import {PoSValidatorManagerSettings} from "./interfaces/IPoSValidatorManager.sol"; +import {ValidatorRegistrationInput} from "./interfaces/IValidatorManager.sol"; +import {IERC20TokenStakingManager} from "./interfaces/IERC20TokenStakingManager.sol"; +import {IERC20Mintable} from "./interfaces/IERC20Mintable.sol"; +import {ICMInitializable} from "@utilities/ICMInitializable.sol"; +import {SafeERC20TransferFrom} from "@utilities/SafeERC20TransferFrom.sol"; +import {Initializable} from + "@openzeppelin/contracts-upgradeable@5.0.2/proxy/utils/Initializable.sol"; +import {SafeERC20} from "@openzeppelin/contracts@5.0.2/token/ERC20/utils/SafeERC20.sol"; + +/** + * @dev Implementation of the {IERC20TokenStakingManager} interface. + * + * @custom:security-contact https://github.com/ava-labs/teleporter/blob/main/SECURITY.md + */ +contract ERC20TokenStakingManager is + Initializable, + PoSValidatorManager, + IERC20TokenStakingManager +{ + using SafeERC20 for IERC20Mintable; + using SafeERC20TransferFrom for IERC20Mintable; + + // solhint-disable private-vars-leading-underscore + /// @custom:storage-location erc7201:avalanche-icm.storage.ERC20TokenStakingManager + struct ERC20TokenStakingManagerStorage { + IERC20Mintable _token; + uint8 _tokenDecimals; + } + // solhint-enable private-vars-leading-underscore + + // keccak256(abi.encode(uint256(keccak256("avalanche-icm.storage.ERC20TokenStakingManager")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 public constant ERC20_STAKING_MANAGER_STORAGE_LOCATION = + 0x6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab00; + + error InvalidTokenAddress(address tokenAddress); + + // solhint-disable ordering + function _getERC20StakingManagerStorage() + private + pure + returns (ERC20TokenStakingManagerStorage storage $) + { + // solhint-disable-next-line no-inline-assembly + assembly { + $.slot := ERC20_STAKING_MANAGER_STORAGE_LOCATION + } + } + + constructor(ICMInitializable init) { + if (init == ICMInitializable.Disallowed) { + _disableInitializers(); + } + } + + /** + * @notice Initialize the ERC20 token staking manager + * @dev Uses reinitializer(2) on the PoS staking contracts to make sure after migration from PoA, the PoS contracts can reinitialize with its needed values. + * @param settings Initial settings for the PoS validator manager + * @param token The ERC20 token to be staked + */ + function initialize( + PoSValidatorManagerSettings calldata settings, + IERC20Mintable token + ) external reinitializer(2) { + __ERC20TokenStakingManager_init(settings, token); + } + + // solhint-disable-next-line func-name-mixedcase + function __ERC20TokenStakingManager_init( + PoSValidatorManagerSettings calldata settings, + IERC20Mintable token + ) internal onlyInitializing { + __POS_Validator_Manager_init(settings); + __ERC20TokenStakingManager_init_unchained(token); + } + + // solhint-disable-next-line func-name-mixedcase + function __ERC20TokenStakingManager_init_unchained(IERC20Mintable token) + internal + onlyInitializing + { + ERC20TokenStakingManagerStorage storage $ = _getERC20StakingManagerStorage(); + if (address(token) == address(0)) { + revert InvalidTokenAddress(address(token)); + } + $._token = token; + } + + /** + * @notice See {IERC20TokenStakingManager-initializeValidatorRegistration} + */ + function initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration, + uint256 stakeAmount + ) external nonReentrant returns (bytes32 validationID) { + return _initializeValidatorRegistration( + registrationInput, delegationFeeBips, minStakeDuration, stakeAmount + ); + } + + /** + * @notice See {IERC20TokenStakingManager-initializeDelegatorRegistration} + */ + function initializeDelegatorRegistration( + bytes32 validationID, + uint256 delegationAmount + ) external nonReentrant returns (bytes32) { + return _initializeDelegatorRegistration(validationID, _msgSender(), delegationAmount); + } + + /** + * @notice See {PoSValidatorManager-_lock} + * Note: Must be guarded with reentrancy guard for safe transfer from. + */ + function _lock(uint256 value) internal virtual override returns (uint256) { + return _getERC20StakingManagerStorage()._token.safeTransferFrom(value); + } + + /** + * @notice See {PoSValidatorManager-_unlock} + * Note: Must be guarded with reentrancy guard for safe transfer. + */ + function _unlock(address to, uint256 value) internal virtual override { + _getERC20StakingManagerStorage()._token.safeTransfer(to, value); + } + + /** + * @notice See {PoSValidatorManager-_reward} + */ + function _reward(address account, uint256 amount) internal virtual override { + ERC20TokenStakingManagerStorage storage $ = _getERC20StakingManagerStorage(); + $._token.mint(account, amount); + } +} diff --git a/contracts/validator-manager/ExampleRewardCalculator.sol b/contracts/validator-manager/ExampleRewardCalculator.sol new file mode 100644 index 000000000..856158350 --- /dev/null +++ b/contracts/validator-manager/ExampleRewardCalculator.sol @@ -0,0 +1,46 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {IRewardCalculator} from "./interfaces/IRewardCalculator.sol"; + +contract ExampleRewardCalculator is IRewardCalculator { + uint256 public constant SECONDS_IN_YEAR = 31536000; + + uint8 public constant UPTIME_REWARDS_THRESHOLD_PERCENTAGE = 80; + + uint16 public constant BIPS_CONVERSION_FACTOR = 10000; + + uint64 public immutable rewardBasisPoints; + + constructor(uint64 rewardBasisPoints_) { + rewardBasisPoints = rewardBasisPoints_; + } + + /** + * @notice A linear, non-compounding reward calculation that rewards a set percentage of tokens per year. + * See {IRewardCalculator-calculateReward} + */ + function calculateReward( + uint256 stakeAmount, + uint64 validatorStartTime, + uint64 stakingStartTime, + uint64 stakingEndTime, + uint64 uptimeSeconds + ) external view returns (uint256) { + // Equivalent to uptimeSeconds/(validator.endedAt - validator.startedAt) < UPTIME_REWARDS_THRESHOLD_PERCENTAGE/100 + // Rearranged to prevent integer division truncation. + if ( + uptimeSeconds * 100 + < (stakingEndTime - validatorStartTime) * UPTIME_REWARDS_THRESHOLD_PERCENTAGE + ) { + return 0; + } + + return (stakeAmount * rewardBasisPoints * (stakingEndTime - stakingStartTime)) + / SECONDS_IN_YEAR / BIPS_CONVERSION_FACTOR; + } +} diff --git a/contracts/validator-manager/MessageSpec.md b/contracts/validator-manager/MessageSpec.md new file mode 100644 index 000000000..f4b44d2ed --- /dev/null +++ b/contracts/validator-manager/MessageSpec.md @@ -0,0 +1,185 @@ +## Warp Message Format Reference + +### `SubnetConversionMessage` + +- Description: Confirms conversion to a Permissionless Subnet on the P-Chain + +- Signed by: P-Chain + +- Consumed by: Validator Manager contract + +Specification: + +``` +SubnetConversionMessage ++--------------------+----------+----------+ +| codecID : uint16 | 2 bytes | ++--------------------+----------+----------+ +| typeID : uint32 | 4 bytes | ++--------------------+----------+----------+ +| subnetConversionID : [32]byte | 32 bytes | ++--------------------+----------+----------+ + | 38 bytes | + +----------+ +``` + +where `subnetConversionID` is defined as the `sha256` hash of the serialization of the `SubnetConversionData`, defined as follows: + +``` +ValidatorData ++--------------+----------+------------------------+ +| nodeID : []byte | 4 + len(nodeID) bytes | ++--------------+----------+------------------------+ +| blsPublicKey : [48]byte | 48 bytes | ++--------------+----------+------------------------+ +| weight : uint64 | 8 bytes | ++--------------+----------+------------------------+ + | 60 + len(nodeID) bytes | + +------------------------+ + +SubnetConversionData ++----------------+-----------------+--------------------------------------------------------+ +| codecID : uint16 | 2 bytes | ++----------------+-----------------+--------------------------------------------------------+ +| subnetID : [32]byte | 32 bytes | ++----------------+-----------------+--------------------------------------------------------+ +| managerChainID : [32]byte | 32 bytes | ++----------------+-----------------+--------------------------------------------------------+ +| managerAddress : []byte | 4 + len(managerAddress) bytes | ++----------------+-----------------+--------------------------------------------------------+ +| validators : []ValidatorData | 4 + sum(validatorLengths) bytes | ++----------------+-----------------+--------------------------------------------------------+ + | 74 + len(managerAddress) + len(validatorLengths) bytes | + +--------------------------------------------------------+ +``` + +### `RegisterSubnetValidatorMessage` + +- Description: Registers a Subnet Validator on the P-Chain + +- Signed by: Subnet + +- Consumed by: P-Chain + +Specification: + +``` +PChainOwner ++-----------+------------+-------------------------------+ +| threshold : uint32 | 4 bytes | ++-----------+------------+-------------------------------+ +| addresses : [][20]byte | 4 + len(addresses) * 20 bytes | ++-----------+------------+-------------------------------+ + | 8 + len(addresses) * 20 bytes | + +-------------------------------+ + +RegisterSubnetValidatorMessage ++-----------------------+-------------+--------------------------------------------------------------------+ +| codecID : uint16 | 2 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| typeID : uint32 | 4 bytes | ++-----------------------+-------------+-------------------------------------------------------------------+ +| subnetID : [32]byte | 32 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| nodeID : []byte | 4 + len(nodeID) bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| blsPublicKey : [48]byte | 48 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| expiry : uint64 | 8 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| remainingBalanceOwner : PChainOwner | 4 + len(addresses) * 20 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| disableOwner : PChainOwner | 4 + len(addresses) * 20 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ +| weight : uint64 | 8 bytes | ++-----------------------+-------------+--------------------------------------------------------------------+ + | 114 + len(nodeID) + (len(addresses1) + len(addresses2)) * 20 bytes | + +--------------------------------------------------------------------+ + +``` + +### `SubnetValidatorRegistrationMessage` + +- Description: Confirms a Subnet Validator's registration validity on the P-Chain + +- Signed by: P-Chain + +- Consumed by: Validator Manager contract + +Specification: + +``` +SubnetValidatorRegistrationMessage ++--------------+----------+----------+ +| codecID : uint16 | 2 bytes | ++--------------+----------+----------+ +| typeID : uint32 | 4 bytes | ++--------------+----------+----------+ +| validationID : [32]byte | 32 bytes | ++--------------+----------+----------+ +| valid : bool | 1 byte | ++--------------+----------+----------+ + | 39 bytes | + +----------+ +``` + +### `SubnetValidatorWeightMessage` + +- Description: Used to set and acknowledge a Validator's stake weight on another chain + +- To effect a weight change: + + - Signed by: Subnet + + - Consumed by: P-Chain + +- To acknowledge the weight change: + + - Signed by P-Chain + + + - Consumed by Subnet + +Specification: + +``` +SubnetValidatorWeightMessage ++--------------+----------+----------+ +| codecID : uint16 | 2 bytes | ++--------------+----------+----------+ +| typeID : uint32 | 4 bytes | ++--------------+----------+----------+ +| validationID : [32]byte | 32 bytes | ++--------------+----------+----------+ +| nonce : uint64 | 8 bytes | ++--------------+----------+----------+ +| weight : uint64 | 8 bytes | ++--------------+----------+----------+ + | 54 bytes | + +----------+ +``` + +### `ValidationUptimeMessage` + +- Description: Provides a Validator's uptime for calculating staking rewards + +- Signed by: Subnet + +- Consumed by: Validator Manager contract + +Specification: + +``` +ValidationUptimeMessage ++--------------+----------+----------+ +| codecID : uint16 | 2 bytes | ++--------------+----------+----------+ +| typeID : uint32 | 4 bytes | ++--------------+----------+----------+ +| validationID : [32]byte | 32 bytes | ++--------------+----------+----------+ +| uptime : uint64 | 8 bytes | ++--------------+----------+----------+ + | 46 bytes | + +----------+ +``` \ No newline at end of file diff --git a/contracts/validator-manager/NativeTokenStakingManager.sol b/contracts/validator-manager/NativeTokenStakingManager.sol new file mode 100644 index 000000000..b641a94b5 --- /dev/null +++ b/contracts/validator-manager/NativeTokenStakingManager.sol @@ -0,0 +1,106 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {PoSValidatorManager} from "./PoSValidatorManager.sol"; +import {PoSValidatorManagerSettings} from "./interfaces/IPoSValidatorManager.sol"; +import {ValidatorRegistrationInput} from "./interfaces/IValidatorManager.sol"; +import {INativeTokenStakingManager} from "./interfaces/INativeTokenStakingManager.sol"; +import {INativeMinter} from + "@avalabs/subnet-evm-contracts@1.2.0/contracts/interfaces/INativeMinter.sol"; +import {ICMInitializable} from "@utilities/ICMInitializable.sol"; +import {Address} from "@openzeppelin/contracts@5.0.2/utils/Address.sol"; +import {Initializable} from + "@openzeppelin/contracts-upgradeable@5.0.2/proxy/utils/Initializable.sol"; + +/** + * @dev Implementation of the {INativeTokenStakingManager} interface. + * + * @custom:security-contact https://github.com/ava-labs/teleporter/blob/main/SECURITY.md + */ +contract NativeTokenStakingManager is + Initializable, + PoSValidatorManager, + INativeTokenStakingManager +{ + using Address for address payable; + + INativeMinter public constant NATIVE_MINTER = + INativeMinter(0x0200000000000000000000000000000000000001); + + constructor(ICMInitializable init) { + if (init == ICMInitializable.Disallowed) { + _disableInitializers(); + } + } + + /** + * @notice Initialize the native token staking manager + * @dev Uses reinitializer(2) on the PoS staking contracts to make sure after migration from PoA, the PoS contracts can reinitialize with its needed values. + * @param settings Initial settings for the PoS validator manager + */ + // solhint-disable ordering + function initialize(PoSValidatorManagerSettings calldata settings) external reinitializer(2) { + __NativeTokenStakingManager_init(settings); + } + + // solhint-disable-next-line func-name-mixedcase + function __NativeTokenStakingManager_init(PoSValidatorManagerSettings calldata settings) + internal + onlyInitializing + { + __POS_Validator_Manager_init(settings); + } + + // solhint-disable-next-line func-name-mixedcase, no-empty-blocks + function __NativeTokenStakingManager_init_unchained() internal onlyInitializing {} + + /** + * @notice See {INativeTokenStakingManager-initializeValidatorRegistration}. + */ + function initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration + ) external payable nonReentrant returns (bytes32) { + return _initializeValidatorRegistration( + registrationInput, delegationFeeBips, minStakeDuration, msg.value + ); + } + + /** + * @notice See {INativeTokenStakingManager-initializeDelegatorRegistration}. + */ + function initializeDelegatorRegistration(bytes32 validationID) + external + payable + nonReentrant + returns (bytes32) + { + return _initializeDelegatorRegistration(validationID, _msgSender(), msg.value); + } + + /** + * @notice See {PoSValidatorManager-_lock} + */ + function _lock(uint256 value) internal virtual override returns (uint256) { + return value; + } + + /** + * @notice See {PoSValidatorManager-_unlock} + */ + function _unlock(address to, uint256 value) internal virtual override { + payable(to).sendValue(value); + } + + /** + * @notice See {PoSValidatorManager-_reward} + */ + function _reward(address account, uint256 amount) internal virtual override { + NATIVE_MINTER.mintNativeCoin(account, amount); + } +} diff --git a/contracts/validator-manager/PoAValidatorManager.sol b/contracts/validator-manager/PoAValidatorManager.sol new file mode 100644 index 000000000..ad38db6eb --- /dev/null +++ b/contracts/validator-manager/PoAValidatorManager.sol @@ -0,0 +1,75 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {ValidatorManager} from "./ValidatorManager.sol"; +import { + ValidatorManagerSettings, + ValidatorRegistrationInput +} from "./interfaces/IValidatorManager.sol"; +import {IPoAValidatorManager} from "./interfaces/IPoAValidatorManager.sol"; +import {ICMInitializable} from "@utilities/ICMInitializable.sol"; +import {OwnableUpgradeable} from + "@openzeppelin/contracts-upgradeable@5.0.2/access/OwnableUpgradeable.sol"; + +/** + * @dev Implementation of the {IPoAValidatorManager} interface. + * + * @custom:security-contact https://github.com/ava-labs/teleporter/blob/main/SECURITY.md + */ +contract PoAValidatorManager is IPoAValidatorManager, ValidatorManager, OwnableUpgradeable { + constructor(ICMInitializable init) { + if (init == ICMInitializable.Disallowed) { + _disableInitializers(); + } + } + + function initialize( + ValidatorManagerSettings calldata settings, + address initialOwner + ) external initializer { + __PoAValidatorManager_init(settings, initialOwner); + } + + // solhint-disable func-name-mixedcase, ordering + function __PoAValidatorManager_init( + ValidatorManagerSettings calldata settings, + address initialOwner + ) internal onlyInitializing { + __ValidatorManager_init(settings); + __Ownable_init(initialOwner); + } + + // solhint-disable-next-line no-empty-blocks + function __PoAValidatorManager_init_unchained() internal onlyInitializing {} + + // solhint-enable func-name-mixedcase + + /** + * @notice See {IPoAValidatorManager-initializeValidatorRegistration}. + */ + function initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint64 weight + ) external onlyOwner returns (bytes32 validationID) { + return _initializeValidatorRegistration(registrationInput, weight); + } + + // solhint-enable ordering + /** + * @notice See {IPoAValidatorManager-initializeEndValidation}. + */ + function initializeEndValidation(bytes32 validationID) external override onlyOwner { + _initializeEndValidation(validationID); + } + + /** + * @notice See {IValidatorManager-completeEndValidation}. + */ + function completeEndValidation(uint32 messageIndex) external { + _completeEndValidation(messageIndex); + } +} diff --git a/contracts/validator-manager/PoSValidatorManager.sol b/contracts/validator-manager/PoSValidatorManager.sol new file mode 100644 index 000000000..eacff333a --- /dev/null +++ b/contracts/validator-manager/PoSValidatorManager.sol @@ -0,0 +1,767 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {ValidatorManager} from "./ValidatorManager.sol"; +import {ValidatorMessages} from "./ValidatorMessages.sol"; +import { + Delegator, + DelegatorStatus, + IPoSValidatorManager, + PoSValidatorInfo, + PoSValidatorManagerSettings +} from "./interfaces/IPoSValidatorManager.sol"; +import { + Validator, + ValidatorRegistrationInput, + ValidatorStatus +} from "./interfaces/IValidatorManager.sol"; +import {IRewardCalculator} from "./interfaces/IRewardCalculator.sol"; +import {WarpMessage} from + "@avalabs/subnet-evm-contracts@1.2.0/contracts/interfaces/IWarpMessenger.sol"; +import {ReentrancyGuardUpgradeable} from + "@openzeppelin/contracts-upgradeable@5.0.2/utils/ReentrancyGuardUpgradeable.sol"; + +/** + * @dev Implementation of the {IPoSValidatorManager} interface. + * + * @custom:security-contact https://github.com/ava-labs/teleporter/blob/main/SECURITY.md + */ +abstract contract PoSValidatorManager is + IPoSValidatorManager, + ValidatorManager, + ReentrancyGuardUpgradeable +{ + // solhint-disable private-vars-leading-underscore + /// @custom:storage-location erc7201:avalanche-icm.storage.PoSValidatorManager + struct PoSValidatorManagerStorage { + /// @notice The minimum amount of stake required to be a validator. + uint256 _minimumStakeAmount; + /// @notice The maximum amount of stake allowed to be a validator. + uint256 _maximumStakeAmount; + /// @notice The minimum amount of time in seconds a validator must be staked for. Must be at least {_churnPeriodSeconds}. + uint64 _minimumStakeDuration; + /// @notice The minimum delegation fee percentage, in basis points, required to delegate to a validator. + uint16 _minimumDelegationFeeBips; + /** + * @notice A multiplier applied to validator's initial stake amount to determine + * the maximum amount of stake a validator can have with delegations. + * Note: Setting this value to 1 would disable delegations to validators, since + * the maximum stake would be equal to the initial stake. + */ + uint64 _maximumStakeMultiplier; + /// @notice The factor used to convert between weight and value. + uint256 _weightToValueFactor; + /// @notice The reward calculator for this validator manager. + IRewardCalculator _rewardCalculator; + /// @notice Maps the validation ID to its requirements. + mapping(bytes32 validationID => PoSValidatorInfo) _posValidatorInfo; + /// @notice Maps the delegation ID to the delegator information. + mapping(bytes32 delegationID => Delegator) _delegatorStakes; + /// @notice Maps the delegation ID to its pending staking rewards. + mapping(bytes32 delegationID => uint256) _redeemableDelegatorRewards; + /// @notice Maps the validation ID to its pending staking rewards. + mapping(bytes32 validationID => uint256) _redeemableValidatorRewards; + } + // solhint-enable private-vars-leading-underscore + + // keccak256(abi.encode(uint256(keccak256("avalanche-icm.storage.PoSValidatorManager")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 public constant POS_VALIDATOR_MANAGER_STORAGE_LOCATION = + 0x4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d00; + + uint8 public constant MAXIMUM_STAKE_MULTIPLIER_LIMIT = 10; + + uint16 public constant MAXIMUM_DELEGATION_FEE_BIPS = 10000; + + uint16 public constant BIPS_CONVERSION_FACTOR = 10000; + + error InvalidDelegationFee(uint16 delegationFeeBips); + error InvalidDelegationID(bytes32 delegationID); + error InvalidDelegatorStatus(DelegatorStatus status); + error InvalidNonce(uint64 nonce); + error InvalidStakeAmount(uint256 stakeAmount); + error InvalidMinStakeDuration(uint64 minStakeDuration); + error InvalidStakeMultiplier(uint8 maximumStakeMultiplier); + error MaxWeightExceeded(uint64 newValidatorWeight); + error MinStakeDurationNotPassed(uint64 endTime); + error UnauthorizedOwner(address sender); + error ValidatorNotPoS(bytes32 validationID); + error ValidatorIneligibleForRewards(bytes32 validationID); + error DelegatorIneligibleForRewards(bytes32 delegationID); + error ZeroWeightToValueFactor(); + + // solhint-disable ordering + function _getPoSValidatorManagerStorage() + private + pure + returns (PoSValidatorManagerStorage storage $) + { + // solhint-disable-next-line no-inline-assembly + assembly { + $.slot := POS_VALIDATOR_MANAGER_STORAGE_LOCATION + } + } + + // solhint-disable-next-line func-name-mixedcase + function __POS_Validator_Manager_init(PoSValidatorManagerSettings calldata settings) + internal + onlyInitializing + { + __ValidatorManager_init(settings.baseSettings); + __ReentrancyGuard_init(); + __POS_Validator_Manager_init_unchained({ + minimumStakeAmount: settings.minimumStakeAmount, + maximumStakeAmount: settings.maximumStakeAmount, + minimumStakeDuration: settings.minimumStakeDuration, + minimumDelegationFeeBips: settings.minimumDelegationFeeBips, + maximumStakeMultiplier: settings.maximumStakeMultiplier, + weightToValueFactor: settings.weightToValueFactor, + rewardCalculator: settings.rewardCalculator + }); + } + + // solhint-disable-next-line func-name-mixedcase + function __POS_Validator_Manager_init_unchained( + uint256 minimumStakeAmount, + uint256 maximumStakeAmount, + uint64 minimumStakeDuration, + uint16 minimumDelegationFeeBips, + uint8 maximumStakeMultiplier, + uint256 weightToValueFactor, + IRewardCalculator rewardCalculator + ) internal onlyInitializing { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + if (minimumDelegationFeeBips == 0 || minimumDelegationFeeBips > MAXIMUM_DELEGATION_FEE_BIPS) + { + revert InvalidDelegationFee(minimumDelegationFeeBips); + } + if (minimumStakeAmount > maximumStakeAmount) { + revert InvalidStakeAmount(minimumStakeAmount); + } + if (maximumStakeMultiplier == 0 || maximumStakeMultiplier > MAXIMUM_STAKE_MULTIPLIER_LIMIT) + { + revert InvalidStakeMultiplier(maximumStakeMultiplier); + } + // Minimum stake duration should be at least one churn period in order to prevent churn tracker abuse. + if (minimumStakeDuration < _getChurnPeriodSeconds()) { + revert InvalidMinStakeDuration(minimumStakeDuration); + } + if (weightToValueFactor == 0) { + revert ZeroWeightToValueFactor(); + } + + $._minimumStakeAmount = minimumStakeAmount; + $._maximumStakeAmount = maximumStakeAmount; + $._minimumStakeDuration = minimumStakeDuration; + $._minimumDelegationFeeBips = minimumDelegationFeeBips; + $._maximumStakeMultiplier = maximumStakeMultiplier; + $._weightToValueFactor = weightToValueFactor; + $._rewardCalculator = rewardCalculator; + } + + /** + * @notice See {IPoSValidatorManager-submitUptimeProof}. + */ + function submitUptimeProof(bytes32 validationID, uint32 messageIndex) external { + if (!_isPoSValidator(validationID)) { + revert ValidatorNotPoS(validationID); + } + ValidatorStatus status = getValidator(validationID).status; + if (status != ValidatorStatus.Active) { + revert InvalidValidatorStatus(status); + } + + // Uptime proofs include the absolute number of seconds the validator has been active. + _updateUptime(validationID, messageIndex); + } + + /** + * @notice See {IPoSValidatorManager-claimDelegationFees}. + */ + function claimDelegationFees(bytes32 validationID) external { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + ValidatorStatus status = getValidator(validationID).status; + if (status != ValidatorStatus.Completed) { + revert InvalidValidatorStatus(status); + } + + if ($._posValidatorInfo[validationID].owner != _msgSender()) { + revert UnauthorizedOwner(_msgSender()); + } + + uint256 rewards = $._redeemableValidatorRewards[validationID]; + delete $._redeemableValidatorRewards[validationID]; + _reward($._posValidatorInfo[validationID].owner, rewards); + } + + /** + * @notice See {IPoSValidatorManager-initializeEndValidation}. + */ + function initializeEndValidation( + bytes32 validationID, + bool includeUptimeProof, + uint32 messageIndex + ) external { + if (!_initializeEndPoSValidation(validationID, includeUptimeProof, messageIndex)) { + revert ValidatorIneligibleForRewards(validationID); + } + } + + /** + * @notice See {IPoSValidatorManager-forceInitializeEndValidation}. + */ + function forceInitializeEndValidation( + bytes32 validationID, + bool includeUptimeProof, + uint32 messageIndex + ) external { + // Ignore the return value here to force end validation, regardless of possible missed rewards + _initializeEndPoSValidation(validationID, includeUptimeProof, messageIndex); + } + + /** + * @dev Helper function that initializes the end of a PoS validation period. + * Returns false if it is possible for the validator to claim rewards, but it is not eligible. + * Returns true otherwise. + */ + function _initializeEndPoSValidation( + bytes32 validationID, + bool includeUptimeProof, + uint32 messageIndex + ) internal returns (bool) { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + Validator memory validator = _initializeEndValidation(validationID); + + // Non-PoS validators are required to boostrap the network, but are not eligible for rewards. + if (!_isPoSValidator(validationID)) { + return true; + } + + // PoS validations can only be ended by their owners. + if ($._posValidatorInfo[validationID].owner != _msgSender()) { + revert UnauthorizedOwner(_msgSender()); + } + + // Check that minimum stake duration has passed. + if ( + validator.endedAt + < validator.startedAt + $._posValidatorInfo[validationID].minStakeDuration + ) { + revert MinStakeDurationNotPassed(validator.endedAt); + } + + // Uptime proofs include the absolute number of seconds the validator has been active. + uint64 uptimeSeconds; + if (includeUptimeProof) { + uptimeSeconds = _updateUptime(validationID, messageIndex); + } else { + uptimeSeconds = $._posValidatorInfo[validationID].uptimeSeconds; + } + + uint256 reward = $._rewardCalculator.calculateReward({ + stakeAmount: weightToValue(validator.startingWeight), + validatorStartTime: validator.startedAt, + stakingStartTime: validator.startedAt, + stakingEndTime: validator.endedAt, + uptimeSeconds: uptimeSeconds + }); + $._redeemableValidatorRewards[validationID] += reward; + return (reward > 0); + } + + /** + * @notice See {IValidatorManager-completeEndValidation}. + */ + function completeEndValidation(uint32 messageIndex) external nonReentrant { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + (bytes32 validationID, Validator memory validator) = _completeEndValidation(messageIndex); + + // Return now if this was originally a PoA validator that was later migrated to this PoS manager, + // or the validator was part of the initial validator set. + if (!_isPoSValidator(validationID)) { + return; + } + + address owner = $._posValidatorInfo[validationID].owner; + // The validator can either be Completed or Invalidated here. We only grant rewards for Completed. + if (validator.status == ValidatorStatus.Completed) { + uint256 rewards = $._redeemableValidatorRewards[validationID]; + delete $._redeemableValidatorRewards[validationID]; + _reward(owner, rewards); + } + + // The stake is unlocked whether the validation period is completed or invalidated. + _unlock(owner, weightToValue(validator.startingWeight)); + } + + /** + * @dev Helper function that extracts the uptime from a ValidationUptimeMessage Warp message + * If the uptime is greater than the stored uptime, update the stored uptime. + */ + function _updateUptime(bytes32 validationID, uint32 messageIndex) internal returns (uint64) { + (WarpMessage memory warpMessage, bool valid) = + WARP_MESSENGER.getVerifiedWarpMessage(messageIndex); + if (!valid) { + revert InvalidWarpMessage(); + } + + if (warpMessage.sourceChainID != WARP_MESSENGER.getBlockchainID()) { + revert InvalidWarpSourceChainID(warpMessage.sourceChainID); + } + if (warpMessage.originSenderAddress != address(0)) { + revert InvalidWarpOriginSenderAddress(warpMessage.originSenderAddress); + } + + (bytes32 uptimeValidationID, uint64 uptime) = + ValidatorMessages.unpackValidationUptimeMessage(warpMessage.payload); + if (validationID != uptimeValidationID) { + revert InvalidValidationID(validationID); + } + + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + if (uptime > $._posValidatorInfo[validationID].uptimeSeconds) { + $._posValidatorInfo[validationID].uptimeSeconds = uptime; + emit UptimeUpdated(validationID, uptime); + } else { + uptime = $._posValidatorInfo[validationID].uptimeSeconds; + } + + return uptime; + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration, + uint256 stakeAmount + ) internal virtual returns (bytes32) { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + // Validate and save the validator requirements + if ( + delegationFeeBips < $._minimumDelegationFeeBips + || delegationFeeBips > MAXIMUM_DELEGATION_FEE_BIPS + ) { + revert InvalidDelegationFee(delegationFeeBips); + } + + if (minStakeDuration < $._minimumStakeDuration) { + revert InvalidMinStakeDuration(minStakeDuration); + } + + // Ensure the weight is within the valid range. + if (stakeAmount < $._minimumStakeAmount || stakeAmount > $._maximumStakeAmount) { + revert InvalidStakeAmount(stakeAmount); + } + + // Lock the stake in the contract. + uint256 lockedValue = _lock(stakeAmount); + + uint64 weight = valueToWeight(lockedValue); + bytes32 validationID = _initializeValidatorRegistration(registrationInput, weight); + + $._posValidatorInfo[validationID] = PoSValidatorInfo({ + owner: _msgSender(), + delegationFeeBips: delegationFeeBips, + minStakeDuration: minStakeDuration, + uptimeSeconds: 0 + }); + return validationID; + } + + /** + * @notice Converts a token value to a weight. + * @param value Token value to convert. + */ + function valueToWeight(uint256 value) public view returns (uint64) { + uint256 weight = value / _getPoSValidatorManagerStorage()._weightToValueFactor; + if (weight == 0 || weight > type(uint64).max) { + revert InvalidStakeAmount(value); + } + return uint64(weight); + } + + /** + * @notice Converts a weight to a token value. + * @param weight weight to convert. + */ + function weightToValue(uint64 weight) public view returns (uint256) { + return uint256(weight) * _getPoSValidatorManagerStorage()._weightToValueFactor; + } + + /** + * @notice Locks tokens in this contract. + * @param value Number of tokens to lock. + */ + function _lock(uint256 value) internal virtual returns (uint256); + + /** + * @notice Unlocks token to a specific address. + * @param to Address to send token to. + * @param value Number of tokens to lock. + */ + function _unlock(address to, uint256 value) internal virtual; + + function _initializeDelegatorRegistration( + bytes32 validationID, + address delegatorAddress, + uint256 delegationAmount + ) internal returns (bytes32) { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + uint64 weight = valueToWeight(_lock(delegationAmount)); + + // Ensure the validation period is active + Validator memory validator = getValidator(validationID); + // Check that the validation ID is a PoS validator + if (!_isPoSValidator(validationID)) { + revert ValidatorNotPoS(validationID); + } + if (validator.status != ValidatorStatus.Active) { + revert InvalidValidatorStatus(validator.status); + } + + // Update the validator weight + uint64 newValidatorWeight = validator.weight + weight; + if (newValidatorWeight > validator.startingWeight * $._maximumStakeMultiplier) { + revert MaxWeightExceeded(newValidatorWeight); + } + + (uint64 nonce, bytes32 messageID) = _setValidatorWeight(validationID, newValidatorWeight); + + bytes32 delegationID = keccak256(abi.encodePacked(validationID, nonce)); + + // Store the delegation information. Set the delegator status to pending added, + // so that it can be properly started in the complete step, even if the delivered + // nonce is greater than the nonce used to initialize registration. + $._delegatorStakes[delegationID] = Delegator({ + status: DelegatorStatus.PendingAdded, + owner: delegatorAddress, + validationID: validationID, + weight: weight, + startedAt: 0, + startingNonce: nonce, + endingNonce: 0 + }); + + emit DelegatorAdded({ + delegationID: delegationID, + validationID: validationID, + delegatorAddress: delegatorAddress, + nonce: nonce, + validatorWeight: newValidatorWeight, + delegatorWeight: weight, + setWeightMessageID: messageID + }); + return delegationID; + } + + /** + * @notice See {IPoSValidatorManager-completeDelegatorRegistration}. + */ + function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) external { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + Delegator memory delegator = $._delegatorStakes[delegationID]; + bytes32 validationID = delegator.validationID; + Validator memory validator = getValidator(validationID); + + // Ensure the delegator is pending added. Since anybody can call this function once + // delegator registration has been initialized, we need to make sure that this function is only + // callable after that has been done. + if (delegator.status != DelegatorStatus.PendingAdded) { + revert InvalidDelegatorStatus(delegator.status); + } + + // In the case where the validator has completed its validation period, we can no + // longer stake and should move our status directly to completed and return the stake. + if (validator.status == ValidatorStatus.Completed) { + return _completeEndDelegation(delegationID); + } + + // Unpack the Warp message + (bytes32 messageValidationID, uint64 nonce,) = ValidatorMessages + .unpackSubnetValidatorWeightMessage(_getPChainWarpMessage(messageIndex).payload); + + if (validationID != messageValidationID) { + revert InvalidValidationID(delegator.validationID); + } + + // The received nonce should be no greater than the highest sent nonce, and at least as high as + // the delegation's starting nonce. This allows a weight update using a higher nonce + // (which implicitly includes the delegation's weight update) to be used to complete delisting + // for an earlier delegation. This is necessary because the P-Chain is only willing to sign the latest weight update. + if (validator.messageNonce < nonce || delegator.startingNonce > nonce) { + revert InvalidNonce(nonce); + } + + // Update the delegation status + $._delegatorStakes[delegationID].status = DelegatorStatus.Active; + $._delegatorStakes[delegationID].startedAt = uint64(block.timestamp); + + emit DelegatorRegistered({ + delegationID: delegationID, + validationID: validationID, + startTime: uint64(block.timestamp) + }); + } + + /** + * @notice See {IPoSValidatorManager-initializeEndDelegation}. + */ + function initializeEndDelegation( + bytes32 delegationID, + bool includeUptimeProof, + uint32 messageIndex + ) external { + if (!_initializeEndDelegation(delegationID, includeUptimeProof, messageIndex)) { + revert DelegatorIneligibleForRewards(delegationID); + } + } + + /** + * @notice See {IPoSValidatorManager-forceInitializeEndDelegation}. + */ + function forceInitializeEndDelegation( + bytes32 delegationID, + bool includeUptimeProof, + uint32 messageIndex + ) external { + // Ignore the return value here to force end delegation, regardless of possible missed rewards + _initializeEndDelegation(delegationID, includeUptimeProof, messageIndex); + } + + /** + * @dev Helper function that initializes the end of a PoS delegation period. + * Returns false if it is possible for the delegator to claim rewards, but it is not eligible. + * Returns true otherwise. + */ + function _initializeEndDelegation( + bytes32 delegationID, + bool includeUptimeProof, + uint32 messageIndex + ) internal returns (bool) { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + Delegator memory delegator = $._delegatorStakes[delegationID]; + bytes32 validationID = delegator.validationID; + Validator memory validator = getValidator(validationID); + + // Ensure the delegator is active + if (delegator.status != DelegatorStatus.Active) { + revert InvalidDelegatorStatus(delegator.status); + } + + // Only the delegation owner or parent validator can end the delegation. + if (delegator.owner != _msgSender()) { + // Validators can only remove delegations after the minimum stake duration has passed. + if ($._posValidatorInfo[validationID].owner != _msgSender()) { + revert UnauthorizedOwner(_msgSender()); + } + + if ( + block.timestamp + < validator.startedAt + $._posValidatorInfo[validationID].minStakeDuration + ) { + revert MinStakeDurationNotPassed(uint64(block.timestamp)); + } + } + + if (validator.status == ValidatorStatus.Active) { + // Check that minimum stake duration has passed. + if (block.timestamp < delegator.startedAt + $._minimumStakeDuration) { + revert MinStakeDurationNotPassed(uint64(block.timestamp)); + } + + if (includeUptimeProof) { + // Uptime proofs include the absolute number of seconds the validator has been active. + _updateUptime(validationID, messageIndex); + } + + // Set the delegator status to pending removed, so that it can be properly removed in + // the complete step, even if the delivered nonce is greater than the nonce used to + // initialize the removal. + $._delegatorStakes[delegationID].status = DelegatorStatus.PendingRemoved; + + ($._delegatorStakes[delegationID].endingNonce,) = + _setValidatorWeight(validationID, validator.weight - delegator.weight); + + uint256 reward = _calculateDelegationReward(delegator); + $._redeemableDelegatorRewards[delegationID] = reward; + + emit DelegatorRemovalInitialized({ + delegationID: delegationID, + validationID: validationID + }); + return (reward > 0); + } else if (validator.status == ValidatorStatus.Completed) { + $._redeemableDelegatorRewards[delegationID] = _calculateDelegationReward(delegator); + + _completeEndDelegation(delegationID); + // If the validator has completed, then no further uptimes may be submitted, so we always + // end the delegation. + return true; + } else { + revert InvalidValidatorStatus(validator.status); + } + } + + /// @dev Calculates the reward owed to the delegator based on the state of the delegator and its corresponding validator. + function _calculateDelegationReward(Delegator memory delegator) + private + view + returns (uint256) + { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + Validator memory validator = getValidator(delegator.validationID); + + uint64 delegationEndTime; + if ( + validator.status == ValidatorStatus.PendingRemoved + || validator.status == ValidatorStatus.Completed + ) { + delegationEndTime = validator.endedAt; + } else if (validator.status == ValidatorStatus.Active) { + delegationEndTime = uint64(block.timestamp); + } else { + revert InvalidValidatorStatus(validator.status); + } + + // Only give rewards in the case that the delegation started before the validator exited. + if (delegationEndTime <= delegator.startedAt) { + return 0; + } + + return $._rewardCalculator.calculateReward({ + stakeAmount: weightToValue(delegator.weight), + validatorStartTime: validator.startedAt, + stakingStartTime: delegator.startedAt, + stakingEndTime: delegationEndTime, + uptimeSeconds: $._posValidatorInfo[delegator.validationID].uptimeSeconds + }); + } + + /** + * @notice See {IPoSValidatorManager-resendUpdateDelegation}. + * @dev Resending the latest validator weight with the latest nonce is safe because all weight changes are + * cumulative, so the latest weight change will always include the weight change for any added delegators. + */ + function resendUpdateDelegation(bytes32 delegationID) external { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + Delegator memory delegator = $._delegatorStakes[delegationID]; + if ( + delegator.status != DelegatorStatus.PendingAdded + && delegator.status != DelegatorStatus.PendingRemoved + ) { + revert InvalidDelegatorStatus(delegator.status); + } + + Validator memory validator = getValidator(delegator.validationID); + if (validator.messageNonce == 0) { + revert InvalidDelegationID(delegationID); + } + + // Submit the message to the Warp precompile. + WARP_MESSENGER.sendWarpMessage( + ValidatorMessages.packSubnetValidatorWeightMessage( + delegator.validationID, validator.messageNonce, validator.weight + ) + ); + } + + /** + * @notice See {IPoSValidatorManager-completeEndDelegation}. + */ + function completeEndDelegation( + uint32 messageIndex, + bytes32 delegationID + ) external nonReentrant { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + Delegator memory delegator = $._delegatorStakes[delegationID]; + + // Ensure the delegator is pending removed. Since anybody can call this function once + // end delegation has been initialized, we need to make sure that this function is only + // callable after that has been done. + if (delegator.status != DelegatorStatus.PendingRemoved) { + revert InvalidDelegatorStatus(delegator.status); + } + + if (getValidator(delegator.validationID).status != ValidatorStatus.Completed) { + // Unpack the Warp message + WarpMessage memory warpMessage = _getPChainWarpMessage(messageIndex); + (bytes32 validationID, uint64 nonce,) = + ValidatorMessages.unpackSubnetValidatorWeightMessage(warpMessage.payload); + + if (delegator.validationID != validationID) { + revert InvalidValidationID(validationID); + } + + // The received nonce should be at least as high as the delegation's ending nonce. This allows a weight + // update using a higher nonce (which implicitly includes the delegation's weight update) to be used to + // complete delisting for an earlier delegation. This is necessary because the P-Chain is only willing + // to sign the latest weight update. + if (delegator.endingNonce > nonce) { + revert InvalidNonce(nonce); + } + } + + _completeEndDelegation(delegationID); + } + + function _completeEndDelegation(bytes32 delegationID) internal { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + + Delegator memory delegator = $._delegatorStakes[delegationID]; + bytes32 validationID = delegator.validationID; + + // To prevent churn tracker abuse, check that one full churn period has passed, + // so a delegator may not stake twice in the same churn period. + if (block.timestamp < delegator.startedAt + _getChurnPeriodSeconds()) { + revert MinStakeDurationNotPassed(uint64(block.timestamp)); + } + + // Once this function completes, the delegation is completed so we can clear it from state now. + delete $._delegatorStakes[delegationID]; + + uint256 rewards = $._redeemableDelegatorRewards[delegationID]; + delete $._redeemableDelegatorRewards[delegationID]; + + uint256 validatorFees; + uint256 delegatorRewards; + if (rewards > 0) { + validatorFees = (rewards * $._posValidatorInfo[validationID].delegationFeeBips) + / BIPS_CONVERSION_FACTOR; + + // Allocate the delegation fees to the validator. + $._redeemableValidatorRewards[validationID] += validatorFees; + + // Reward the remaining tokens to the delegator. + delegatorRewards = rewards - validatorFees; + _reward(delegator.owner, delegatorRewards); + } + + // Unlock the delegator's stake. + _unlock(delegator.owner, weightToValue(delegator.weight)); + + emit DelegationEnded(delegationID, validationID, delegatorRewards, validatorFees); + } + + /** + * @dev This function must be implemented to mint rewards to validators and delegators. + */ + function _reward(address account, uint256 amount) internal virtual; + + /** + * @dev Return true if this is a PoS validator with locked stake. Returns false if this was originally a PoA + * validator that was later migrated to this PoS manager, or the validator was part of the initial validator set. + */ + function _isPoSValidator(bytes32 validationID) internal view returns (bool) { + PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); + return $._posValidatorInfo[validationID].owner != address(0); + } +} diff --git a/contracts/validator-manager/README.md b/contracts/validator-manager/README.md new file mode 100644 index 000000000..40d6fece5 --- /dev/null +++ b/contracts/validator-manager/README.md @@ -0,0 +1,148 @@ +# Validator Manager Contract + +> [!CAUTION] +> The contracts in this directory are still under active development, are unaudited, and should not be used in production. + +The contracts in this directory define the Validator Manager used to manage Subnet-only Validators, as defined in [ACP-77](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets). `ValidatorManager.sol` is the top-level abstract contract that provides the basic functionality. The other contracts are related as follows: + +```mermaid +classDiagram +class ValidatorManager { + initializeValidatorSet() + completeValidatorRegistration() + completeEndValidation() + +} +<> ValidatorManager +class PoSValidatorManager { + initializeEndValidation() + completeDelegatorRegistration() + initializeEndDelegation() + completeEndDelegation() +} +<> PoSValidatorManager +class ERC20TokenStakingManager { + initializeValidatorRegistration() + initializeDelegatorRegistration() +} +class NativeTokenStakingManager { + initializeValidatorRegistration() payable + initializeDelegatorRegistration() payable +} +class PoAValidatorManager { + initializeValidatorRegistration() + initializeEndValidation() +} + +ValidatorManager <|-- PoSValidatorManager +ValidatorManager <|-- PoAValidatorManager +PoSValidatorManager <|-- ERC20TokenStakingManager +PoSValidatorManager <|-- NativeTokenStakingManager +``` + +## Deploying + +Three concrete `ValidatorManager` contracts are provided - `PoAValidatorManager`, `NativeTokenStakingManager`, and `ERC20TokenStakingManager`. `NativeTokenStakingManager`, and `ERC20TokenStakingManager` implement `PoSValidatorManager`, which itself implements `ValidatorManager`. These are implemented as [upgradeable](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/main/contracts/proxy/utils/Initializable.sol#L56) contracts. There are numerous [guides](https://blog.chain.link/upgradable-smart-contracts/) for deploying upgradeable smart contracts, but the general steps are as follows: +1. Deploy the implementation contract +2. Deploy the proxy contract +3. Call the implementation contract's `initialize` function + - Each flavor of `ValidatorManager` requires different settings. For example, `ValidatorManagerSettings` specifies the churn parameters, while `PoSValidatorManagerSettings` specifies the staking and rewards parameters. +4. Initialize the Validator set by calling `initializeValidatorSet` + - When a Subnet is first created on the P-Chain, it must be explicitly converted to a Subnet-only Validator compatible Subnet via [`ConvertSubnetTx`](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets#setting-a-subnet-manager). The resulting `SubnetConversionMessage` Warp message is provided in the call to `initializeValidatorSet` to specify the starting Validator set in the `ValidatorManager`. Regardless of the implementation, these initial Validators are treated as PoA and are not eligible for staking rewards. + +### PoAValidatorManager + +Proof-of-Authority Validator management is provided via `PoAValidatorManager`, which restricts modification of the Validator set to an owner address. After deploying `PoAValidatorManager.sol` and a proxy, the `initialize` function takes the owner address, in addition to standard `ValidatorManagerSettings`. + +### PoSValidatorManager + +Proof-of-Stake Validator management is provided by the abstract contract `PoSValidatorManager`, which has two concrete implementations: `NativeTokenStakingManager` and `ERC20TokenStakingManager`. In addition to basic Validator management provided in `ValidatorManager`, `PoSValidatorManager` supports uptime-based Validation rewards, as well as Delegation to a Validator. This [state transition diagram](./StateTransition.md) illustrates the relationship between Validators and Delegators. + +> [!NOTE] +> The `weightToValueFactor` fields of the `PoSValidatorManagerSettings` passed to `PoSValidatorManager`'s `initialize` function sets the factor used to convert between the weight that the Validator is registered with on the P-Chain, and the value transferred to the contract as stake. This involves integer division, which may result in loss of precision. When selecting `weightToValueFactor`, it's important to make the following considerations: +> 1. If `weightToValueFactor` is near the denomination of the asset, then staking amounts on the order of 1 unit of the asset may cause the converted weight to round down to 0. This may impose a larger-than-expected minimum stake amount. +> - Ex: If USDC (denomination of 6) is used as the staking token and `weightToValueFactor` is 1e9, then any amount less than 1,000 USDC will round down to 0 and therefore be invalid. +> 2. Staked amounts up to `weightValueFactor - 1` may be lost in the contract as dust, as the Validator's registered weight is used to calculate the original staked amount. +> - Ex: `value=1001` and `weightToValueFactor=1e3`. The resulting weight will be `1`. Converting the weight back to a value results in `value=1000`. +> 3. The Validator's weight is represented on the P-Chain as a `uint64`. `PoSValidatorManager` restricts values such that the calculated weight does not exceed the maximum value for that type. + +#### NativeTokenStakingManager + +`NativeTokenStakingManager` allows permissionless addition and removal of Validators that post the Subnet's native token as stake. Staking rewards are minted via the Native Minter Precompile, which is configured with a set of addresses with minting privileges. As such, the address that `NativeTokenStakingManager` is deployed to must be added as an admin to the precompile. This can be done by either calling the precompile's `setAdmin` method from an admin address, or setting the address in the Native Minter precompile settings in the chain's genesis (`config.contractNativeMinterConfig.adminAddresses`). There are a couple of methods to get this address: one is to calculate the resulting deployed address based on the deployer's address and account nonce: `keccak256(rlp.encode(address, nonce))`. The second method involves manually placing the `NativeTokenStakingManager` bytecode at a particular address in the genesis, then setting that address as an admin. + +``` +{ + "config" : { + ... + "contractNativeMinterConfig": { + "blockTimestamp": 0, + "adminAddresses": [ + "0xffffffffffffffffffffffffffffffffffffffff" + ] + } + }, + "alloc": { + "0xffffffffffffffffffffffffffffffffffffffff": { + "balance": "0x0", + "code": "", + "nonce": 1 + } + } +} +``` + +#### ERC20TokenStakingManager +`ERC20TokenStakingManager` allows permissionless addition and removal of Validators that post the an ERC20 token as stake. The ERC20 is specified in the call to `initialize`, and must implement [`IERC20Mintable`](./interfaces/IERC20Mintable.sol). Care should be taken to enforce that only authorized users are able to call `mint`. + +### Convert PoA to PoS + +A `PoAValidatorManager` can later be converted to a `PoSValidatorManager` by upgrading the implementation contract pointed to by the proxy. After performing the upgrade, the `PoSValidatorManager` contract should be initialized by calling `initialize` as described above. The Validator set contained in the `PoAValidatorManager` will be tracked by the `PoSValidatorManager` after the upgrade, but will not be eligible to earn staking rewards, nor are they able to be delegated to. + +## Usage +### Register a Validator +Validator registration is initiated with a call to `initializeValidatorRegistration`. The sender of this transaction is registered as the Validator owner. Churn limitations are checked - only a certain (configurable) percentage of the total weight is allowed to be added or removed in a (configurable) period of time. The `ValidatorManager` then constructs a [`RegisterSubnetValidatorMessage`](./MessageSpec.md#registersubnetvalidatormessage) Warp message to be sent to the P-Chain. Each Validator registration request includes all of the information needed to identify the Validator and its stake weight, as well as an `expiry` timestamp before which the `RegisterSubnetValidatorMessage` must be delivered to the P-Chain. If the Validator is not registered on the P-Chain before the `expiry`, then the Validator may be removed from the contract state by calling `completeEndValidation`. + +The `RegisterSubnetValidatorMessage` is delivered to the P-Chain as the Warp message payload of a [`RegisterSubnetValidatorTx`](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets#registersubnetvalidatortx). Please see the transaction [specification](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets#step-2-issue-a-registersubnetvalidatortx-on-the-p-chain) for validity requirements. The P-Chain then signs a [`SubnetValidatorRegistrationMessage`](./MessageSpec.md#subnetvalidatorregistrationmessage) Warp message indicating that the specified Validator was successfully registered on the P-Chain. + +The `SubnetValidatorRegistrationMessage` is delivered to the `ValidatorManager` via a call to `completeValidatorRegistration`. For PoS Validator Managers, staking rewards begin accruing at this time. + +### Remove a Validator +Validator exit is initiated with a call to `initializeEndValidation` on the `ValidatorManager`. Only the Validator owner may initiate exit. For `PoSValidatorManagers` a [`ValidationUptimeMessage`](./MessageSpec.md#validationuptimemessage) Warp message may optionally be provided in order to calculate the staking rewards; otherwise the latest received uptime will be used (see [(PoS only) Submit and Uptime Proof](#pos-only-submit-an-uptime-proof)). This proof may be requested directly from the Subnet Validators, which will provide it in a `ValidationUptimeMessage` Warp message. If the uptime is not sufficient to earn Validation rewards, the call to `initializeEndValidation` will fail. `forceInitializeEndValidation` acts the same as `initializeEndValidation`, but bypasses the uptime-based rewards check. Once `initializeEndValidation` or `forceInitializeEndValidation` is called, staking rewards cease accruing for `PoSValidatorManagers`. + +The `ValidatorManager` contructs a [`SetSubnetValidatorWeightMessage`](./MessageSpec.md#setsubnetvalidatorweightmessage) Warp message with the weight set to `0`. This is delivered to the P-Chain as the payload of a [`SetSubnetValidatorWeightTx`](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets#setsubnetvalidatorweighttx). The P-Chain acknowledges Validator exit by signing a `SubnetValidatorRegistrationMessage` with `valid=0`, which is delivered to the `ValidatorManager` by calling `completeEndValidation`. The Validation is removed from the contract's state, and for `PoSValidatorManagers`, staking rewards are disbursed and stake is returned. + +#### Disable a Validator Directly on the P-Chain + +ACP-77 also provides a method to disable a Validator without interacting with the Subnet directly. The P-Chain transaction [`DisableValidatorTx`](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets#disablevalidatortx) disables the Validator on the P-Chain. The disabled Validator's weight will still count towards the Subnet's total weight. + +Disabled Subnet Validators can re-activate at any time by increasing their balance with an `IncreaseBalanceTx`. Anyone can call `IncreaseBalanceTx` for any Validator on the P-Chain. A disabled Validator can only be totally removed from the Validator set by a call to `initializeEndValidation`. + +### (PoS only) Register a Delegator + +`PoSValidatorManager` supports Delegation to an active Validator as a way for users to earn staking rewards without having to validate the chain. Delegators pay a configurable percentage fee on any earned staking rewards to the host Validator. A Delegator may be registered by calling `initializeDelegatorRegistration` and providing an amount to stake. The sender of this transaction is registered as the Delegator owner. The Delegator will be registered as long as churn restrictions are not violated. The Delegator is reflected on the P-Chain by adjusting the Validator's registered weight via a [`SetSubnetValidatorWeightTx`](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets#setsubnetvalidatorweighttx). The weight change acknowledgement is delivered to the `PoSValidatorManager` via a [`SubnetValidatorWeightUpdateMessage`](./MessageSpec.md#subnetvalidatorweightupdatemessage), which is provided by calling `completeDelegatorRegistration`. + +> [!NOTE] +> The P-Chain is only willing to sign a `SubnetValidatorWeightUpdateMessage` for an active Validator. Once Validator exit has been initiated (via a call to `initializeEndValidation`), the `PoSValidatorManager` must assume that the Validator has been deactivated on the P-Chain, and will therefore not sign any further weight updates. Therefore, it is invalid to _initiate_ adding or removing a Delegator when the Validator is in this state, though it _may be_ valid to _complete_ an already initiated Delegator action, depending on the order of delivery to the P-Chain. If the Delegator weight change was submitted (and a Warp signature on the acknowledgement retrieved) before the Validator was removed, then the Delegator action may be completed. Otherwise, the acknowledgement of the Validation end must first be delivered before completing the Delegator action. + +### (PoS only) Remove a Delegator + +Delegators removal may be initiated by calling `initializeEndDelegation`, as long as churn restrictions are not violated. Similar to `initializeEndValidation`, an uptime proof may be provided to be used to determine Delegator rewards eligibility. If no proof is provided, the latest known uptime will be used (see [(PoS only) Submit and Uptime Proof](#pos-only-submit-an-uptime-proof)). The Validator's weight is updated on the P-Chain by the same mechanism used to register a Delegator. The `SubnetValidatorWeightUpdateMessage` from the P-Chain is delivered to the `PoSValidatorManager` in the call to `completeEndDelegation`. + +Either the Delegator owner or the Validator owner may initiate removing a Delegator. This is to prevent the Validator from being unable to remove itself due to churn limitations if it is has too high a proportion of the Subnet's total weight due to Delegator additions. The Validator owner may only remove Delegators after the minimum stake duration has elapsed. + +### (PoS only) Submit an Uptime Proof + +The [rewards calculater](./interfaces/IRewardCalculator.sol) is a function of uptime seconds since the Validator's start time. In addition to doing so in the calls to `initializeEndValidation` and `initializeEndDelegation` as described above, uptime proofs may also be supplied by calling `submitUptimeProof`. Unlike `initializeEndValidation` and `initializeEndDelegation`, `submitUptimeProof` may be called by anyone, decreasing the likelihood of a Validation or Delegation not being able to claim rewards that it deserved based on its actual uptime. + +### (PoS only) Collect Staking Rewards +#### Validation Rewards + +Validation rewards are distributed in the call to `completeEndValidation`. + +#### Delegation Rewards + +Delegation rewards are distributed in the call to `completeEndDelegation`. + +#### Delegation Fees + +Delegation fees owed to Validators are _not_ distributed when the Validation ends as to bound the amount of gas consumed in the call to `completeEndValidation`. Instead, `claimDelegationFees` may be called after the Validation is completed. diff --git a/contracts/validator-manager/StateTransition.md b/contracts/validator-manager/StateTransition.md new file mode 100644 index 000000000..9dd3c8de5 --- /dev/null +++ b/contracts/validator-manager/StateTransition.md @@ -0,0 +1,33 @@ +## State Transitions + +The following state transition diagram illustrates the relationship between Validator and Delegator state. `Validator` is abbreviated as `V`, `Delegator` is abbreviated as `D`, and function names are shortened to improve readability. `Delegator.Completed` is omitted to show equivalance between the Validator's initial state and the state after a Delegation completes. +```mermaid +stateDiagram-v2 + % Happy path + [*] --> V.PendingAdded : initVdrReg + V.PendingAdded --> V.Active : completeVdrReg + V.PendingAdded --> V.Completed : completeVdrReg (expiry passed) + V.Active --> V.Active,D.PendingAdded : initDelReg + V.Active,D.PendingAdded --> V.Active,D.Active : completeDelReg + V.Active,D.Active --> V.Active,D.PendingRemoved : initEndDel + V.Active,D.PendingRemoved --> V.Active : completeEndDel + V.Active --> V.PendingRemoved : initEndVdr + V.PendingRemoved --> V.Completed : completeEndVdr + + % Validator/Delegator state changes do not affect the Delegator/Validator state + V.Active,D.PendingRemoved --> V.PendingRemoved,D.PendingRemoved : initEndVdr + V.Active,D.PendingAdded --> V.PendingRemoved,D.PendingAdded : initEndVdr + V.Active,D.Active --> V.PendingRemoved,D.Active: initEndVdr + + % When the Validator is in PendingRemoved or Completed, in general Delegator actions + % may be completed, but not initialized. + V.PendingRemoved,D.PendingAdded --> V.Completed,D.PendingAdded : completeEndVdr + V.PendingRemoved,D.PendingRemoved --> V.Completed,D.PendingRemoved : completeEndVdr + V.PendingRemoved,D.PendingRemoved --> V.PendingRemoved : completeEndDel + V.PendingRemoved,D.Active --> V.Completed,D.Active : completeEndVdr + % This is a no-op + V.PendingRemoved,D.PendingAdded --> V.PendingRemoved,D.Active : completeDelReg + V.Completed,D.PendingRemoved --> V.Completed : completeEndDel + V.Completed,D.Active --> V.Completed : initEndDel + V.Completed,D.PendingAdded --> V.Completed : completeDelReg +``` diff --git a/contracts/validator-manager/ValidatorManager.sol b/contracts/validator-manager/ValidatorManager.sol new file mode 100644 index 000000000..943a7b356 --- /dev/null +++ b/contracts/validator-manager/ValidatorManager.sol @@ -0,0 +1,598 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {ValidatorMessages} from "./ValidatorMessages.sol"; +import { + InitialValidator, + IValidatorManager, + PChainOwner, + SubnetConversionData, + Validator, + ValidatorChurnPeriod, + ValidatorManagerSettings, + ValidatorRegistrationInput, + ValidatorStatus +} from "./interfaces/IValidatorManager.sol"; +import { + IWarpMessenger, + WarpMessage +} from "@avalabs/subnet-evm-contracts@1.2.0/contracts/interfaces/IWarpMessenger.sol"; +import {ContextUpgradeable} from + "@openzeppelin/contracts-upgradeable@5.0.2/utils/ContextUpgradeable.sol"; +import {Initializable} from + "@openzeppelin/contracts-upgradeable@5.0.2/proxy/utils/Initializable.sol"; + +/** + * @dev Implementation of the {IValidatorManager} interface. + * + * @custom:security-contact https://github.com/ava-labs/teleporter/blob/main/SECURITY.md + */ +abstract contract ValidatorManager is Initializable, ContextUpgradeable, IValidatorManager { + // solhint-disable private-vars-leading-underscore + /// @custom:storage-location erc7201:avalanche-icm.storage.ValidatorManager + + struct ValidatorManagerStorage { + /// @notice The subnetID associated with this validator manager. + bytes32 _subnetID; + /// @notice The number of seconds after which to reset the churn tracker. + uint64 _churnPeriodSeconds; + /// @notice The maximum churn rate allowed per churn period. + uint8 _maximumChurnPercentage; + /// @notice The churn tracker used to track the amount of stake added or removed in the churn period. + ValidatorChurnPeriod _churnTracker; + /// @notice Maps the validationID to the registration message such that the message can be re-sent if needed. + mapping(bytes32 => bytes) _pendingRegisterValidationMessages; + /// @notice Maps the validationID to the validator information. + mapping(bytes32 => Validator) _validationPeriods; + /// @notice Maps the nodeID to the validationID for validation periods that have not ended. + mapping(bytes => bytes32) _registeredValidators; + /// @notice Boolean that indicates if the initial validator set has been set. + bool _initializedValidatorSet; + } + // solhint-enable private-vars-leading-underscore + + // keccak256(abi.encode(uint256(keccak256("avalanche-icm.storage.ValidatorManager")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 public constant VALIDATOR_MANAGER_STORAGE_LOCATION = + 0xe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb00; + + uint8 public constant MAXIMUM_CHURN_PERCENTAGE_LIMIT = 20; + uint64 public constant MAXIMUM_REGISTRATION_EXPIRY_LENGTH = 2 days; + uint32 public constant ADDRESS_LENGTH = 20; // This is only used as a packed uint32 + uint8 public constant BLS_PUBLIC_KEY_LENGTH = 48; + bytes32 public constant P_CHAIN_BLOCKCHAIN_ID = bytes32(0); + + error InvalidValidatorManagerAddress(address validatorManagerAddress); + error InvalidWarpOriginSenderAddress(address senderAddress); + error InvalidValidatorManagerBlockchainID(bytes32 blockchainID); + error InvalidWarpSourceChainID(bytes32 sourceChainID); + error InvalidRegistrationExpiry(uint64 registrationExpiry); + error InvalidInitializationStatus(); + error InvalidMaximumChurnPercentage(uint8 maximumChurnPercentage); + error InvalidBLSKeyLength(uint256 length); + error InvalidNodeID(bytes nodeID); + error InvalidSubnetConversionID( + bytes32 encodedSubnetConversionID, bytes32 expectedSubnetConversionID + ); + error InvalidTotalWeight(uint256 weight); + error InvalidValidationID(bytes32 validationID); + error InvalidValidatorStatus(ValidatorStatus status); + error InvalidWarpMessage(); + error MaxChurnRateExceeded(uint64 churnAmount); + error NodeAlreadyRegistered(bytes nodeID); + error UnexpectedRegistrationStatus(bool validRegistration); + error InvalidPChainOwnerThreshold(uint256 threshold, uint256 addressesLength); + error PChainOwnerAddressesNotSorted(); + + // solhint-disable ordering + function _getValidatorManagerStorage() + private + pure + returns (ValidatorManagerStorage storage $) + { + // solhint-disable-next-line no-inline-assembly + assembly { + $.slot := VALIDATOR_MANAGER_STORAGE_LOCATION + } + } + + /** + * @notice Warp precompile used for sending and receiving Warp messages. + */ + IWarpMessenger public constant WARP_MESSENGER = + IWarpMessenger(0x0200000000000000000000000000000000000005); + + // solhint-disable-next-line func-name-mixedcase + function __ValidatorManager_init(ValidatorManagerSettings calldata settings) + internal + onlyInitializing + { + __Context_init(); + __ValidatorManager_init_unchained(settings); + } + + // solhint-disable-next-line func-name-mixedcase + function __ValidatorManager_init_unchained(ValidatorManagerSettings calldata settings) + internal + onlyInitializing + { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + $._subnetID = settings.subnetID; + + if ( + settings.maximumChurnPercentage > MAXIMUM_CHURN_PERCENTAGE_LIMIT + || settings.maximumChurnPercentage == 0 + ) { + revert InvalidMaximumChurnPercentage(settings.maximumChurnPercentage); + } + + $._maximumChurnPercentage = settings.maximumChurnPercentage; + $._churnPeriodSeconds = settings.churnPeriodSeconds; + } + + modifier initializedValidatorSet() { + if (!_getValidatorManagerStorage()._initializedValidatorSet) { + revert InvalidInitializationStatus(); + } + _; + } + + /** + * @notice See {IValidatorManager-initializeValidatorSet}. + */ + function initializeValidatorSet( + SubnetConversionData calldata subnetConversionData, + uint32 messageIndex + ) external { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + if ($._initializedValidatorSet) { + revert InvalidInitializationStatus(); + } + // Check that the blockchainID and validator manager address in the subnetConversionData correspond to this contract. + // Other validation checks are done by the P-Chain when converting the subnet, so are not required here. + if (subnetConversionData.validatorManagerBlockchainID != WARP_MESSENGER.getBlockchainID()) { + revert InvalidValidatorManagerBlockchainID( + subnetConversionData.validatorManagerBlockchainID + ); + } + if (address(subnetConversionData.validatorManagerAddress) != address(this)) { + revert InvalidValidatorManagerAddress( + address(subnetConversionData.validatorManagerAddress) + ); + } + + uint256 numInitialValidators = subnetConversionData.initialValidators.length; + + uint256 totalWeight; + for (uint32 i; i < numInitialValidators; ++i) { + InitialValidator memory initialValidator = subnetConversionData.initialValidators[i]; + if ($._registeredValidators[initialValidator.nodeID] != bytes32(0)) { + revert NodeAlreadyRegistered(initialValidator.nodeID); + } + + // Validation ID of the initial validators is the sha256 hash of the + // convert Subnet tx ID and the index of the initial validator. + bytes32 validationID = sha256(abi.encodePacked(subnetConversionData.subnetID, i)); + + // Save the initial validator as an active validator. + + $._registeredValidators[initialValidator.nodeID] = validationID; + $._validationPeriods[validationID] = Validator({ + status: ValidatorStatus.Active, + nodeID: initialValidator.nodeID, + startingWeight: initialValidator.weight, + messageNonce: 0, + weight: initialValidator.weight, + startedAt: uint64(block.timestamp), + endedAt: 0 + }); + totalWeight += initialValidator.weight; + + emit InitialValidatorCreated( + validationID, initialValidator.nodeID, initialValidator.weight + ); + } + $._churnTracker.totalWeight = totalWeight; + + // Rearranged equation for totalWeight < (100 / $._maximumChurnPercentage) + // Total weight must be above this value in order to not trigger churn limits with an added/removed weight of 1. + if (totalWeight * $._maximumChurnPercentage < 100) { + revert InvalidTotalWeight(totalWeight); + } + + // Verify that the sha256 hash of the Subnet conversion data matches with the Warp message's subnetConversionID. + bytes32 subnetConversionID = ValidatorMessages.unpackSubnetConversionMessage( + _getPChainWarpMessage(messageIndex).payload + ); + bytes memory encodedConversion = + ValidatorMessages.packSubnetConversionData(subnetConversionData); + bytes32 encodedSubnetConversionID = sha256(encodedConversion); + if (encodedSubnetConversionID != subnetConversionID) { + revert InvalidSubnetConversionID(encodedSubnetConversionID, subnetConversionID); + } + + $._initializedValidatorSet = true; + } + + function _validatePChainOwner(PChainOwner calldata pChainOwner) internal pure { + // If threshold is 0, addresses must be empty. + if (pChainOwner.threshold == 0 && pChainOwner.addresses.length != 0) { + revert InvalidPChainOwnerThreshold(pChainOwner.threshold, pChainOwner.addresses.length); + } + // Threshold must be less than or equal to the number of addresses. + if (pChainOwner.threshold > pChainOwner.addresses.length) { + revert InvalidPChainOwnerThreshold(pChainOwner.threshold, pChainOwner.addresses.length); + } + // Addresses must be sorted in ascending order + for (uint256 i = 1; i < pChainOwner.addresses.length; i++) { + // Compare current address with the previous one + if (pChainOwner.addresses[i] < pChainOwner.addresses[i - 1]) { + revert PChainOwnerAddressesNotSorted(); + } + } + } + + /** + * @notice Begins the validator registration process, and sets the initial weight for the validator. + * This is the only method related to validator registration and removal that needs the initializedValidatorSet + * modifier. All others are guarded by checking the validator status changes initialized in this function. + * @param input The inputs for a validator registration. + * @param weight The weight of the validator being registered. + */ + function _initializeValidatorRegistration( + ValidatorRegistrationInput calldata input, + uint64 weight + ) internal virtual initializedValidatorSet returns (bytes32) { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + + if ( + input.registrationExpiry <= block.timestamp + || input.registrationExpiry >= block.timestamp + MAXIMUM_REGISTRATION_EXPIRY_LENGTH + ) { + revert InvalidRegistrationExpiry(input.registrationExpiry); + } + + _validatePChainOwner(input.remainingBalanceOwner); + _validatePChainOwner(input.disableOwner); + + // Ensure the nodeID is not the zero address, and is not already an active validator. + + if (input.blsPublicKey.length != BLS_PUBLIC_KEY_LENGTH) { + revert InvalidBLSKeyLength(input.blsPublicKey.length); + } + if (input.nodeID.length == 0) { + revert InvalidNodeID(input.nodeID); + } + if ($._registeredValidators[input.nodeID] != bytes32(0)) { + revert NodeAlreadyRegistered(input.nodeID); + } + + // Check that adding this validator would not exceed the maximum churn rate. + _checkAndUpdateChurnTracker(weight, 0); + + (bytes32 validationID, bytes memory registerSubnetValidatorMessage) = ValidatorMessages + .packRegisterSubnetValidatorMessage( + ValidatorMessages.ValidationPeriod({ + subnetID: $._subnetID, + nodeID: input.nodeID, + blsPublicKey: input.blsPublicKey, + remainingBalanceOwner: input.remainingBalanceOwner, + disableOwner: input.disableOwner, + registrationExpiry: input.registrationExpiry, + weight: weight + }) + ); + $._pendingRegisterValidationMessages[validationID] = registerSubnetValidatorMessage; + $._registeredValidators[input.nodeID] = validationID; + + // Submit the message to the Warp precompile. + bytes32 messageID = WARP_MESSENGER.sendWarpMessage(registerSubnetValidatorMessage); + $._validationPeriods[validationID] = Validator({ + status: ValidatorStatus.PendingAdded, + nodeID: input.nodeID, + startingWeight: weight, + messageNonce: 0, + weight: weight, + startedAt: 0, // The validation period only starts once the registration is acknowledged. + endedAt: 0 + }); + + emit ValidationPeriodCreated( + validationID, input.nodeID, messageID, weight, input.registrationExpiry + ); + + return validationID; + } + + /** + * @notice See {IValidatorManager-resendRegisterValidatorMessage}. + */ + function resendRegisterValidatorMessage(bytes32 validationID) external { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + // The initial validator set must have been set already to have pending register validation messages. + if ($._pendingRegisterValidationMessages[validationID].length == 0) { + revert InvalidValidationID(validationID); + } + if ($._validationPeriods[validationID].status != ValidatorStatus.PendingAdded) { + revert InvalidValidatorStatus($._validationPeriods[validationID].status); + } + + // Submit the message to the Warp precompile. + WARP_MESSENGER.sendWarpMessage($._pendingRegisterValidationMessages[validationID]); + } + + /** + * @notice See {IValidatorManager-completeValidatorRegistration}. + */ + function completeValidatorRegistration(uint32 messageIndex) external { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + (bytes32 validationID, bool validRegistration) = ValidatorMessages + .unpackSubnetValidatorRegistrationMessage(_getPChainWarpMessage(messageIndex).payload); + + if (!validRegistration) { + revert UnexpectedRegistrationStatus(validRegistration); + } + // The initial validator set must have been set already to have pending register validation messages. + if ($._pendingRegisterValidationMessages[validationID].length == 0) { + revert InvalidValidationID(validationID); + } + if ($._validationPeriods[validationID].status != ValidatorStatus.PendingAdded) { + revert InvalidValidatorStatus($._validationPeriods[validationID].status); + } + + delete $._pendingRegisterValidationMessages[validationID]; + $._validationPeriods[validationID].status = ValidatorStatus.Active; + $._validationPeriods[validationID].startedAt = uint64(block.timestamp); + emit ValidationPeriodRegistered( + validationID, $._validationPeriods[validationID].weight, block.timestamp + ); + } + + /** + * @notice Returns a validation ID registered to the given nodeID + * @param nodeID ID of the node associated with the validation ID + */ + function registeredValidators(bytes calldata nodeID) public view returns (bytes32) { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + return $._registeredValidators[nodeID]; + } + + /** + * @notice Returns a validator registered to the given validationID + * @param validationID ID of the validation period associated with the validator + */ + function getValidator(bytes32 validationID) public view returns (Validator memory) { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + return $._validationPeriods[validationID]; + } + + /** + * @notice Begins the process of ending an active validation period. The validation period must have been previously + * started by a successful call to {completeValidatorRegistration} with the given validationID. + * Any rewards for this validation period will stop accruing when this function is called. + * @param validationID The ID of the validation period being ended. + */ + function _initializeEndValidation(bytes32 validationID) + internal + virtual + returns (Validator memory) + { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + + // Ensure the validation period is active. + // The initial validator set must have been set already to have active validators. + Validator memory validator = $._validationPeriods[validationID]; + if (validator.status != ValidatorStatus.Active) { + revert InvalidValidatorStatus($._validationPeriods[validationID].status); + } + + // Update the validator status to pending removal. + // They are not removed from the active validators mapping until the P-Chain acknowledges the removal. + validator.status = ValidatorStatus.PendingRemoved; + + // Set the end time of the validation period, since it is no longer known to be an active validator + // on the P-Chain. + validator.endedAt = uint64(block.timestamp); + + // Save the validator updates. + $._validationPeriods[validationID] = validator; + + (, bytes32 messageID) = _setValidatorWeight(validationID, 0); + + // Emit the event to signal the start of the validator removal process. + emit ValidatorRemovalInitialized(validationID, messageID, validator.weight, block.timestamp); + + return validator; + } + + /** + * @notice See {IValidatorManager-resendEndValidatorMessage}. + */ + function resendEndValidatorMessage(bytes32 validationID) external { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + Validator memory validator = $._validationPeriods[validationID]; + + // The initial validator set must have been set already to have pending end validation messages. + if (validator.status != ValidatorStatus.PendingRemoved) { + revert InvalidValidatorStatus($._validationPeriods[validationID].status); + } + + WARP_MESSENGER.sendWarpMessage( + ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, validator.messageNonce, 0 + ) + ); + } + + /** + * @notice Completes the process of ending a validation period by receiving an acknowledgement from the P-Chain + * that the validation ID is not active and will never be active in the future. + * Note: that this function can be used for successful validation periods that have been explicitly + * ended by calling {initializeEndValidation} or for validation periods that never began on the P-Chain due to the + * {registrationExpiry} being reached. + * @return (Validation ID, Validator instance) representing the completed validation period. + */ + function _completeEndValidation(uint32 messageIndex) + internal + returns (bytes32, Validator memory) + { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + + // Get the Warp message. + (bytes32 validationID, bool validRegistration) = ValidatorMessages + .unpackSubnetValidatorRegistrationMessage(_getPChainWarpMessage(messageIndex).payload); + if (validRegistration) { + revert UnexpectedRegistrationStatus(validRegistration); + } + + Validator memory validator = $._validationPeriods[validationID]; + + // The validation status is PendingRemoved if validator removal was initiated with a call to {initiateEndValidation}. + // The validation status is PendingAdded if the validator was never registered on the P-Chain. + // The initial validator set must have been set already to have pending validation messages. + if ( + validator.status != ValidatorStatus.PendingRemoved + && validator.status != ValidatorStatus.PendingAdded + ) { + revert InvalidValidatorStatus(validator.status); + } + + if (validator.status == ValidatorStatus.PendingRemoved) { + validator.status = ValidatorStatus.Completed; + } else { + validator.status = ValidatorStatus.Invalidated; + } + // Remove the validator from the registered validators mapping. + delete $._registeredValidators[validator.nodeID]; + + // Update the validator. + $._validationPeriods[validationID] = validator; + + // Emit event. + emit ValidationPeriodEnded(validationID, validator.status); + + return (validationID, validator); + } + + /** + * @notice Returns the validator's weight. This weight is not guaranteed to be known by the P-Chain + * @return Weight of the validator. If the validation ID does not exist, the weight will be 0. + */ + function getWeight(bytes32 validationID) external view returns (uint64) { + return getValidator(validationID).weight; + } + + function _incrementAndGetNonce(bytes32 validationID) internal returns (uint64) { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + return ++$._validationPeriods[validationID].messageNonce; + } + + function _getPChainWarpMessage(uint32 messageIndex) + internal + view + returns (WarpMessage memory) + { + (WarpMessage memory warpMessage, bool valid) = + WARP_MESSENGER.getVerifiedWarpMessage(messageIndex); + if (!valid) { + revert InvalidWarpMessage(); + } + // Must match to P-Chain blockchain id, which is 0. + if (warpMessage.sourceChainID != P_CHAIN_BLOCKCHAIN_ID) { + revert InvalidWarpSourceChainID(warpMessage.sourceChainID); + } + if (warpMessage.originSenderAddress != address(0)) { + revert InvalidWarpOriginSenderAddress(warpMessage.originSenderAddress); + } + + return warpMessage; + } + + function _setValidatorWeight( + bytes32 validationID, + uint64 newWeight + ) internal returns (uint64, bytes32) { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + uint64 validatorWeight = $._validationPeriods[validationID].weight; + + // Check that changing the validator weight would not exceed the maximum churn rate. + _checkAndUpdateChurnTracker(newWeight, validatorWeight); + + uint64 nonce = _incrementAndGetNonce(validationID); + + $._validationPeriods[validationID].weight = newWeight; + + // Submit the message to the Warp precompile. + bytes32 messageID = WARP_MESSENGER.sendWarpMessage( + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, nonce, newWeight) + ); + + emit ValidatorWeightUpdate({ + validationID: validationID, + nonce: nonce, + validatorWeight: newWeight, + setWeightMessageID: messageID + }); + + return (nonce, messageID); + } + + function _getChurnPeriodSeconds() internal view returns (uint64) { + return _getValidatorManagerStorage()._churnPeriodSeconds; + } + + /** + * @dev Helper function to check if the stake weight to be added or removed would exceed the maximum stake churn + * rate for the past churn period. If the churn rate is exceeded, the function will revert. If the churn rate is + * not exceeded, the function will update the churn tracker with the new weight. + */ + function _checkAndUpdateChurnTracker( + uint64 newValidatorWeight, + uint64 oldValidatorWeight + ) private { + ValidatorManagerStorage storage $ = _getValidatorManagerStorage(); + + uint64 weightChange; + if (newValidatorWeight > oldValidatorWeight) { + weightChange = newValidatorWeight - oldValidatorWeight; + } else { + weightChange = oldValidatorWeight - newValidatorWeight; + } + + uint256 currentTime = block.timestamp; + ValidatorChurnPeriod memory churnTracker = $._churnTracker; + + if ( + churnTracker.startedAt == 0 + || currentTime >= churnTracker.startedAt + $._churnPeriodSeconds + ) { + churnTracker.churnAmount = weightChange; + churnTracker.startedAt = currentTime; + churnTracker.initialWeight = churnTracker.totalWeight; + } else { + // Churn is always additive whether the weight is being added or removed. + churnTracker.churnAmount += weightChange; + } + + // Rearranged equation of maximumChurnPercentage >= currentChurnPercentage to avoid integer division truncation. + if ($._maximumChurnPercentage * churnTracker.initialWeight < churnTracker.churnAmount * 100) + { + revert MaxChurnRateExceeded(churnTracker.churnAmount); + } + + // Two separate calculations because we're using uints and (newValidatorWeight - oldValidatorWeight) could underflow. + churnTracker.totalWeight += newValidatorWeight; + churnTracker.totalWeight -= oldValidatorWeight; + + // Rearranged equation for totalWeight < (100 / $._maximumChurnPercentage) + // Total weight must be above this value in order to not trigger churn limits with an added/removed weight of 1. + if (churnTracker.totalWeight * $._maximumChurnPercentage < 100) { + revert InvalidTotalWeight(churnTracker.totalWeight); + } + + $._churnTracker = churnTracker; + } +} diff --git a/contracts/validator-manager/ValidatorMessages.sol b/contracts/validator-manager/ValidatorMessages.sol new file mode 100644 index 000000000..ca836eb5a --- /dev/null +++ b/contracts/validator-manager/ValidatorMessages.sol @@ -0,0 +1,671 @@ +// (c) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem +pragma solidity 0.8.25; + +import {PChainOwner, SubnetConversionData} from "./interfaces/IValidatorManager.sol"; + +/** + * @dev Packing utilities for the Warp message types used by the Validator Manager contracts, as specified in ACP-77: + * https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/77-reinventing-subnets + */ +library ValidatorMessages { + // The information that uniquely identifies a subnet validation period. + // The validationID is the SHA-256 hash of the concatenation of the CODEC_ID, + // REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID, and the concatenated ValidationPeriod fields. + struct ValidationPeriod { + bytes32 subnetID; + bytes nodeID; + bytes blsPublicKey; + uint64 registrationExpiry; + PChainOwner remainingBalanceOwner; + PChainOwner disableOwner; + uint64 weight; + } + + // The P-Chain uses a hardcoded codecID of 0 for all messages. + uint16 internal constant CODEC_ID = 0; + + // The P-Chain signs a SubnetConversion message that is used to verify the Subnet's initial validators. + uint32 internal constant SUBNET_CONVERSION_MESSAGE_TYPE_ID = 0; + + // Subnets send a RegisterSubnetValidator message to the P-Chain to register a validator. + uint32 internal constant REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID = 1; + + // The P-Chain responds with a RegisterSubnetValidator message indicating whether the registration was successful + // for the given validation ID. + uint32 internal constant SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID = 2; + + // Subnets can send a SubnetValidatorWeight message to the P-Chain to update a validator's weight. + // The P-Chain responds with another SubnetValidatorWeight message acknowledging the weight update. + uint32 internal constant SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID = 3; + + // The Subnet will self-sign a ValidationUptimeMessage to be provided when a validator is initiating + // the end of their validation period. + uint32 internal constant VALIDATION_UPTIME_MESSAGE_TYPE_ID = 0; + + error InvalidMessageLength(uint32 actual, uint32 expected); + error InvalidCodecID(uint32 id); + error InvalidMessageType(); + error InvalidBLSPublicKey(); + + /** + * @notice Packs a SubnetConversionMessage message into a byte array. + * The message format specification is: + * +--------------------+----------+----------+ + * | codecID : uint16 | 2 bytes | + * +--------------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------------+----------+----------+ + * | subnetConversionID : [32]byte | 32 bytes | + * +--------------------+----------+----------+ + * | 38 bytes | + * +----------+ + * + * @param subnetConversionID The subnet conversion ID to pack into the message. + * @return The packed message. + */ + function packSubnetConversionMessage(bytes32 subnetConversionID) + internal + pure + returns (bytes memory) + { + return abi.encodePacked(CODEC_ID, SUBNET_CONVERSION_MESSAGE_TYPE_ID, subnetConversionID); + } + + /** + * @notice Unpacks a byte array as a SubnetConversionMessage message. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The unpacked subnetConversionID. + */ + function unpackSubnetConversionMessage(bytes memory input) internal pure returns (bytes32) { + if (input.length != 38) { + revert InvalidMessageLength(uint32(input.length), 38); + } + + // Unpack the codec ID + uint16 codecID; + for (uint256 i; i < 2; ++i) { + codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); + } + if (codecID != CODEC_ID) { + revert InvalidCodecID(codecID); + } + + // Unpack the type ID + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); + } + if (typeID != SUBNET_CONVERSION_MESSAGE_TYPE_ID) { + revert InvalidMessageType(); + } + + // Unpack the subnetConversionID + bytes32 subnetConversionID; + for (uint256 i; i < 32; ++i) { + subnetConversionID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); + } + + return subnetConversionID; + } + + /** + * @notice Packs SubnetConversionData into a byte array. + * This byte array is the SHA256 pre-image of the subnetConversionID hash + * The message format specification is: + * + * SubnetConversionData: + * +----------------+-----------------+--------------------------------------------------------+ + * | codecID : uint16 | 2 bytes | + * +----------------+-----------------+--------------------------------------------------------+ + * | subnetID : [32]byte | 32 bytes | + * +----------------+-----------------+--------------------------------------------------------+ + * | managerChainID : [32]byte | 32 bytes | + * +----------------+-----------------+--------------------------------------------------------+ + * | managerAddress : []byte | 4 + len(managerAddress) bytes | + * +----------------+-----------------+--------------------------------------------------------+ + * | validators : []ValidatorData | 4 + sum(validatorLengths) bytes | + * +----------------+-----------------+--------------------------------------------------------+ + * | 74 + len(managerAddress) + len(validatorLengths) bytes | + * +--------------------------------------------------------+ + * ValidatorData: + * +--------------+----------+------------------------+ + * | nodeID : []byte | 4 + len(nodeID) bytes | + * +--------------+----------+------------------------+ + * | blsPublicKey : [48]byte | 48 bytes | + * +--------------+----------+------------------------+ + * | weight : uint64 | 8 bytes | + * +--------------+----------+------------------------+ + * | 60 + len(nodeID) bytes | + * +------------------------+ + * + * @dev Input validation is skipped, since the returned value is intended to be compared + * directly with an authenticated Warp message. + * @param subnetConversionData The struct representing data to pack into the message. + * @return The packed message. + */ + function packSubnetConversionData(SubnetConversionData calldata subnetConversionData) + internal + pure + returns (bytes memory) + { + // Hardcoded 20 is for length of the managerAddress on EVM chains + // solhint-disable-next-line func-named-parameters + bytes memory res = abi.encodePacked( + CODEC_ID, + subnetConversionData.subnetID, + subnetConversionData.validatorManagerBlockchainID, + uint32(20), + subnetConversionData.validatorManagerAddress, + uint32(subnetConversionData.initialValidators.length) + ); + // The approach below of encoding initialValidators using `abi.encodePacked` in a loop + // was tested against pre-allocating the array and doing manual byte by byte packing and + // it was found to be more gas efficient. + for (uint256 i; i < subnetConversionData.initialValidators.length; ++i) { + res = abi.encodePacked( + res, + uint32(subnetConversionData.initialValidators[i].nodeID.length), + subnetConversionData.initialValidators[i].nodeID, + subnetConversionData.initialValidators[i].blsPublicKey, + subnetConversionData.initialValidators[i].weight + ); + } + return res; + } + + /** + * @notice Packs a RegisterSubnetValidatorMessage message into a byte array. + * The message format specification is: + * + * RegisterSubnetValidatorMessage: + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | codecID : uint16 | 2 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | typeID : uint32 | 4 bytes | + * +-----------------------+-------------+-------------------------------------------------------------------+ + * | subnetID : [32]byte | 32 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | nodeID : []byte | 4 + len(nodeID) bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | blsPublicKey : [48]byte | 48 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | expiry : uint64 | 8 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | remainingBalanceOwner : PChainOwner | 8 + len(addresses) * 20 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | disableOwner : PChainOwner | 8 + len(addresses) * 20 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | weight : uint64 | 8 bytes | + * +-----------------------+-------------+--------------------------------------------------------------------+ + * | 122 + len(nodeID) + (len(addresses1) + len(addresses2)) * 20 bytes | + * +--------------------------------------------------------------------+ + * + * PChainOwner: + * +-----------+------------+-------------------------------+ + * | threshold : uint32 | 4 bytes | + * +-----------+------------+-------------------------------+ + * | addresses : [][20]byte | 4 + len(addresses) * 20 bytes | + * +-----------+------------+-------------------------------+ + * | 8 + len(addresses) * 20 bytes | + * +-------------------------------+ + * + * @param validationPeriod The information to pack into the message. + * @return The validationID and the packed message. + */ + function packRegisterSubnetValidatorMessage(ValidationPeriod memory validationPeriod) + internal + pure + returns (bytes32, bytes memory) + { + if (validationPeriod.blsPublicKey.length != 48) { + revert InvalidBLSPublicKey(); + } + + // solhint-disable-next-line func-named-parameters + bytes memory res = abi.encodePacked( + CODEC_ID, + REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID, + validationPeriod.subnetID, + uint32(validationPeriod.nodeID.length), + validationPeriod.nodeID, + validationPeriod.blsPublicKey, + validationPeriod.registrationExpiry, + validationPeriod.remainingBalanceOwner.threshold, + uint32(validationPeriod.remainingBalanceOwner.addresses.length) + ); + for (uint256 i; i < validationPeriod.remainingBalanceOwner.addresses.length; ++i) { + res = abi.encodePacked(res, validationPeriod.remainingBalanceOwner.addresses[i]); + } + res = abi.encodePacked( + res, + validationPeriod.disableOwner.threshold, + uint32(validationPeriod.disableOwner.addresses.length) + ); + for (uint256 i; i < validationPeriod.disableOwner.addresses.length; ++i) { + res = abi.encodePacked(res, validationPeriod.disableOwner.addresses[i]); + } + res = abi.encodePacked(res, validationPeriod.weight); + + return (sha256(res), res); + } + + /** + * @notice Unpacks a byte array as a RegisterSubnetValidatorMessage message. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The unpacked ValidationPeriod. + */ + function unpackRegisterSubnetValidatorMessage(bytes memory input) + internal + pure + returns (ValidationPeriod memory) + { + uint32 index = 0; + ValidationPeriod memory validation; + + // Unpack the codec ID + // Individual fields are unpacked in their own scopes to avoid stack too deep errors. + { + uint16 codecID; + for (uint256 i; i < 2; ++i) { + codecID |= uint16(uint8(input[i + index])) << uint16((8 * (1 - i))); + } + if (codecID != CODEC_ID) { + revert InvalidCodecID(codecID); + } + index += 2; + } + + // Unpack the type ID + { + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i + index])) << uint32((8 * (3 - i))); + } + if (typeID != REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID) { + revert InvalidMessageType(); + } + index += 4; + } + + // Unpack the subnetID + { + bytes32 subnetID; + for (uint256 i; i < 32; ++i) { + subnetID |= bytes32(uint256(uint8(input[i + index])) << (8 * (31 - i))); + } + validation.subnetID = subnetID; + index += 32; + } + + // Unpack the nodeID length + uint32 nodeIDLength; + { + for (uint256 i; i < 4; ++i) { + nodeIDLength |= uint32(uint8(input[i + index])) << uint32((8 * (3 - i))); + } + index += 4; + + // Unpack the nodeID + bytes memory nodeID = new bytes(nodeIDLength); + for (uint256 i; i < nodeIDLength; ++i) { + nodeID[i] = input[i + index]; + } + validation.nodeID = nodeID; + index += nodeIDLength; + } + + // Unpack the blsPublicKey + { + bytes memory blsPublicKey = new bytes(48); + for (uint256 i; i < 48; ++i) { + blsPublicKey[i] = input[i + index]; + } + validation.blsPublicKey = blsPublicKey; + index += 48; + } + + // Unpack the registration expiry + { + uint64 expiry; + for (uint256 i; i < 8; ++i) { + expiry |= uint64(uint8(input[i + index])) << uint64((8 * (7 - i))); + } + validation.registrationExpiry = expiry; + index += 8; + } + + // Unpack the remainingBalanceOwner threshold + uint32 remainingBalanceOwnerAddressesLength; + { + uint32 remainingBalanceOwnerThreshold; + for (uint256 i; i < 4; ++i) { + remainingBalanceOwnerThreshold |= + uint32(uint8(input[i + index])) << uint32((8 * (3 - i))); + } + index += 4; + + // Unpack the remainingBalanceOwner addresses length + for (uint256 i; i < 4; ++i) { + remainingBalanceOwnerAddressesLength |= + uint32(uint8(input[i + index])) << uint32((8 * (3 - i))); + } + index += 4; + + // Unpack the remainingBalanceOwner addresses + address[] memory remainingBalanceOwnerAddresses = + new address[](remainingBalanceOwnerAddressesLength); + for (uint256 i; i < remainingBalanceOwnerAddressesLength; ++i) { + bytes memory addrBytes = new bytes(20); + for (uint256 j; j < 20; ++j) { + addrBytes[j] = input[j + index]; + } + address addr; + // solhint-disable-next-line no-inline-assembly + assembly { + addr := mload(add(addrBytes, 20)) + } + remainingBalanceOwnerAddresses[i] = addr; + index += 20; + } + validation.remainingBalanceOwner = PChainOwner({ + threshold: remainingBalanceOwnerThreshold, + addresses: remainingBalanceOwnerAddresses + }); + } + + // Unpack the disableOwner threshold + uint32 disableOwnerAddressesLength; + { + uint32 disableOwnerThreshold; + for (uint256 i; i < 4; ++i) { + disableOwnerThreshold |= uint32(uint8(input[i + index])) << uint32((8 * (3 - i))); + } + index += 4; + + // Unpack the disableOwner addresses length + for (uint256 i; i < 4; ++i) { + disableOwnerAddressesLength |= + uint32(uint8(input[i + index])) << uint32((8 * (3 - i))); + } + index += 4; + + // Unpack the disableOwner addresses + address[] memory disableOwnerAddresses = new address[](disableOwnerAddressesLength); + for (uint256 i; i < disableOwnerAddressesLength; ++i) { + bytes memory addrBytes = new bytes(20); + for (uint256 j; j < 20; ++j) { + addrBytes[j] = input[j + index]; + } + address addr; + // solhint-disable-next-line no-inline-assembly + assembly { + addr := mload(add(addrBytes, 20)) + } + disableOwnerAddresses[i] = addr; + index += 20; + } + validation.disableOwner = + PChainOwner({threshold: disableOwnerThreshold, addresses: disableOwnerAddresses}); + } + // Now that we have all the variable lengths, validate the input length + uint32 expectedLength = 122 + nodeIDLength + + (remainingBalanceOwnerAddressesLength + disableOwnerAddressesLength) * 20; + if (input.length != expectedLength) { + revert InvalidMessageLength(uint32(input.length), expectedLength); + } + // Unpack the weight + { + uint64 weight; + for (uint256 i; i < 8; ++i) { + weight |= uint64(uint8(input[i + index])) << uint64((8 * (7 - i))); + } + validation.weight = weight; + } + + return validation; + } + + /** + * @notice Packs a SubnetValidatorRegistrationMessage into a byte array. + * The message format specification is: + * +--------------+----------+----------+ + * | codecID : uint16 | 2 bytes | + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | valid : bool | 1 byte | + * +--------------+----------+----------+ + * | 39 bytes | + * +----------+ + * + * @param validationID The ID of the validation period. + * @param valid true if the validation period was registered, false if it was not and never will be. + * @return The packed message. + * + */ + function packSubnetValidatorRegistrationMessage( + bytes32 validationID, + bool valid + ) internal pure returns (bytes memory) { + return abi.encodePacked( + CODEC_ID, SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, validationID, valid + ); + } + + /** + * @notice Unpacks a byte array as a SubnetValidatorRegistrationMessage message. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The validationID and whether the validation period was registered or is not a + * validator and never will be a validator due to the expiry time passing. + */ + function unpackSubnetValidatorRegistrationMessage(bytes memory input) + internal + pure + returns (bytes32, bool) + { + if (input.length != 39) { + revert InvalidMessageLength(uint32(input.length), 39); + } + // Unpack the codec ID + uint16 codecID; + for (uint256 i; i < 2; ++i) { + codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); + } + if (codecID != CODEC_ID) { + revert InvalidCodecID(codecID); + } + + // Unpack the type ID + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); + } + if (typeID != SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID) { + revert InvalidMessageType(); + } + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); + } + + // Unpack the validity + bool valid = input[38] != 0; + + return (validationID, valid); + } + + /** + * @notice Packs a SubnetValidatorWeightMessage message into a byte array. + * The message format specification is: + * +--------------+----------+----------+ + * | codecID : uint16 | 2 bytes | + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | nonce : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | weight : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | 54 bytes | + * +----------+ + * + * @param validationID The ID of the validation period. + * @param nonce The nonce of the validation ID. + * @param weight The new weight of the validator. + * @return The packed message. + */ + function packSubnetValidatorWeightMessage( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) internal pure returns (bytes memory) { + return abi.encodePacked( + CODEC_ID, SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight + ); + } + + /** + * @notice Unpacks a byte array as a SubnetValidatorWeight message. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The validationID, nonce, and weight. + */ + function unpackSubnetValidatorWeightMessage(bytes memory input) + internal + pure + returns (bytes32, uint64, uint64) + { + if (input.length != 54) { + revert InvalidMessageLength(uint32(input.length), 54); + } + + // Unpack the codec ID. + uint16 codecID; + for (uint256 i; i < 2; ++i) { + codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); + } + if (codecID != CODEC_ID) { + revert InvalidCodecID(codecID); + } + + // Unpack the type ID. + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); + } + if (typeID != SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID) { + revert InvalidMessageType(); + } + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); + } + + // Unpack the nonce. + uint64 nonce; + for (uint256 i; i < 8; ++i) { + nonce |= uint64(uint8(input[i + 38])) << uint64((8 * (7 - i))); + } + + // Unpack the weight. + uint64 weight; + for (uint256 i; i < 8; ++i) { + weight |= uint64(uint8(input[i + 46])) << uint64((8 * (7 - i))); + } + + return (validationID, nonce, weight); + } + + /** + * @notice Packs a ValidationUptimeMessage into a byte array. + * The message format specification is: + * +--------------+----------+----------+ + * | codecID : uint16 | 2 bytes | + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | uptime : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | 46 bytes | + * +----------+ + * + * @param validationID The ID of the validation period. + * @param uptime The uptime of the validator. + * @return The packed message. + */ + function packValidationUptimeMessage( + bytes32 validationID, + uint64 uptime + ) internal pure returns (bytes memory) { + return abi.encodePacked(CODEC_ID, VALIDATION_UPTIME_MESSAGE_TYPE_ID, validationID, uptime); + } + + /** + * @notice Unpacks a byte array as a ValidationUptimeMessage. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The validationID and uptime. + */ + function unpackValidationUptimeMessage(bytes memory input) + internal + pure + returns (bytes32, uint64) + { + if (input.length != 46) { + revert InvalidMessageLength(uint32(input.length), 46); + } + + // Unpack the codec ID. + uint16 codecID; + for (uint256 i; i < 2; ++i) { + codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); + } + if (codecID != CODEC_ID) { + revert InvalidCodecID(codecID); + } + + // Unpack the type ID. + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); + } + if (typeID != VALIDATION_UPTIME_MESSAGE_TYPE_ID) { + revert InvalidMessageType(); + } + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); + } + + // Unpack the uptime. + uint64 uptime; + for (uint256 i; i < 8; ++i) { + uptime |= uint64(uint8(input[i + 38])) << uint64((8 * (7 - i))); + } + + return (validationID, uptime); + } +} diff --git a/contracts/validator-manager/interfaces/IERC20Mintable.sol b/contracts/validator-manager/interfaces/IERC20Mintable.sol new file mode 100644 index 000000000..f3524de3e --- /dev/null +++ b/contracts/validator-manager/interfaces/IERC20Mintable.sol @@ -0,0 +1,21 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {IERC20} from "@openzeppelin/contracts@5.0.2/token/ERC20/IERC20.sol"; + +/** + * @notice Extension of the ERC20 standard that allows for minting new tokens. + */ +interface IERC20Mintable is IERC20 { + /** + * @notice Mint tokens to the specified address. + * @param account The address to mint tokens to. + * @param amount How many tokens to mint. + * @dev This function should have appropriate user controls to ensure that only authorized users can mint. + */ + function mint(address account, uint256 amount) external; +} diff --git a/contracts/validator-manager/interfaces/IERC20TokenStakingManager.sol b/contracts/validator-manager/interfaces/IERC20TokenStakingManager.sol new file mode 100644 index 000000000..eb1b56a32 --- /dev/null +++ b/contracts/validator-manager/interfaces/IERC20TokenStakingManager.sol @@ -0,0 +1,38 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {ValidatorRegistrationInput} from "./IValidatorManager.sol"; +import {IPoSValidatorManager} from "./IPoSValidatorManager.sol"; + +/** + * Proof of Stake Validator Manager that stakes ERC20 tokens. + */ +interface IERC20TokenStakingManager is IPoSValidatorManager { + /** + * @notice Begins the validator registration process. Locks the specified ERC20 tokens in the contract as the stake. + * @param registrationInput The inputs for a validator registration. + * @param delegationFeeBips The fee that delegators must pay to delegate to this validator. + * @param minStakeDuration The minimum amount of time this validator must be staked for in seconds. + * @param stakeAmount The amount of tokens to stake. + */ + function initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration, + uint256 stakeAmount + ) external returns (bytes32 validationID); + + /** + * @notice Begins the delegator registration process. Locks the specified ERC20 tokens in the contract as the stake. + * @param validationID The ID of the validator to stake to. + * @param stakeAmount The amount of tokens to stake. + */ + function initializeDelegatorRegistration( + bytes32 validationID, + uint256 stakeAmount + ) external returns (bytes32); +} diff --git a/contracts/validator-manager/interfaces/INativeTokenStakingManager.sol b/contracts/validator-manager/interfaces/INativeTokenStakingManager.sol new file mode 100644 index 000000000..c1cc4a2c9 --- /dev/null +++ b/contracts/validator-manager/interfaces/INativeTokenStakingManager.sol @@ -0,0 +1,35 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {ValidatorRegistrationInput} from "./IValidatorManager.sol"; +import {IPoSValidatorManager} from "./IPoSValidatorManager.sol"; + +/** + * Proof of Stake Validator Manager that stakes the blockchain's native tokens. + */ +interface INativeTokenStakingManager is IPoSValidatorManager { + /** + * @notice Begins the validator registration process. Locks the provided native asset in the contract as the stake. + * @param registrationInput The inputs for a validator registration. + * @param delegationFeeBips The fee that delegators must pay to delegate to this validator. + * @param minStakeDuration The minimum amount of time this validator must be staked for in seconds. + */ + function initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration + ) external payable returns (bytes32 validationID); + + /** + * @notice Begins the delegator registration process. Locks the provided native asset in the contract as the stake. + * @param validationID The ID of the validator to stake to. + */ + function initializeDelegatorRegistration(bytes32 validationID) + external + payable + returns (bytes32); +} diff --git a/contracts/validator-manager/interfaces/IPoAValidatorManager.sol b/contracts/validator-manager/interfaces/IPoAValidatorManager.sol new file mode 100644 index 000000000..94c1663d3 --- /dev/null +++ b/contracts/validator-manager/interfaces/IPoAValidatorManager.sol @@ -0,0 +1,30 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {IValidatorManager, ValidatorRegistrationInput} from "./IValidatorManager.sol"; + +/** + * @notice Interface for Proof of Authority Validator Manager contracts + */ +interface IPoAValidatorManager is IValidatorManager { + /** + * @notice Begins the validator registration process, and sets the {weight} of the validator. + * @param registrationInput The inputs for a validator registration. + * @param weight The weight of the validator being registered. + */ + function initializeValidatorRegistration( + ValidatorRegistrationInput calldata registrationInput, + uint64 weight + ) external returns (bytes32 validationID); + + /** + * @notice Begins the process of ending an active validation period. The validation period must have been previously + * started by a successful call to {completeValidatorRegistration} with the given validationID. + * @param validationID The ID of the validation period being ended. + */ + function initializeEndValidation(bytes32 validationID) external; +} diff --git a/contracts/validator-manager/interfaces/IPoSValidatorManager.sol b/contracts/validator-manager/interfaces/IPoSValidatorManager.sol new file mode 100644 index 000000000..fc0a77d6c --- /dev/null +++ b/contracts/validator-manager/interfaces/IPoSValidatorManager.sol @@ -0,0 +1,238 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {IValidatorManager, ValidatorManagerSettings} from "./IValidatorManager.sol"; +import {IRewardCalculator} from "./IRewardCalculator.sol"; + +/** + * @dev Delegator status + */ +enum DelegatorStatus { + Unknown, + PendingAdded, + Active, + PendingRemoved +} + +/** + * @dev PoS Validator Manager settings, used to initialize the PoS Validator Manager + */ +struct PoSValidatorManagerSettings { + ValidatorManagerSettings baseSettings; + uint256 minimumStakeAmount; + uint256 maximumStakeAmount; + uint64 minimumStakeDuration; + uint16 minimumDelegationFeeBips; + uint8 maximumStakeMultiplier; + uint256 weightToValueFactor; + IRewardCalculator rewardCalculator; +} + +/** + * @dev Contains the active state of a Delegator + */ +struct Delegator { + DelegatorStatus status; + address owner; + bytes32 validationID; + uint64 weight; + uint64 startedAt; + uint64 startingNonce; + uint64 endingNonce; +} + +/** + * @dev Describes the active state of a PoS Validator in addition the information in {IValidatorManager-Validator} + */ +struct PoSValidatorInfo { + address owner; + uint16 delegationFeeBips; + uint64 minStakeDuration; + uint64 uptimeSeconds; +} + +/** + * @notice Interface for Proof of Stake Validator Managers + */ +interface IPoSValidatorManager is IValidatorManager { + /** + * @notice Event emitted when a delegator registration is initiated + * @param delegationID The ID of the delegation + * @param validationID The ID of the validation period being delegated to + * @param delegatorAddress The address of the delegator + * @param nonce The message nonce used to update the validator weight + * @param validatorWeight The updated validator weight that is sent to the P-Chain + * @param delegatorWeight The weight of the delegator + * @param setWeightMessageID The ID of the Warp message that updates the validator's weight on the P-Chain + */ + event DelegatorAdded( + bytes32 indexed delegationID, + bytes32 indexed validationID, + address indexed delegatorAddress, + uint64 nonce, + uint64 validatorWeight, + uint64 delegatorWeight, + bytes32 setWeightMessageID + ); + + /** + * @notice Event emitted when a delegator registration is completed + * @param delegationID The ID of the delegation + * @param validationID The ID of the validation period + * @param startTime The time at which the registration was completed + */ + event DelegatorRegistered( + bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime + ); + + /** + * @notice Event emitted when delegator removal is initiated + * @param delegationID The ID of the delegation + * @param validationID The ID of the validation period the delegator was staked to + */ + event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID); + + /** + * @notice Event emitted when delegator removal is completed + * @param delegationID The ID of the delegation + * @param validationID The ID of the validator the delegator was staked to + * @param rewards The rewards given to the delegator + * @param fees The portion of the delegator's rewards paid to the validator + */ + event DelegationEnded( + bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees + ); + + /** + * @notice Event emitted when the uptime of a validator is updated. Only emitted when the uptime is greater than the stored uptime. + * @param validationID The ID of the validation period + * @param uptime The updated uptime of the validator + */ + event UptimeUpdated(bytes32 indexed validationID, uint64 uptime); + + /** + * @notice Updates the uptime of the validationID if the submitted proof is greated than the stored uptime. + * Anybody may call this function to ensure the stored uptime is accurate. Callable only when the validation period is active. + * @param validationID The ID of the validation period + * @param messageIndex The index of the Warp message to be received providing the uptime proof + */ + function submitUptimeProof(bytes32 validationID, uint32 messageIndex) external; + + /** + * @notice Begins the process of ending an active validation period, and reverts if the validation period is not eligible + * for uptime-based rewards. This function is used to exit the validator set when rewards are expected. + * The validation period must have been previously started by a successful call to {completeValidatorRegistration} with the given validationID. + * Any rewards for this validation period will stop accruing when this function is called. + * Note: Reverts if the uptime is not eligible for rewards. + * @param validationID The ID of the validation period being ended. + * @param includeUptimeProof Whether or not an uptime proof is provided for the validation period. If no uptime proof is provided, + * the latest known uptime will be used. + * @param messageIndex The index of the Warp message to be received providing the uptime proof. + */ + function initializeEndValidation( + bytes32 validationID, + bool includeUptimeProof, + uint32 messageIndex + ) external; + + /** + * @notice Begins the process of ending an active validation period, but does not revert if the latest known uptime + * is not sufficient to collect uptime-based rewards. This function is used to exit the validator set when rewards are + * not expected. + * The validation period must have been previously started by a successful call to {completeValidatorRegistration} with the given validationID. + * Any rewards for this validation period will stop accruing when this function is called. + * @param validationID The ID of the validation period being ended. + * @param includeUptimeProof Whether or not an uptime proof is provided for the validation period. If no uptime proof is provided, + * the latest known uptime will be used. + * @param messageIndex The index of the Warp message to be received providing the uptime proof. + */ + function forceInitializeEndValidation( + bytes32 validationID, + bool includeUptimeProof, + uint32 messageIndex + ) external; + + /** + * @notice Completes the delegator registration process by submitting an acknowledgement of the registration of a + * validationID from the P-Chain. After this function is called, the validator's weight is updated in the contract state. + * Any P-Chain acknowledgement with a nonce greater than or equal to the nonce used to initialize registration of the + * delegator is valid, as long as that nonce has been sent by the contract. For the purposes of computing delegation rewards, + * the delegation is considered active after this function is completed. + * Note: Only the specified delegation will be marked as registered, even if the validator weight update + * message implicitly includes multiple weight changes. + * @param messageIndex The index of the Warp message to be received providing the acknowledgement. + * @param delegationID The ID of the delegation being registered. + */ + function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) external; + + /** + * @notice Begins the process of removing a delegator from a validation period, and reverts if the delegation is not eligible for rewards. + * The delegator must have been previously registered with the given validationID. For the purposes of computing delegation rewards, + * the delegation period is considered ended when this function is called. Uses the supplied uptime proof to calculate rewards. + * If none is provided in the call, the latest known uptime will be used. Reverts if the uptime is not eligible for rewards. + * Note: This function can only be called by the address that registered the delegation. + * Note: Reverts if the uptime is not eligible for rewards. + * @param delegationID The ID of the delegation being removed. + * @param includeUptimeProof Whether or not an uptime proof is provided for the validation period. + * If the validator has completed its validation period, it has already provided an uptime proof, so {includeUptimeProof} + * will be ignored and can be set to false. If the validator has not completed its validation period and no uptime proof + * is provided, the latest known uptime will be used. + * @param messageIndex If {includeUptimeProof} is true, the index of the Warp message to be received providing the + * uptime proof. + */ + function initializeEndDelegation( + bytes32 delegationID, + bool includeUptimeProof, + uint32 messageIndex + ) external; + + /** + * @notice Begins the process of removing a delegator from a validation period, but does not revert if the delegation is not eligible for rewards. + * The delegator must have been previously registered with the given validationID. For the purposes of computing delegation rewards, + * the delegation period is considered ended when this function is called. Uses the supplied uptime proof to calculate rewards. + * If none is provided in the call, the latest known uptime will be used. Reverts if the uptime is not eligible for rewards. + * Note: This function can only be called by the address that registered the delegation. + * @param delegationID The ID of the delegation being removed. + * @param includeUptimeProof Whether or not an uptime proof is provided for the validation period. + * If the validator has completed its validation period, it has already provided an uptime proof, so {includeUptimeProof} + * will be ignored and can be set to false. If the validator has not completed its validation period and no uptime proof + * is provided, the latest known uptime will be used. + * @param messageIndex If {includeUptimeProof} is true, the index of the Warp message to be received providing the + * uptime proof. + */ + function forceInitializeEndDelegation( + bytes32 delegationID, + bool includeUptimeProof, + uint32 messageIndex + ) external; + + /** + * @notice Resubmits a delegator registration or delegator end message to be sent to the P-Chain. + * Only necessary if the original message can't be delivered due to validator churn. + * @param delegationID The ID of the delegation. + */ + function resendUpdateDelegation(bytes32 delegationID) external; + + /** + * @notice Completes the process of ending a delegation by receiving an acknowledgement from the P-Chain. + * After this function is called, the validator's weight is updated in the contract state. + * Any P-Chain acknowledgement with a nonce greater than or equal to the nonce used to initialize the end of the + * delegator's delegation is valid, as long as that nonce has been sent by the contract. This is because the validator + * weight change pertaining to the delegation ending is included in any subsequent validator weight update messages. + * Note: Only the specified delegation will be marked as completed, even if the validator weight update + * message implicitly includes multiple weight changes. + * @param messageIndex The index of the Warp message to be received providing the acknowledgement. + * @param delegationID The ID of the delegation being removed. + */ + function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) external; + + /** + * @notice Withdraws the delegation fees from completed delegations to the owner of the validator. + * @param validationID The ID of the validation period being ended. + */ + function claimDelegationFees(bytes32 validationID) external; +} diff --git a/contracts/validator-manager/interfaces/IRewardCalculator.sol b/contracts/validator-manager/interfaces/IRewardCalculator.sol new file mode 100644 index 000000000..e8c556e25 --- /dev/null +++ b/contracts/validator-manager/interfaces/IRewardCalculator.sol @@ -0,0 +1,27 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +/** + * @notice Interface for Validation and Delegation reward calculators + */ +interface IRewardCalculator { + /** + * @notice Calculate the reward for a staker (validator or delegator) + * @param stakeAmount The amount of tokens staked + * @param validatorStartTime The time the validator started validating + * @param stakingStartTime The time the staker started staking + * @param stakingEndTime The time the staker stopped staking + * @param uptimeSeconds The total time the validator was validating + */ + function calculateReward( + uint256 stakeAmount, + uint64 validatorStartTime, + uint64 stakingStartTime, + uint64 stakingEndTime, + uint64 uptimeSeconds + ) external view returns (uint256); +} diff --git a/contracts/validator-manager/interfaces/IValidatorManager.sol b/contracts/validator-manager/interfaces/IValidatorManager.sol new file mode 100644 index 000000000..1c2ae4ee4 --- /dev/null +++ b/contracts/validator-manager/interfaces/IValidatorManager.sol @@ -0,0 +1,213 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +/** + * @dev Validator status + */ +enum ValidatorStatus { + Unknown, + PendingAdded, + Active, + PendingRemoved, + Completed, + Invalidated +} + +/** + * @dev Specifies the owner of a validator's remaining balance or disable owner on the P-Chain. + * P-Chain addresses are also 20-bytes, so we use the address type to represent them. + */ +struct PChainOwner { + uint32 threshold; + address[] addresses; +} + +/** + * @dev Contains the active state of a Validator + */ +struct Validator { + ValidatorStatus status; + bytes nodeID; + uint64 startingWeight; + uint64 messageNonce; + uint64 weight; + uint64 startedAt; + uint64 endedAt; +} + +/** + * @dev Describes the current churn period + */ +struct ValidatorChurnPeriod { + uint256 startedAt; + uint256 initialWeight; + uint256 totalWeight; + uint64 churnAmount; +} + +/** + * @dev Validator Manager settings, used to initialize the Validator Manager + */ +struct ValidatorManagerSettings { + bytes32 subnetID; + uint64 churnPeriodSeconds; + uint8 maximumChurnPercentage; +} + +/** + * @dev Description of the subnet conversion data used to convert + * a subnet to a permissionless subnet on the P-Chain. + * This data is the pre-image of a hash that is authenticated by the P-Chain + * and verified by the Validator Manager. + */ +struct SubnetConversionData { + bytes32 subnetID; + bytes32 validatorManagerBlockchainID; + address validatorManagerAddress; + InitialValidator[] initialValidators; +} + +/** + * @dev Specifies an initial validator, used in the subnet conversion data. + */ +struct InitialValidator { + bytes nodeID; + bytes blsPublicKey; + uint64 weight; +} + +/** + * @dev Specifies a validator to register. + */ +struct ValidatorRegistrationInput { + bytes nodeID; + bytes blsPublicKey; + uint64 registrationExpiry; + PChainOwner remainingBalanceOwner; + PChainOwner disableOwner; +} + +/** + * @notice Interface for Validator Manager contracts that implement Subnet-only Validator management. + */ +interface IValidatorManager { + /** + * @notice Emitted when a new validation period is created by locking stake in the manager contract. + * Note: This event does not mean that the validation period has been successfully registered on the P-Chain, + * and rewards for this validation period will not begin accruing until the {ValidationPeriodRegistered} event is + * emitted. + * @param validationID The ID of the validation period being created. + * @param nodeID The node ID of the validator being registered. + * @param registerValidationMessageID The ID of the Warp message that will be sent to the P-Chain to register the + * validation period. + * @param weight The weight of the validator being registered. + * @param registrationExpiry The Unix timestamp after which the reigistration is no longer valid on the P-Chain. + */ + event ValidationPeriodCreated( + bytes32 indexed validationID, + bytes indexed nodeID, + bytes32 indexed registerValidationMessageID, + uint256 weight, + uint64 registrationExpiry + ); + + event InitialValidatorCreated( + bytes32 indexed validationID, bytes indexed nodeID, uint256 weight + ); + + /** + * @notice Emitted when the staking manager learns that the validation period has been successfully registered + * on the P-Chain. Rewards for this validation period will begin accruing when this event is emitted. + * @param validationID The ID of the validation period being registered. + * @param weight The weight of the validator being registered. + * @param timestamp The time at which the validation period was registered with the contract. + */ + event ValidationPeriodRegistered( + bytes32 indexed validationID, uint256 weight, uint256 timestamp + ); + + /** + * @notice Emitted when the process of ending a registered validation period is started by calling + * {initializeEndValidation}. + * Note: The stake for this validation period remains locked until a {ValidationPeriodRemoved} event is emitted. + * @param validationID The ID of the validation period being removed. + * @param setWeightMessageID The ID of the Warp message that updates the validator's weight on the P-Chain. + * @param weight The weight of the validator being removed. + * @param endTime The time at which the removal was initiated. + */ + event ValidatorRemovalInitialized( + bytes32 indexed validationID, + bytes32 indexed setWeightMessageID, + uint256 weight, + uint256 endTime + ); + + /** + * @notice Emitted when the stake for a validation period is unlocked and returned to the staker. + * This is done by calling {completeEndValidation}, which provides proof from the P-Chain that the + * validation period is not active and will never be active in the future. + * @param validationID The ID of the validation period being removed. + */ + event ValidationPeriodEnded(bytes32 indexed validationID, ValidatorStatus indexed status); + + /** + * @notice Event emitted when validator weight is updated. + * @param validationID The ID of the validation period being updated + * @param nonce The message nonce used to update the validator weight + * @param validatorWeight The updated validator weight that is sent to the P-Chain + * @param setWeightMessageID The ID of the Warp message that updates the validator's weight on the P-Chain + */ + event ValidatorWeightUpdate( + bytes32 indexed validationID, + uint64 indexed nonce, + uint64 validatorWeight, + bytes32 setWeightMessageID + ); + + /** + * @notice Verifies and sets the initial validator set for the chain through a P-Chain + * SubnetConversionMessage. + * @param subnetConversionData The subnet conversion message data used to recompute and verify against the subnetConversionID. + * @param messsageIndex The index that contains the SubnetConversionMessage Warp message containing the subnetConversionID to be verified against the provided {subnetConversionData} + */ + function initializeValidatorSet( + SubnetConversionData calldata subnetConversionData, + uint32 messsageIndex + ) external; + + /** + * @notice Resubmits a validator registration message to be sent to the P-Chain. + * Only necessary if the original message can't be delivered due to validator churn. + * @param validationID The ID of the validation period being registered. + */ + function resendRegisterValidatorMessage(bytes32 validationID) external; + + /** + * @notice Completes the validator registration process by returning an acknowledgement of the registration of a + * validationID from the P-Chain. + * @param messageIndex The index of the Warp message to be received providing the acknowledgement. + */ + function completeValidatorRegistration(uint32 messageIndex) external; + + /** + * @notice Resubmits a validator end message to be sent to the P-Chain. + * Only necessary if the original message can't be delivered due to validator churn. + * @param validationID The ID of the validation period being ended. + */ + function resendEndValidatorMessage(bytes32 validationID) external; + + /** + * @notice Completes the process of ending a validation period by receiving an acknowledgement from the P-Chain + * that the validation ID is not active and will never be active in the future. Returns the the stake associated + * with the validation. + * Note: This function can be used for successful validation periods that have been explicitly ended by calling + * {initializeEndValidation} or for validation periods that never began on the P-Chain due to the {registrationExpiry} being reached. + * @param messageIndex The index of the Warp message to be received providing the proof the validation is not active + * and never will be active on the P-Chain. + */ + function completeEndValidation(uint32 messageIndex) external; +} diff --git a/contracts/validator-manager/tests/ERC20TokenStakingManagerTests.t.sol b/contracts/validator-manager/tests/ERC20TokenStakingManagerTests.t.sol new file mode 100644 index 000000000..a96100814 --- /dev/null +++ b/contracts/validator-manager/tests/ERC20TokenStakingManagerTests.t.sol @@ -0,0 +1,331 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {PoSValidatorManagerTest} from "./PoSValidatorManagerTests.t.sol"; +import {ERC20TokenStakingManager} from "../ERC20TokenStakingManager.sol"; +import {PoSValidatorManager} from "../PoSValidatorManager.sol"; +import {ExampleRewardCalculator} from "../ExampleRewardCalculator.sol"; +import { + ValidatorManagerSettings, + ValidatorRegistrationInput, + IValidatorManager +} from "../interfaces/IValidatorManager.sol"; +import {PoSValidatorManagerSettings} from "../interfaces/IPoSValidatorManager.sol"; +import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; +import {ICMInitializable} from "../../utilities/ICMInitializable.sol"; +import {ExampleERC20} from "@mocks/ExampleERC20.sol"; +import {IERC20} from "@openzeppelin/contracts@5.0.2/token/ERC20/IERC20.sol"; +import {IERC20Mintable} from "../interfaces/IERC20Mintable.sol"; +import {SafeERC20} from "@openzeppelin/contracts@5.0.2/token/ERC20/utils/SafeERC20.sol"; +import {ValidatorManagerTest} from "./ValidatorManagerTests.t.sol"; + +contract ERC20TokenStakingManagerTest is PoSValidatorManagerTest { + using SafeERC20 for IERC20Mintable; + + ERC20TokenStakingManager public app; + IERC20Mintable public token; + + function setUp() public override { + ValidatorManagerTest.setUp(); + + _setUp(); + _mockGetBlockchainID(); + _mockInitializeValidatorSet(); + app.initializeValidatorSet(_defaultSubnetConversionData(), 0); + } + + function testZeroMinimumDelegationFee() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.InvalidDelegationFee.selector, 0) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: 0, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testMaxMinimumDelegationFee() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + uint16 minimumDelegationFeeBips = app.MAXIMUM_DELEGATION_FEE_BIPS() + 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidDelegationFee.selector, minimumDelegationFeeBips + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: minimumDelegationFeeBips, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testInvalidStakeAmountRange() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidStakeAmount.selector, DEFAULT_MAXIMUM_STAKE_AMOUNT + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testZeroMaxStakeMultiplier() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.InvalidStakeMultiplier.selector, 0) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: 0, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testMinStakeDurationTooLow() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + uint64 minStakeDuration = DEFAULT_CHURN_PERIOD - 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidMinStakeDuration.selector, minStakeDuration + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: minStakeDuration, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testMaxStakeMultiplierOverLimit() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + uint8 maximumStakeMultiplier = app.MAXIMUM_STAKE_MULTIPLIER_LIMIT() + 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidStakeMultiplier.selector, maximumStakeMultiplier + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: maximumStakeMultiplier, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testZeroWeightToValueFactor() public { + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.ZeroWeightToValueFactor.selector) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: 0, + rewardCalculator: IRewardCalculator(address(0)) + }), + token + ); + } + + function testInvalidValidatorMinStakeDuration() public { + ValidatorRegistrationInput memory input = ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }); + uint256 stakeAmount = _weightToValue(DEFAULT_WEIGHT); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidMinStakeDuration.selector, + DEFAULT_MINIMUM_STAKE_DURATION - 1 + ) + ); + app.initializeValidatorRegistration( + input, DEFAULT_DELEGATION_FEE_BIPS, DEFAULT_MINIMUM_STAKE_DURATION - 1, stakeAmount + ); + } + + function testERC20TokenStakingManagerStorageSlot() public view { + assertEq( + _erc7201StorageSlot("ERC20TokenStakingManager"), + app.ERC20_STAKING_MANAGER_STORAGE_LOCATION() + ); + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration, + uint256 stakeAmount + ) internal virtual override returns (bytes32) { + return app.initializeValidatorRegistration( + registrationInput, delegationFeeBips, minStakeDuration, stakeAmount + ); + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory input, + uint64 weight + ) internal virtual override returns (bytes32) { + return app.initializeValidatorRegistration( + input, + DEFAULT_DELEGATION_FEE_BIPS, + DEFAULT_MINIMUM_STAKE_DURATION, + _weightToValue(weight) + ); + } + + function _initializeDelegatorRegistration( + bytes32 validationID, + address delegatorAddress, + uint64 weight + ) internal virtual override returns (bytes32) { + uint256 value = _weightToValue(weight); + vm.startPrank(delegatorAddress); + bytes32 delegationID = app.initializeDelegatorRegistration(validationID, value); + vm.stopPrank(); + return delegationID; + } + + function _beforeSend(uint256 amount, address spender) internal override { + token.safeIncreaseAllowance(spender, amount); + token.safeTransfer(spender, amount); + + // ERC20 tokens need to be pre-approved + vm.startPrank(spender); + token.safeIncreaseAllowance(address(app), amount); + vm.stopPrank(); + } + + function _expectStakeUnlock(address account, uint256 amount) internal override { + vm.expectCall(address(token), abi.encodeCall(IERC20.transfer, (account, amount))); + } + + function _expectRewardIssuance(address account, uint256 amount) internal override { + vm.expectCall(address(token), abi.encodeCall(IERC20Mintable.mint, (account, amount))); + } + + function _setUp() internal override returns (IValidatorManager) { + // Construct the object under test + app = new ERC20TokenStakingManager(ICMInitializable.Allowed); + token = new ExampleERC20(); + rewardCalculator = new ExampleRewardCalculator(DEFAULT_REWARD_RATE); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: rewardCalculator + }), + token + ); + validatorManager = app; + posValidatorManager = app; + + return app; + } + + function _getStakeAssetBalance(address account) internal view override returns (uint256) { + return token.balanceOf(account); + } +} diff --git a/contracts/validator-manager/tests/ExamplesRewardCalculatorTests.t.sol b/contracts/validator-manager/tests/ExamplesRewardCalculatorTests.t.sol new file mode 100644 index 000000000..dc59a6409 --- /dev/null +++ b/contracts/validator-manager/tests/ExamplesRewardCalculatorTests.t.sol @@ -0,0 +1,46 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {ExampleRewardCalculator} from "../ExampleRewardCalculator.sol"; +import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; + +contract ExampleRewardCalculatorTest is Test { + IRewardCalculator public exampleRewardCalculator; + + uint256 public constant DEFAULT_STAKE_AMOUNT = 1e12; + uint64 public constant DEFAULT_START_TIME = 1000; + uint64 public constant DEFAULT_END_TIME = 31537000; // a year + 1000 seonds + uint64 public constant DEFAULT_UPTIME = (DEFAULT_END_TIME - DEFAULT_START_TIME) * 80 / 100; + uint64 public constant DEFAULT_REWARD_BASIS_POINTS = 42; + + function setUp() public { + exampleRewardCalculator = new ExampleRewardCalculator(DEFAULT_REWARD_BASIS_POINTS); + } + + function testRewardCalculation() public view { + uint256 output = exampleRewardCalculator.calculateReward({ + stakeAmount: DEFAULT_STAKE_AMOUNT, + validatorStartTime: DEFAULT_START_TIME, + stakingStartTime: DEFAULT_START_TIME, + stakingEndTime: DEFAULT_END_TIME, + uptimeSeconds: DEFAULT_UPTIME + }); + assertEq(output, 42e8); + } + + function testInsufficientUptime() public view { + uint256 output = exampleRewardCalculator.calculateReward({ + stakeAmount: DEFAULT_STAKE_AMOUNT, + validatorStartTime: DEFAULT_START_TIME, + stakingStartTime: DEFAULT_START_TIME, + stakingEndTime: DEFAULT_END_TIME, + uptimeSeconds: DEFAULT_UPTIME - 1 + }); + assertEq(output, 0); + } +} diff --git a/contracts/validator-manager/tests/NativeTokenStakingManagerTests.t.sol b/contracts/validator-manager/tests/NativeTokenStakingManagerTests.t.sol new file mode 100644 index 000000000..adbfb79bb --- /dev/null +++ b/contracts/validator-manager/tests/NativeTokenStakingManagerTests.t.sol @@ -0,0 +1,296 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {PoSValidatorManagerTest} from "./PoSValidatorManagerTests.t.sol"; +import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; +import {PoSValidatorManager} from "../PoSValidatorManager.sol"; +import { + ValidatorManagerSettings, + ValidatorRegistrationInput, + IValidatorManager +} from "../interfaces/IValidatorManager.sol"; +import {PoSValidatorManagerSettings} from "../interfaces/IPoSValidatorManager.sol"; +import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; +import {ExampleRewardCalculator} from "../ExampleRewardCalculator.sol"; +import {ICMInitializable} from "../../utilities/ICMInitializable.sol"; +import {INativeMinter} from + "@avalabs/subnet-evm-contracts@1.2.0/contracts/interfaces/INativeMinter.sol"; +import {ValidatorManagerTest} from "./ValidatorManagerTests.t.sol"; + +contract NativeTokenStakingManagerTest is PoSValidatorManagerTest { + NativeTokenStakingManager public app; + + function setUp() public override { + ValidatorManagerTest.setUp(); + + _setUp(); + _mockGetBlockchainID(); + _mockInitializeValidatorSet(); + app.initializeValidatorSet(_defaultSubnetConversionData(), 0); + } + + function testZeroMinimumDelegationFee() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.InvalidDelegationFee.selector, 0) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: 0, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testMaxMinimumDelegationFee() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + uint16 minimumDelegationFeeBips = app.MAXIMUM_DELEGATION_FEE_BIPS() + 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidDelegationFee.selector, minimumDelegationFeeBips + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: minimumDelegationFeeBips, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testInvalidStakeAmountRange() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidStakeAmount.selector, DEFAULT_MAXIMUM_STAKE_AMOUNT + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testZeroMaxStakeMultiplier() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.InvalidStakeMultiplier.selector, 0) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: 0, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testMaxStakeMultiplierOverLimit() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + uint8 maximumStakeMultiplier = app.MAXIMUM_STAKE_MULTIPLIER_LIMIT() + 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidStakeMultiplier.selector, maximumStakeMultiplier + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: maximumStakeMultiplier, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testZeroWeightToValueFactor() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.ZeroWeightToValueFactor.selector) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: 0, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testMinStakeDurationTooLow() public { + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + uint64 minStakeDuration = DEFAULT_CHURN_PERIOD - 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidMinStakeDuration.selector, minStakeDuration + ) + ); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: minStakeDuration, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + // Helpers + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration, + uint256 stakeAmount + ) internal virtual override returns (bytes32) { + return app.initializeValidatorRegistration{value: stakeAmount}( + registrationInput, delegationFeeBips, minStakeDuration + ); + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory input, + uint64 weight + ) internal virtual override returns (bytes32) { + return app.initializeValidatorRegistration{value: _weightToValue(weight)}( + input, DEFAULT_DELEGATION_FEE_BIPS, DEFAULT_MINIMUM_STAKE_DURATION + ); + } + + function _initializeDelegatorRegistration( + bytes32 validationID, + address delegatorAddress, + uint64 weight + ) internal virtual override returns (bytes32) { + uint256 value = _weightToValue(weight); + vm.prank(delegatorAddress); + vm.deal(delegatorAddress, value); + return app.initializeDelegatorRegistration{value: value}(validationID); + } + + // solhint-disable no-empty-blocks + function _beforeSend(uint256 amount, address spender) internal override { + // Native tokens no need pre approve + } + // solhint-enable no-empty-blocks + + function _expectStakeUnlock(address account, uint256 amount) internal override { + // empty calldata implies the receive function will be called + vm.expectCall(account, amount, ""); + } + + function _expectRewardIssuance(address account, uint256 amount) internal override { + vm.mockCall( + address(app.NATIVE_MINTER()), + abi.encodeCall(INativeMinter.mintNativeCoin, (account, amount)), + "" + ); + // empty calldata implies the receive function will be called: + vm.mockCall({ + callee: account, + msgValue: amount, + data: "", // implies receive() + returnData: "" + }); + // Units tests don't have access to the native minter precompile, so use vm.deal instead. + vm.deal(account, account.balance + amount); + } + + function _setUp() internal override returns (IValidatorManager) { + // Construct the object under test + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + rewardCalculator = new ExampleRewardCalculator(DEFAULT_REWARD_RATE); + app.initialize( + PoSValidatorManagerSettings({ + baseSettings: ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + minimumStakeAmount: DEFAULT_MINIMUM_STAKE_AMOUNT, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE_AMOUNT, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + minimumDelegationFeeBips: DEFAULT_MINIMUM_DELEGATION_FEE_BIPS, + maximumStakeMultiplier: DEFAULT_MAXIMUM_STAKE_MULTIPLIER, + weightToValueFactor: DEFAULT_WEIGHT_TO_VALUE_FACTOR, + rewardCalculator: rewardCalculator + }) + ); + validatorManager = app; + posValidatorManager = app; + return app; + } + + function _getStakeAssetBalance(address account) internal view override returns (uint256) { + return account.balance; + } +} diff --git a/contracts/validator-manager/tests/PoAValidatorManagerTests.t.sol b/contracts/validator-manager/tests/PoAValidatorManagerTests.t.sol new file mode 100644 index 000000000..063bcd6f8 --- /dev/null +++ b/contracts/validator-manager/tests/PoAValidatorManagerTests.t.sol @@ -0,0 +1,85 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {ValidatorManagerTest} from "./ValidatorManagerTests.t.sol"; +import {PoAValidatorManager} from "../PoAValidatorManager.sol"; +import {ICMInitializable} from "@utilities/ICMInitializable.sol"; +import { + ValidatorManagerSettings, + ValidatorRegistrationInput, + IValidatorManager +} from "../interfaces/IValidatorManager.sol"; +import {OwnableUpgradeable} from + "@openzeppelin/contracts-upgradeable@5.0.2/access/OwnableUpgradeable.sol"; +import {ValidatorManagerTest} from "./ValidatorManagerTests.t.sol"; + +contract PoAValidatorManagerTest is ValidatorManagerTest { + PoAValidatorManager public app; + + address public constant DEFAULT_OWNER = address(0x1); + + function setUp() public override { + ValidatorManagerTest.setUp(); + + _setUp(); + _mockGetBlockchainID(); + _mockInitializeValidatorSet(); + app.initializeValidatorSet(_defaultSubnetConversionData(), 0); + } + + function testInvalidOwnerRegistration() public { + vm.prank(vm.addr(1)); + vm.expectRevert( + abi.encodeWithSelector( + OwnableUpgradeable.OwnableUnauthorizedAccount.selector, vm.addr(1) + ) + ); + _initializeValidatorRegistration( + ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }), + DEFAULT_WEIGHT + ); + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory input, + uint64 weight + ) internal virtual override returns (bytes32) { + return app.initializeValidatorRegistration(input, weight); + } + + function _initializeEndValidation(bytes32 validationID, bool) internal virtual override { + return app.initializeEndValidation(validationID); + } + + function _forceInitializeEndValidation(bytes32 validationID, bool) internal virtual override { + return app.initializeEndValidation(validationID); + } + + function _setUp() internal override returns (IValidatorManager) { + app = new PoAValidatorManager(ICMInitializable.Allowed); + app.initialize( + ValidatorManagerSettings({ + subnetID: DEFAULT_SUBNET_ID, + churnPeriodSeconds: DEFAULT_CHURN_PERIOD, + maximumChurnPercentage: DEFAULT_MAXIMUM_CHURN_PERCENTAGE + }), + address(this) + ); + validatorManager = app; + + return app; + } + + // solhint-disable-next-line no-empty-blocks + function _beforeSend(uint256 amount, address spender) internal virtual override {} +} diff --git a/contracts/validator-manager/tests/PoSValidatorManagerTests.t.sol b/contracts/validator-manager/tests/PoSValidatorManagerTests.t.sol new file mode 100644 index 000000000..1684e165d --- /dev/null +++ b/contracts/validator-manager/tests/PoSValidatorManagerTests.t.sol @@ -0,0 +1,1580 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; +import {ValidatorManagerTest} from "./ValidatorManagerTests.t.sol"; +import {PoSValidatorManager} from "../PoSValidatorManager.sol"; +import {ValidatorManager} from "../ValidatorManager.sol"; +import { + WarpMessage, + IWarpMessenger +} from "@avalabs/subnet-evm-contracts@1.2.0/contracts/interfaces/IWarpMessenger.sol"; +import {ValidatorMessages} from "../ValidatorMessages.sol"; +import {ValidatorRegistrationInput, ValidatorStatus} from "../interfaces/IValidatorManager.sol"; + +abstract contract PoSValidatorManagerTest is ValidatorManagerTest { + uint64 public constant DEFAULT_UPTIME = uint64(100); + uint64 public constant DEFAULT_DELEGATOR_WEIGHT = uint64(1e5); + uint64 public constant DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP = + DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_EXPIRY; + uint64 public constant DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP = + DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + DEFAULT_EXPIRY; + uint64 public constant DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP = + DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION; + address public constant DEFAULT_DELEGATOR_ADDRESS = + address(0x1234123412341234123412341234123412341234); + address public constant DEFAULT_VALIDATOR_OWNER_ADDRESS = + address(0x2345234523452345234523452345234523452345); + uint64 public constant DEFAULT_REWARD_RATE = uint64(10); + uint64 public constant DEFAULT_MINIMUM_STAKE_DURATION = 24 hours; + uint16 public constant DEFAULT_MINIMUM_DELEGATION_FEE_BIPS = 100; + uint16 public constant DEFAULT_DELEGATION_FEE_BIPS = 150; + uint8 public constant DEFAULT_MAXIMUM_STAKE_MULTIPLIER = 4; + uint256 public constant DEFAULT_WEIGHT_TO_VALUE_FACTOR = 1e12; + uint256 public constant SECONDS_IN_YEAR = 31536000; + + PoSValidatorManager public posValidatorManager; + IRewardCalculator public rewardCalculator; + + event ValidationUptimeUpdated(bytes32 indexed validationID, uint64 uptime); + + event DelegatorAdded( + bytes32 indexed delegationID, + bytes32 indexed validationID, + address indexed delegatorAddress, + uint64 nonce, + uint64 validatorWeight, + uint64 delegatorWeight, + bytes32 setWeightMessageID + ); + + event DelegatorRegistered( + bytes32 indexed delegationID, bytes32 indexed validationID, uint256 startTime + ); + + event DelegatorRemovalInitialized(bytes32 indexed delegationID, bytes32 indexed validationID); + + event ValidatorWeightUpdate( + bytes32 indexed validationID, + uint64 indexed nonce, + uint64 validatorWeight, + bytes32 setWeightMessageID + ); + + event DelegationEnded( + bytes32 indexed delegationID, bytes32 indexed validationID, uint256 rewards, uint256 fees + ); + + event UptimeUpdated(bytes32 indexed validationID, uint64 uptime); + + function testDelegationFeeBipsTooLow() public { + ValidatorRegistrationInput memory registrationInput = ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidDelegationFee.selector, + DEFAULT_MINIMUM_DELEGATION_FEE_BIPS - 1 + ) + ); + _initializeValidatorRegistration( + registrationInput, + DEFAULT_MINIMUM_DELEGATION_FEE_BIPS - 1, + DEFAULT_MINIMUM_STAKE_DURATION, + DEFAULT_MINIMUM_STAKE_AMOUNT + ); + } + + function testDelegationFeeBipsTooHigh() public { + ValidatorRegistrationInput memory registrationInput = ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }); + uint16 delegationFeeBips = posValidatorManager.MAXIMUM_DELEGATION_FEE_BIPS() + 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidDelegationFee.selector, delegationFeeBips + ) + ); + + _initializeValidatorRegistration( + registrationInput, + delegationFeeBips, + DEFAULT_MINIMUM_STAKE_DURATION, + DEFAULT_MINIMUM_STAKE_AMOUNT + ); + } + + function testInvalidMinStakeDuration() public { + ValidatorRegistrationInput memory registrationInput = ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidMinStakeDuration.selector, + DEFAULT_MINIMUM_STAKE_DURATION - 1 + ) + ); + _initializeValidatorRegistration( + registrationInput, + DEFAULT_DELEGATION_FEE_BIPS, + DEFAULT_MINIMUM_STAKE_DURATION - 1, + DEFAULT_MINIMUM_STAKE_AMOUNT + ); + } + + function testStakeAmountTooLow() public { + ValidatorRegistrationInput memory registrationInput = ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidStakeAmount.selector, DEFAULT_MINIMUM_STAKE_AMOUNT - 1 + ) + ); + _initializeValidatorRegistration( + registrationInput, + DEFAULT_DELEGATION_FEE_BIPS, + DEFAULT_MINIMUM_STAKE_DURATION, + DEFAULT_MINIMUM_STAKE_AMOUNT - 1 + ); + } + + function testStakeAmountTooHigh() public { + ValidatorRegistrationInput memory registrationInput = ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER + }); + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.InvalidStakeAmount.selector, DEFAULT_MAXIMUM_STAKE_AMOUNT + 1 + ) + ); + _initializeValidatorRegistration( + registrationInput, + DEFAULT_DELEGATION_FEE_BIPS, + DEFAULT_MINIMUM_STAKE_DURATION, + DEFAULT_MAXIMUM_STAKE_AMOUNT + 1 + ); + } + + function testInvalidInitializeEndTime() public { + bytes32 validationID = _registerDefaultValidator(); + + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.MinStakeDurationNotPassed.selector, block.timestamp + ) + ); + posValidatorManager.initializeEndValidation(validationID, false, 0); + } + + function testInvalidUptimeWarpMessage() public { + bytes32 validationID = _registerDefaultValidator(); + + _mockGetUptimeWarpMessage(new bytes(0), false); + vm.warp(DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION); + vm.expectRevert(ValidatorManager.InvalidWarpMessage.selector); + posValidatorManager.initializeEndValidation(validationID, true, 0); + } + + function testInvalidUptimeChainID() public { + bytes32 validationID = _registerDefaultValidator(); + + _mockGetUptimeWarpMessage(new bytes(0), true); + _mockGetBlockchainID(posValidatorManager.P_CHAIN_BLOCKCHAIN_ID()); + vm.warp(DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION); + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.InvalidWarpSourceChainID.selector, DEFAULT_SOURCE_BLOCKCHAIN_ID + ) + ); + posValidatorManager.initializeEndValidation(validationID, true, 0); + } + + function testInvalidUptimeSenderAddress() public { + bytes32 validationID = _registerDefaultValidator(); + + _mockGetBlockchainID(); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: DEFAULT_SOURCE_BLOCKCHAIN_ID, + originSenderAddress: address(this), + payload: new bytes(0) + }), + true + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + + vm.warp(DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION); + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.InvalidWarpOriginSenderAddress.selector, address(this) + ) + ); + posValidatorManager.initializeEndValidation(validationID, true, 0); + } + + function testInvalidUptimeValidationID() public { + bytes32 validationID = _registerDefaultValidator(); + + _mockGetBlockchainID(); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: DEFAULT_SOURCE_BLOCKCHAIN_ID, + originSenderAddress: address(0), + payload: ValidatorMessages.packValidationUptimeMessage(bytes32(0), 0) + }), + true + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + + vm.warp(DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION); + vm.expectRevert( + abi.encodeWithSelector(ValidatorManager.InvalidValidationID.selector, validationID) + ); + posValidatorManager.initializeEndValidation(validationID, true, 0); + } + + function testInitializeDelegatorRegistration() public { + bytes32 validationID = _registerDefaultValidator(); + + _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: DEFAULT_DELEGATOR_ADDRESS, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + } + + function testResendDelegatorRegistration() public { + bytes32 validationID = _registerDefaultValidator(); + + bytes32 delegationID = _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: DEFAULT_DELEGATOR_ADDRESS, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + bytes memory setValidatorWeightPayload = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, 1, DEFAULT_WEIGHT + DEFAULT_DELEGATOR_WEIGHT + ); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + posValidatorManager.resendUpdateDelegation(delegationID); + } + + function testCompleteDelegatorRegistration() public { + bytes32 validationID = _registerDefaultValidator(); + + _registerDefaultDelegator(validationID); + } + + function testCompleteDelegatorRegistrationWrongNonce() public { + bytes32 validationID = _registerDefaultValidator(); + + // Initialize two delegations + address delegator1 = DEFAULT_DELEGATOR_ADDRESS; + _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: delegator1, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + address delegator2 = address(0x5678567856785678567856785678567856785678); + bytes32 delegationID2 = _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: delegator2, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + 1, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_DELEGATOR_WEIGHT + + DEFAULT_WEIGHT, + expectedNonce: 2 + }); + + // Complete registration of delegator2 with delegator1's nonce + // Note that registering delegator1 with delegator2's nonce is valid + uint64 nonce = 1; + bytes memory setValidatorWeightPayload = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, nonce, DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT + ); + _mockGetPChainWarpMessage(setValidatorWeightPayload, true); + + vm.warp(DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP); + vm.expectRevert(abi.encodeWithSelector(PoSValidatorManager.InvalidNonce.selector, nonce)); + posValidatorManager.completeDelegatorRegistration(0, delegationID2); + } + + function testCompleteDelegatorRegistrationImplicitNonce() public { + bytes32 validationID = _registerDefaultValidator(); + + // Initialize two delegations + address delegator1 = DEFAULT_DELEGATOR_ADDRESS; + bytes32 delegationID1 = _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: delegator1, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + address delegator2 = address(0x5678567856785678567856785678567856785678); + _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: delegator2, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + 1, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_DELEGATOR_WEIGHT + + DEFAULT_WEIGHT, + expectedNonce: 2 + }); + // Mark delegator1 as registered by delivering the weight update from nonce 2 (delegator 2's nonce) + _setUpCompleteDelegatorRegistration( + validationID, + delegationID1, + DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + DEFAULT_DELEGATOR_WEIGHT + DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + 2 + ); + } + + function testInitializeEndValidationNotOwner() public { + bytes32 validationID = _registerDefaultValidator(); + + vm.prank(address(1)); + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.UnauthorizedOwner.selector, address(1)) + ); + posValidatorManager.initializeEndValidation(validationID, false, 0); + } + + function testInitializeEndDelegation() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: false + }); + } + + function testInitializeEndDelegationByValidator() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: address(this), + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: false + }); + } + + function testInitializeEndDelegationByValidatorMinStakeDurationNotPassed() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + uint64 invalidEndTime = DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + 1 hours; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.MinStakeDurationNotPassed.selector, invalidEndTime + ) + ); + _initializeEndDelegation({ + sender: address(this), + delegationID: delegationID, + endDelegationTimestamp: invalidEndTime, + includeUptime: false, + force: false + }); + } + + function testInitializeEndDelegationMinStakeDurationNotPassed() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + uint64 invalidEndTime = + DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION - 1; + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.MinStakeDurationNotPassed.selector, invalidEndTime + ) + ); + _initializeEndDelegation({ + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + endDelegationTimestamp: invalidEndTime, + includeUptime: false, + force: false + }); + } + + function testCompleteEndDelegationChurnPeriodSecondsNotPassed() public { + bytes32 validationID = _registerDefaultValidator(); + uint64 delegatorRegistrationTime = + DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION + 1; + bytes32 delegationID = _registerDelegator({ + validationID: validationID, + delegatorAddress: DEFAULT_DELEGATOR_ADDRESS, + weight: DEFAULT_DELEGATOR_WEIGHT, + initRegistrationTimestamp: delegatorRegistrationTime - 1, + completeRegistrationTimestamp: delegatorRegistrationTime, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + + _endValidationWithChecks({ + validationID: validationID, + validatorOwner: address(this), + completeRegistrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: delegatorRegistrationTime + 1, + validatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2 + }); + + uint64 invalidEndTime = delegatorRegistrationTime + DEFAULT_CHURN_PERIOD - 1; + + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.MinStakeDurationNotPassed.selector, invalidEndTime + ) + ); + + // Initialize end delegation will also call _completeEndDelegation because the validator is copmleted. + _initializeEndDelegation({ + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + endDelegationTimestamp: invalidEndTime, + includeUptime: false, + force: false + }); + } + + function testInitializeEndDelegationInsufficientUptime() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.DelegatorIneligibleForRewards.selector, delegationID + ) + ); + vm.warp(DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP); + vm.prank(DEFAULT_DELEGATOR_ADDRESS); + posValidatorManager.initializeEndDelegation(delegationID, false, 0); + } + + function testForceInitializeEndDelegation() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: true + }); + } + + function testForceInitializeEndDelegationInsufficientUptime() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: false, + force: true + }); + } + + function testResendEndDelegation() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: false + }); + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, 2, DEFAULT_WEIGHT); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + posValidatorManager.resendUpdateDelegation(delegationID); + } + + function testResendEndValidation() public override { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: true, + force: false + }); + + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, 1, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + validatorManager.resendEndValidatorMessage(validationID); + } + + function testCompleteEndDelegation() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: false + }); + + uint256 expectedTotalReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(DEFAULT_DELEGATOR_WEIGHT), + validatorStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingStartTime: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + stakingEndTime: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + uptimeSeconds: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP + }); + + _completeEndDelegationWithChecks({ + validationID: validationID, + delegationID: delegationID, + delegator: DEFAULT_DELEGATOR_ADDRESS, + delegatorWeight: DEFAULT_DELEGATOR_WEIGHT, + expectedTotalReward: expectedTotalReward, + delegationFeeBips: DEFAULT_DELEGATION_FEE_BIPS, + validatorWeight: DEFAULT_WEIGHT, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2 + }); + } + + // Delegator registration is not allowed when Validator is pending removed. + function testInitializeDelegatorRegistrationValidatorPendingRemoved() public { + bytes32 validationID = _registerDefaultValidator(); + + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION, + expectedNonce: 1, + includeUptime: true, + force: false + }); + + _beforeSend(_weightToValue(DEFAULT_DELEGATOR_WEIGHT), DEFAULT_DELEGATOR_ADDRESS); + + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.InvalidValidatorStatus.selector, ValidatorStatus.PendingRemoved + ) + ); + _initializeDelegatorRegistration( + validationID, DEFAULT_DELEGATOR_ADDRESS, DEFAULT_DELEGATOR_WEIGHT + ); + } + + // Complete delegator registration may be called when validator is pending removed. + function testCompleteRegisterDelegatorValidatorPendingRemoved() public { + bytes32 validationID = _registerDefaultValidator(); + + bytes32 delegationID = _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: DEFAULT_DELEGATOR_ADDRESS, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + + uint64 validatorEndTime = DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION; + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: validatorEndTime, + expectedNonce: 2, + includeUptime: true, + force: false + }); + + _setUpCompleteDelegatorRegistrationWithChecks( + validationID, + delegationID, + validatorEndTime + 1, + DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + 1 + ); + } + + // Delegator cannot initialize end delegation when validator is pending removed. + function testInitializeEndDelegationValidatorPendingRemoved() public { + bytes32 validationID = _registerDefaultValidator(); + + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_REGISTRATION_TIMESTAMP + DEFAULT_MINIMUM_STAKE_DURATION, + expectedNonce: 1, + includeUptime: true, + force: false + }); + + _beforeSend(_weightToValue(DEFAULT_DELEGATOR_WEIGHT), DEFAULT_DELEGATOR_ADDRESS); + + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.InvalidValidatorStatus.selector, ValidatorStatus.PendingRemoved + ) + ); + _initializeDelegatorRegistration( + validationID, DEFAULT_DELEGATOR_ADDRESS, DEFAULT_DELEGATOR_WEIGHT + ); + } + + // Delegator may complete end delegation while validator is pending removed. + function testCompleteEndDelegationValidatorPendingRemoved() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: false + }); + + uint64 validationEndTime = DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP + 1; + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: validationEndTime, + expectedNonce: 3, + includeUptime: true, + force: false + }); + + uint256 expectedTotalReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(DEFAULT_DELEGATOR_WEIGHT), + validatorStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingStartTime: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + stakingEndTime: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + uptimeSeconds: validationEndTime - DEFAULT_REGISTRATION_TIMESTAMP + }); + + _completeEndDelegationWithChecks({ + validationID: validationID, + delegationID: delegationID, + delegator: DEFAULT_DELEGATOR_ADDRESS, + delegatorWeight: DEFAULT_DELEGATOR_WEIGHT, + expectedTotalReward: expectedTotalReward, + delegationFeeBips: DEFAULT_DELEGATION_FEE_BIPS, + validatorWeight: DEFAULT_WEIGHT, + expectedValidatorWeight: 0, + expectedNonce: 2 + }); + } + + function testInitializeDelegatorRegistrationValidatorCompleted() public { + bytes32 validationID = _registerDefaultValidator(); + _endDefaultValidator(validationID, 1); + + _beforeSend(_weightToValue(DEFAULT_DELEGATOR_WEIGHT), DEFAULT_DELEGATOR_ADDRESS); + + vm.warp(DEFAULT_COMPLETION_TIMESTAMP + 1); + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.InvalidValidatorStatus.selector, ValidatorStatus.Completed + ) + ); + _initializeDelegatorRegistration( + validationID, DEFAULT_DELEGATOR_ADDRESS, DEFAULT_DELEGATOR_WEIGHT + ); + } + + function testCompleteDelegatorRegistrationValidatorCompleted() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _initializeDefaultDelegatorRegistration(validationID); + + _endDefaultValidator(validationID, 2); + + // completeDelegatorRegistration should fall through to _completeEndDelegation and refund the stake + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit DelegationEnded(delegationID, validationID, 0, 0); + + uint256 balanceBefore = _getStakeAssetBalance(DEFAULT_DELEGATOR_ADDRESS); + + _expectStakeUnlock(DEFAULT_DELEGATOR_ADDRESS, _weightToValue(DEFAULT_DELEGATOR_WEIGHT)); + + // warp to right after validator ended + vm.warp(DEFAULT_COMPLETION_TIMESTAMP + 1); + posValidatorManager.completeDelegatorRegistration(0, delegationID); + + assertEq( + _getStakeAssetBalance(DEFAULT_DELEGATOR_ADDRESS), + balanceBefore + _weightToValue(DEFAULT_DELEGATOR_WEIGHT) + ); + } + + function testInitializeEndDelegationValidatorCompleted() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _endDefaultValidator(validationID, 2); + + uint64 delegationEndTime = DEFAULT_COMPLETION_TIMESTAMP + 1; + + uint256 expectedTotalReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(DEFAULT_DELEGATOR_WEIGHT), + validatorStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingStartTime: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + stakingEndTime: DEFAULT_COMPLETION_TIMESTAMP, + uptimeSeconds: DEFAULT_COMPLETION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP + }); + + uint256 expectedValidatorFees = expectedTotalReward * DEFAULT_DELEGATION_FEE_BIPS / 10000; + uint256 expectedDelegatorReward = expectedTotalReward - expectedValidatorFees; + + // completeDelegatorRegistration should fall through to _completeEndDelegation and refund the stake + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit DelegationEnded( + delegationID, validationID, expectedDelegatorReward, expectedValidatorFees + ); + + uint256 balanceBefore = _getStakeAssetBalance(DEFAULT_DELEGATOR_ADDRESS); + + _expectStakeUnlock(DEFAULT_DELEGATOR_ADDRESS, _weightToValue(DEFAULT_DELEGATOR_WEIGHT)); + _expectRewardIssuance(DEFAULT_DELEGATOR_ADDRESS, expectedDelegatorReward); + + // warp to right after validator ended + vm.warp(delegationEndTime); + vm.prank(DEFAULT_DELEGATOR_ADDRESS); + posValidatorManager.initializeEndDelegation(delegationID, false, 0); + + assertEq( + _getStakeAssetBalance(DEFAULT_DELEGATOR_ADDRESS), + balanceBefore + _weightToValue(DEFAULT_DELEGATOR_WEIGHT) + expectedDelegatorReward + ); + } + + function testCompleteEndDelegationValidatorCompleted() public { + bytes32 validationID = _registerDefaultValidator(); + bytes32 delegationID = _registerDefaultDelegator(validationID); + + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: DEFAULT_DELEGATOR_ADDRESS, + delegationID: delegationID, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 2, + includeUptime: true, + force: false + }); + + _endDefaultValidator(validationID, 3); + + uint256 expectedTotalReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(DEFAULT_DELEGATOR_WEIGHT), + validatorStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingStartTime: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + stakingEndTime: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + uptimeSeconds: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP + }); + + uint256 expectedValidatorFees = expectedTotalReward * DEFAULT_DELEGATION_FEE_BIPS / 10000; + uint256 expectedDelegatorReward = expectedTotalReward - expectedValidatorFees; + + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit DelegationEnded( + delegationID, validationID, expectedDelegatorReward, expectedValidatorFees + ); + uint256 balanceBefore = _getStakeAssetBalance(DEFAULT_DELEGATOR_ADDRESS); + + _expectStakeUnlock(DEFAULT_DELEGATOR_ADDRESS, _weightToValue(DEFAULT_DELEGATOR_WEIGHT)); + _expectRewardIssuance(DEFAULT_DELEGATOR_ADDRESS, expectedDelegatorReward); + + posValidatorManager.completeEndDelegation(0, delegationID); + + assertEq( + _getStakeAssetBalance(DEFAULT_DELEGATOR_ADDRESS), + balanceBefore + _weightToValue(DEFAULT_DELEGATOR_WEIGHT) + expectedDelegatorReward + ); + } + + function testCompleteEndDelegationWrongNonce() public { + bytes32 validationID = _registerDefaultValidator(); + // Register two delegations + address delegator1 = DEFAULT_DELEGATOR_ADDRESS; + bytes32 delegationID1 = _registerDelegator({ + validationID: validationID, + delegatorAddress: delegator1, + weight: DEFAULT_DELEGATOR_WEIGHT, + initRegistrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + completeRegistrationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + + address delegator2 = address(0x5678567856785678567856785678567856785678); + bytes32 delegationID2 = _registerDelegator({ + validationID: validationID, + delegatorAddress: delegator2, + weight: DEFAULT_DELEGATOR_WEIGHT, + initRegistrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + 1, + completeRegistrationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT * 2 + DEFAULT_WEIGHT, + expectedNonce: 2 + }); + + // Initialize end delegation for both delegators + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: delegator1, + delegationID: delegationID1, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 3, + includeUptime: true, + force: false + }); + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: delegator2, + delegationID: delegationID2, + startDelegationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP + 1, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 4, + includeUptime: true, + force: false + }); + + // Complete ending delegator2 with delegator1's nonce + // Note that ending delegator1 with delegator2's nonce is valid + uint64 nonce = 3; + bytes memory setValidatorWeightPayload = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, nonce, DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT + ); + _mockGetPChainWarpMessage(setValidatorWeightPayload, true); + + vm.expectRevert(abi.encodeWithSelector(PoSValidatorManager.InvalidNonce.selector, nonce)); + posValidatorManager.completeEndDelegation(0, delegationID2); + } + + function testCompleteEndDelegationImplicitNonce() public { + bytes32 validationID = _registerDefaultValidator(); + + // Register two delegations + address delegator1 = DEFAULT_DELEGATOR_ADDRESS; + bytes32 delegationID1 = _registerDelegator({ + validationID: validationID, + delegatorAddress: delegator1, + weight: DEFAULT_DELEGATOR_WEIGHT, + initRegistrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + completeRegistrationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + + address delegator2 = address(0x5678567856785678567856785678567856785678); + bytes32 delegationID2 = _registerDelegator({ + validationID: validationID, + delegatorAddress: delegator2, + weight: DEFAULT_DELEGATOR_WEIGHT, + initRegistrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP + 1, + completeRegistrationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT * 2 + DEFAULT_WEIGHT, + expectedNonce: 2 + }); + + // Initialize end delegation for both delegators + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: delegator1, + delegationID: delegationID1, + startDelegationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 3, + includeUptime: true, + force: false + }); + _initializeEndDelegationValidatorActiveWithChecks({ + validationID: validationID, + sender: delegator2, + delegationID: delegationID2, + startDelegationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + endDelegationTimestamp: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP + 1, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 4, + includeUptime: true, + force: false + }); + + uint256 expectedTotalReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(DEFAULT_DELEGATOR_WEIGHT), + validatorStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingStartTime: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + stakingEndTime: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP, + uptimeSeconds: DEFAULT_DELEGATOR_END_DELEGATION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP + }); + + // Complete delegation1 by delivering the weight update from nonce 4 (delegator2's nonce) + _completeEndDelegationWithChecks({ + validationID: validationID, + delegationID: delegationID1, + delegator: DEFAULT_DELEGATOR_ADDRESS, + delegatorWeight: DEFAULT_DELEGATOR_WEIGHT, + expectedTotalReward: expectedTotalReward, + delegationFeeBips: DEFAULT_DELEGATION_FEE_BIPS, + validatorWeight: DEFAULT_WEIGHT, + expectedValidatorWeight: DEFAULT_WEIGHT, + expectedNonce: 4 + }); + } + + function testCompleteEndValidation() public virtual override { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: true, + force: false + }); + + uint256 expectedReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(DEFAULT_WEIGHT), + validatorStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingStartTime: DEFAULT_REGISTRATION_TIMESTAMP, + stakingEndTime: DEFAULT_COMPLETION_TIMESTAMP, + uptimeSeconds: DEFAULT_COMPLETION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP + }); + + _completeEndValidationWithChecks({ + validationID: validationID, + validatorOwner: address(this), + expectedReward: expectedReward, + validatorWeight: DEFAULT_WEIGHT + }); + } + + function testInitializeEndValidation() public virtual override { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: true, + force: false + }); + } + + function testInitializeEndValidationUseStoredUptime() public { + bytes32 validationID = _registerDefaultValidator(); + + vm.warp(DEFAULT_COMPLETION_TIMESTAMP); + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, 1, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + + // Submit an uptime proof via submitUptime + uint64 uptimePercentage1 = 80; + uint64 uptime1 = (DEFAULT_COMPLETION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP) + * uptimePercentage1 / 100; + bytes memory uptimeMsg1 = + ValidatorMessages.packValidationUptimeMessage(validationID, uptime1); + _mockGetUptimeWarpMessage(uptimeMsg1, true); + _mockGetBlockchainID(); + + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit UptimeUpdated(validationID, uptime1); + posValidatorManager.submitUptimeProof(validationID, 0); + + // Submit a second uptime proof via initializeEndValidation. This one is not sufficient for rewards + // Submit an uptime proof via submitUptime + uint64 uptimePercentage2 = 79; + uint64 uptime2 = (DEFAULT_COMPLETION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP) + * uptimePercentage2 / 100; + bytes memory uptimeMsg2 = + ValidatorMessages.packValidationUptimeMessage(validationID, uptime2); + _mockGetUptimeWarpMessage(uptimeMsg2, true); + _mockGetBlockchainID(); + + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidatorRemovalInitialized( + validationID, bytes32(0), DEFAULT_WEIGHT, DEFAULT_COMPLETION_TIMESTAMP + ); + + _initializeEndValidation(validationID, true); + } + + function testInitializeEndValidationInsufficientUptime() public { + bytes32 validationID = _registerDefaultValidator(); + uint64 uptimePercentage = 79; + + vm.warp(DEFAULT_COMPLETION_TIMESTAMP); + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, 1, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + + bytes memory uptimeMsg = ValidatorMessages.packValidationUptimeMessage( + validationID, + (DEFAULT_COMPLETION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP) * uptimePercentage / 100 + ); + _mockGetUptimeWarpMessage(uptimeMsg, true); + _mockGetBlockchainID(); + + vm.expectRevert( + abi.encodeWithSelector( + PoSValidatorManager.ValidatorIneligibleForRewards.selector, validationID + ) + ); + + _initializeEndValidation(validationID, true); + } + + function testInitializeEndValidationPoAValidator() public { + bytes32 defaultInitialValidationID = sha256(abi.encodePacked(DEFAULT_SUBNET_ID, uint32(1))); + + vm.warp(DEFAULT_COMPLETION_TIMESTAMP); + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(defaultInitialValidationID, 1, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidatorRemovalInitialized( + defaultInitialValidationID, bytes32(0), DEFAULT_WEIGHT, DEFAULT_COMPLETION_TIMESTAMP + ); + + _initializeEndValidation(defaultInitialValidationID, false); + } + + function testForceInitializeEndValidation() public { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: true, + force: true + }); + } + + function testForceInitializeEndValidationInsufficientUptime() public { + bytes32 validationID = _registerDefaultValidator(); + uint64 uptimePercentage = 79; + + vm.warp(DEFAULT_COMPLETION_TIMESTAMP); + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, 1, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + + bytes memory uptimeMsg = ValidatorMessages.packValidationUptimeMessage( + validationID, + (DEFAULT_COMPLETION_TIMESTAMP - DEFAULT_REGISTRATION_TIMESTAMP) * uptimePercentage / 100 + ); + _mockGetUptimeWarpMessage(uptimeMsg, true); + _mockGetBlockchainID(); + + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidatorRemovalInitialized( + validationID, bytes32(0), DEFAULT_WEIGHT, DEFAULT_COMPLETION_TIMESTAMP + ); + + _forceInitializeEndValidation(validationID, true); + } + + function testValueToWeightTruncated() public { + // default weightToValueFactor is 1e12 + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.InvalidStakeAmount.selector, 1e11) + ); + posValidatorManager.valueToWeight(1e11); + } + + function testValueToWeightExceedsUInt64Max() public { + // default weightToValueFactor is 1e12 + vm.expectRevert( + abi.encodeWithSelector(PoSValidatorManager.InvalidStakeAmount.selector, 1e40) + ); + posValidatorManager.valueToWeight(1e40); + } + + function testValueToWeight() public view { + uint64 w1 = posValidatorManager.valueToWeight(1e12); + uint64 w2 = posValidatorManager.valueToWeight(1e18); + uint64 w3 = posValidatorManager.valueToWeight(1e27); + + assertEq(w1, 1); + assertEq(w2, 1e6); + assertEq(w3, 1e15); + } + + function testWeightToValue() public view { + uint256 v1 = posValidatorManager.weightToValue(1); + uint256 v2 = posValidatorManager.weightToValue(1e6); + uint256 v3 = posValidatorManager.weightToValue(1e15); + + assertEq(v1, 1e12); + assertEq(v2, 1e18); + assertEq(v3, 1e27); + } + + function testPoSValidatorManagerStorageSlot() public view { + assertEq( + _erc7201StorageSlot("PoSValidatorManager"), + posValidatorManager.POS_VALIDATOR_MANAGER_STORAGE_LOCATION() + ); + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory registrationInput, + uint16 delegationFeeBips, + uint64 minStakeDuration, + uint256 stakeAmount + ) internal virtual returns (bytes32); + + function _initializeEndValidation( + bytes32 validationID, + bool includeUptime + ) internal virtual override { + posValidatorManager.initializeEndValidation(validationID, includeUptime, 0); + } + + function _forceInitializeEndValidation( + bytes32 validationID, + bool includeUptime + ) internal virtual override { + posValidatorManager.forceInitializeEndValidation(validationID, includeUptime, 0); + } + + function _initializeDelegatorRegistration( + bytes32 validationID, + address delegatorAddress, + uint64 weight + ) internal virtual returns (bytes32); + + // + // Delegation setup utilities + // + function _setUpInitializeDelegatorRegistration( + bytes32 validationID, + address delegatorAddress, + uint64 weight, + uint64 registrationTimestamp, + uint64 expectedValidatorWeight, + uint64 expectedNonce + ) internal returns (bytes32) { + bytes memory setValidatorWeightPayload = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, expectedNonce, expectedValidatorWeight + ); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + vm.warp(registrationTimestamp); + + _beforeSend(_weightToValue(weight), delegatorAddress); + + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit DelegatorAdded({ + delegationID: keccak256(abi.encodePacked(validationID, expectedNonce)), + validationID: validationID, + delegatorAddress: delegatorAddress, + nonce: expectedNonce, + validatorWeight: expectedValidatorWeight, + delegatorWeight: weight, + setWeightMessageID: bytes32(0) + }); + + return _initializeDelegatorRegistration(validationID, delegatorAddress, weight); + } + + function _setUpCompleteDelegatorRegistration( + bytes32 validationID, + bytes32 delegationID, + uint64 completeRegistrationTimestamp, + uint64 expectedValidatorWeight, + uint64 expectedNonce + ) internal { + bytes memory setValidatorWeightPayload = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, expectedNonce, expectedValidatorWeight + ); + _mockGetPChainWarpMessage(setValidatorWeightPayload, true); + + vm.warp(completeRegistrationTimestamp); + posValidatorManager.completeDelegatorRegistration(0, delegationID); + } + + function _setUpCompleteDelegatorRegistrationWithChecks( + bytes32 validationID, + bytes32 delegationID, + uint64 completeRegistrationTimestamp, + uint64 expectedValidatorWeight, + uint64 expectedNonce + ) internal { + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit DelegatorRegistered({ + delegationID: delegationID, + validationID: validationID, + startTime: completeRegistrationTimestamp + }); + _setUpCompleteDelegatorRegistration( + validationID, + delegationID, + completeRegistrationTimestamp, + expectedValidatorWeight, + expectedNonce + ); + } + + function _registerDefaultDelegator(bytes32 validationID) + internal + returns (bytes32 delegationID) + { + return _registerDelegator({ + validationID: validationID, + delegatorAddress: DEFAULT_DELEGATOR_ADDRESS, + weight: DEFAULT_DELEGATOR_WEIGHT, + initRegistrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + completeRegistrationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + } + + function _initializeDefaultDelegatorRegistration(bytes32 validationID) + internal + returns (bytes32) + { + return _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: DEFAULT_DELEGATOR_ADDRESS, + weight: DEFAULT_DELEGATOR_WEIGHT, + registrationTimestamp: DEFAULT_DELEGATOR_INIT_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + } + + function _completeDefaultDelegatorRegistration( + bytes32 validationID, + bytes32 delegationID + ) internal { + _setUpCompleteDelegatorRegistration({ + validationID: validationID, + delegationID: delegationID, + completeRegistrationTimestamp: DEFAULT_DELEGATOR_COMPLETE_REGISTRATION_TIMESTAMP, + expectedValidatorWeight: DEFAULT_DELEGATOR_WEIGHT + DEFAULT_WEIGHT, + expectedNonce: 1 + }); + } + + function _registerDelegator( + bytes32 validationID, + address delegatorAddress, + uint64 weight, + uint64 initRegistrationTimestamp, + uint64 completeRegistrationTimestamp, + uint64 expectedValidatorWeight, + uint64 expectedNonce + ) internal returns (bytes32) { + bytes32 delegationID = _setUpInitializeDelegatorRegistration({ + validationID: validationID, + delegatorAddress: delegatorAddress, + weight: weight, + registrationTimestamp: initRegistrationTimestamp, + expectedValidatorWeight: expectedValidatorWeight, + expectedNonce: expectedNonce + }); + _setUpCompleteDelegatorRegistration( + validationID, + delegationID, + completeRegistrationTimestamp, + expectedValidatorWeight, + expectedNonce + ); + return delegationID; + } + + function _initializeEndDelegationValidatorActiveWithChecks( + bytes32 validationID, + address sender, + bytes32 delegationID, + uint64 startDelegationTimestamp, + uint64 endDelegationTimestamp, + uint64 expectedValidatorWeight, + uint64 expectedNonce, + bool includeUptime, + bool force + ) internal { + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit ValidatorWeightUpdate({ + validationID: validationID, + nonce: expectedNonce, + validatorWeight: expectedValidatorWeight, + setWeightMessageID: bytes32(0) + }); + + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit DelegatorRemovalInitialized({delegationID: delegationID, validationID: validationID}); + + _initializeEndDelegationValidatorActive({ + validationID: validationID, + sender: sender, + delegationID: delegationID, + startDelegationTimestamp: startDelegationTimestamp, + endDelegationTimestamp: endDelegationTimestamp, + expectedValidatorWeight: expectedValidatorWeight, + expectedNonce: expectedNonce, + includeUptime: includeUptime, + force: force + }); + } + + function _initializeEndDelegationValidatorActive( + bytes32 validationID, + address sender, + bytes32 delegationID, + uint64 startDelegationTimestamp, + uint64 endDelegationTimestamp, + uint64 expectedValidatorWeight, + uint64 expectedNonce, + bool includeUptime, + bool force + ) internal { + bytes memory setValidatorWeightPayload = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, expectedNonce, expectedValidatorWeight + ); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + bytes memory uptimeMsg = ValidatorMessages.packValidationUptimeMessage( + validationID, endDelegationTimestamp - startDelegationTimestamp + ); + if (includeUptime) { + _mockGetUptimeWarpMessage(uptimeMsg, true); + _mockGetBlockchainID(); + } + _initializeEndDelegation(sender, delegationID, endDelegationTimestamp, includeUptime, force); + } + + function _initializeEndDelegation( + address sender, + bytes32 delegationID, + uint64 endDelegationTimestamp, + bool includeUptime, + bool force + ) internal { + vm.warp(endDelegationTimestamp); + vm.prank(sender); + if (force) { + posValidatorManager.forceInitializeEndDelegation(delegationID, includeUptime, 0); + } else { + posValidatorManager.initializeEndDelegation(delegationID, includeUptime, 0); + } + } + + function _endDefaultValidator(bytes32 validationID, uint64 expectedNonce) internal { + _endValidationWithChecks({ + validationID: validationID, + validatorOwner: address(this), + completeRegistrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + validatorWeight: DEFAULT_WEIGHT, + expectedNonce: expectedNonce + }); + } + + function _endValidationWithChecks( + bytes32 validationID, + address validatorOwner, + uint64 completeRegistrationTimestamp, + uint64 completionTimestamp, + uint64 validatorWeight, + uint64 expectedNonce + ) internal { + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: completeRegistrationTimestamp, + completionTimestamp: completionTimestamp, + expectedNonce: expectedNonce, + includeUptime: true, + force: false + }); + + uint256 expectedReward = rewardCalculator.calculateReward({ + stakeAmount: _weightToValue(validatorWeight), + validatorStartTime: completeRegistrationTimestamp, + stakingStartTime: completeRegistrationTimestamp, + stakingEndTime: completionTimestamp, + uptimeSeconds: completionTimestamp - completeRegistrationTimestamp + }); + + _completeEndValidationWithChecks({ + validationID: validationID, + validatorOwner: validatorOwner, + expectedReward: expectedReward, + validatorWeight: validatorWeight + }); + } + + function _completeEndValidationWithChecks( + bytes32 validationID, + address validatorOwner, + uint256 expectedReward, + uint64 validatorWeight + ) internal { + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit ValidationPeriodEnded(validationID, ValidatorStatus.Completed); + uint256 balanceBefore = _getStakeAssetBalance(validatorOwner); + + _expectStakeUnlock(validatorOwner, _weightToValue(validatorWeight)); + _expectRewardIssuance(validatorOwner, expectedReward); + + _completeEndValidation(validationID); + + assertEq( + _getStakeAssetBalance(validatorOwner), + balanceBefore + _weightToValue(validatorWeight) + expectedReward + ); + } + + function _completeEndValidation(bytes32 validationID) internal { + bytes memory subnetValidatorRegistrationMessage = + ValidatorMessages.packSubnetValidatorRegistrationMessage(validationID, false); + _mockGetPChainWarpMessage(subnetValidatorRegistrationMessage, true); + + posValidatorManager.completeEndValidation(0); + } + + function _completeEndDelegationWithChecks( + bytes32 validationID, + bytes32 delegationID, + address delegator, + uint64 delegatorWeight, + uint256 expectedTotalReward, + uint64 delegationFeeBips, + uint64 validatorWeight, + uint64 expectedValidatorWeight, + uint64 expectedNonce + ) internal { + uint256 expectedValidatorFees = expectedTotalReward * delegationFeeBips / 10000; + uint256 expectedDelegatorReward = expectedTotalReward - expectedValidatorFees; + + vm.expectEmit(true, true, true, true, address(posValidatorManager)); + emit DelegationEnded( + delegationID, validationID, expectedDelegatorReward, expectedValidatorFees + ); + uint256 balanceBefore = _getStakeAssetBalance(delegator); + + _expectStakeUnlock(delegator, _weightToValue(delegatorWeight)); + _expectRewardIssuance(delegator, expectedDelegatorReward); + + _completeEndDelegation(validationID, delegationID, validatorWeight, expectedNonce); + + assertEq(posValidatorManager.getWeight(validationID), expectedValidatorWeight); + assertEq( + _getStakeAssetBalance(delegator), + balanceBefore + _weightToValue(delegatorWeight) + expectedDelegatorReward + ); + } + + function _completeEndDelegation( + bytes32 validationID, + bytes32 delegationID, + uint64 validatorWeight, + uint64 expectedNonce + ) internal { + bytes memory weightUpdateMessage = ValidatorMessages.packSubnetValidatorWeightMessage( + validationID, expectedNonce, validatorWeight + ); + _mockGetPChainWarpMessage(weightUpdateMessage, true); + + posValidatorManager.completeEndDelegation(0, delegationID); + } + + function _getStakeAssetBalance(address account) internal virtual returns (uint256); + function _expectStakeUnlock(address account, uint256 amount) internal virtual; + function _expectRewardIssuance(address account, uint256 amount) internal virtual; +} diff --git a/contracts/validator-manager/tests/ValidatorManagerTests.t.sol b/contracts/validator-manager/tests/ValidatorManagerTests.t.sol new file mode 100644 index 000000000..0ce88da54 --- /dev/null +++ b/contracts/validator-manager/tests/ValidatorManagerTests.t.sol @@ -0,0 +1,689 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {ValidatorManager, SubnetConversionData, InitialValidator} from "../ValidatorManager.sol"; +import {ValidatorMessages} from "../ValidatorMessages.sol"; +import { + ValidatorStatus, + ValidatorRegistrationInput, + PChainOwner, + IValidatorManager +} from "../interfaces/IValidatorManager.sol"; +import { + WarpMessage, + IWarpMessenger +} from "@avalabs/subnet-evm-contracts@1.2.0/contracts/interfaces/IWarpMessenger.sol"; + +// TODO: Remove this once all unit tests implemented +// solhint-disable no-empty-blocks +abstract contract ValidatorManagerTest is Test { + bytes32 public constant DEFAULT_SUBNET_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes public constant DEFAULT_NODE_ID = + bytes(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes public constant DEFAULT_INITIAL_VALIDATOR_NODE_ID_1 = + bytes(hex"2345678123456781234567812345678123456781234567812345678123456781"); + bytes public constant DEFAULT_INITIAL_VALIDATOR_NODE_ID_2 = + bytes(hex"1345678123456781234567812345678123456781234567812345678123456781"); + bytes public constant DEFAULT_BLS_PUBLIC_KEY = bytes( + hex"123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" + ); + bytes32 public constant DEFAULT_SOURCE_BLOCKCHAIN_ID = + bytes32(hex"abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"); + bytes32 public constant DEFAULT_SUBNET_CONVERSION_ID = + bytes32(hex"76a386628f079b7b00452f8cab0925740363fcd52b721a8cf91773e857327b36"); + address public constant WARP_PRECOMPILE_ADDRESS = 0x0200000000000000000000000000000000000005; + + uint64 public constant DEFAULT_WEIGHT = 1e6; + // Set the default weight to 1e10 to avoid churn issues + uint64 public constant DEFAULT_INITIAL_VALIDATOR_WEIGHT = DEFAULT_WEIGHT * 1e4; + uint256 public constant DEFAULT_MINIMUM_STAKE_AMOUNT = 20e12; + uint256 public constant DEFAULT_MAXIMUM_STAKE_AMOUNT = 1e22; + uint64 public constant DEFAULT_CHURN_PERIOD = 1 hours; + uint8 public constant DEFAULT_MAXIMUM_CHURN_PERCENTAGE = 20; + uint64 public constant DEFAULT_EXPIRY = 1000; + uint8 public constant DEFAULT_MAXIMUM_HOURLY_CHURN = 0; + uint64 public constant DEFAULT_REGISTRATION_TIMESTAMP = 1000; + uint256 public constant DEFAULT_STARTING_TOTAL_WEIGHT = 1e10 + DEFAULT_WEIGHT; + uint64 public constant DEFAULT_COMPLETION_TIMESTAMP = 100_000; + // solhint-disable-next-line var-name-mixedcase + PChainOwner public DEFAULT_P_CHAIN_OWNER; + + ValidatorManager public validatorManager; + + // Used to create unique validator IDs in {_newNodeID} + uint64 public nodeIDCounter = 0; + + event ValidationPeriodCreated( + bytes32 indexed validationID, + bytes indexed nodeID, + bytes32 indexed registerValidationMessageID, + uint256 weight, + uint64 registrationExpiry + ); + + event ValidationPeriodRegistered( + bytes32 indexed validationID, uint256 stakeAmount, uint256 timestamp + ); + + event ValidatorRemovalInitialized( + bytes32 indexed validationID, + bytes32 indexed setWeightMessageID, + uint256 stakeAmount, + uint256 endTime + ); + + event ValidationPeriodEnded(bytes32 indexed validationID, ValidatorStatus indexed status); + + receive() external payable {} + fallback() external payable {} + + function setUp() public virtual { + address[] memory addresses = new address[](1); + addresses[0] = 0x1234567812345678123456781234567812345678; + DEFAULT_P_CHAIN_OWNER = PChainOwner({threshold: 1, addresses: addresses}); + } + + function testInitializeValidatorRegistrationSuccess() public { + _setUpInitializeValidatorRegistration( + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + DEFAULT_WEIGHT, + DEFAULT_EXPIRY, + DEFAULT_BLS_PUBLIC_KEY + ); + } + + function testInitializeValidatorRegistrationExcessiveChurn() public { + // TODO: implement + } + + function testInitializeValidatorRegistrationInsufficientStake() public { + // TODO: implement + } + + function testInitializeValidatorRegistrationExcessiveStake() public { + // TODO: implement + } + + function testInitializeValidatorRegistrationInsufficientDuration() public { + // TODO: implement + } + + function testInitializeValidatorRegistrationPChainOwnerThresholdTooLarge() public { + // Threshold too large + address[] memory addresses = new address[](1); + addresses[0] = 0x1234567812345678123456781234567812345678; + PChainOwner memory invalidPChainOwner1 = PChainOwner({threshold: 2, addresses: addresses}); + _beforeSend(_weightToValue(DEFAULT_WEIGHT), address(this)); + vm.expectRevert( + abi.encodeWithSelector(ValidatorManager.InvalidPChainOwnerThreshold.selector, 2, 1) + ); + _initializeValidatorRegistration( + ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + remainingBalanceOwner: invalidPChainOwner1, + disableOwner: DEFAULT_P_CHAIN_OWNER, + registrationExpiry: DEFAULT_EXPIRY + }), + DEFAULT_WEIGHT + ); + } + + function testInitializeValidatorRegistrationZeroPChainOwnerThreshold() public { + // Zero threshold for non-zero address + address[] memory addresses = new address[](1); + addresses[0] = 0x1234567812345678123456781234567812345678; + PChainOwner memory invalidPChainOwner1 = PChainOwner({threshold: 0, addresses: addresses}); + _beforeSend(_weightToValue(DEFAULT_WEIGHT), address(this)); + vm.expectRevert( + abi.encodeWithSelector(ValidatorManager.InvalidPChainOwnerThreshold.selector, 0, 1) + ); + _initializeValidatorRegistration( + ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + remainingBalanceOwner: invalidPChainOwner1, + disableOwner: DEFAULT_P_CHAIN_OWNER, + registrationExpiry: DEFAULT_EXPIRY + }), + DEFAULT_WEIGHT + ); + } + + function testInitializeValidatorRegistrationPChainOwnerAddressesUnsorted() public { + // Addresses not sorted + address[] memory addresses = new address[](2); + addresses[0] = 0x1234567812345678123456781234567812345678; + addresses[1] = 0x0123456781234567812345678123456781234567; + PChainOwner memory invalidPChainOwner1 = PChainOwner({threshold: 1, addresses: addresses}); + + _beforeSend(_weightToValue(DEFAULT_WEIGHT), address(this)); + vm.expectRevert( + abi.encodeWithSelector(ValidatorManager.PChainOwnerAddressesNotSorted.selector) + ); + _initializeValidatorRegistration( + ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + remainingBalanceOwner: invalidPChainOwner1, + disableOwner: DEFAULT_P_CHAIN_OWNER, + registrationExpiry: DEFAULT_EXPIRY + }), + DEFAULT_WEIGHT + ); + } + + // The following tests call functions that are implemented in ValidatorManager, but access state that's + // only set in NativeTokenValidatorManager. Therefore we call them via the concrete type, rather than a + // reference to the abstract type. + function testResendRegisterValidatorMessage() public { + bytes32 validationID = _setUpInitializeValidatorRegistration( + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + DEFAULT_WEIGHT, + DEFAULT_EXPIRY, + DEFAULT_BLS_PUBLIC_KEY + ); + (, bytes memory registerSubnetValidatorMessage) = ValidatorMessages + .packRegisterSubnetValidatorMessage( + ValidatorMessages.ValidationPeriod({ + subnetID: DEFAULT_SUBNET_ID, + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationExpiry: DEFAULT_EXPIRY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER, + weight: DEFAULT_WEIGHT + }) + ); + _mockSendWarpMessage(registerSubnetValidatorMessage, bytes32(0)); + validatorManager.resendRegisterValidatorMessage(validationID); + } + + function testCompleteValidatorRegistration() public { + _registerDefaultValidator(); + } + + function testInitializeEndValidation() public virtual { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: false, + force: false + }); + } + + function testResendEndValidation() public virtual { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: false, + force: false + }); + + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, 1, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + validatorManager.resendEndValidatorMessage(validationID); + } + + function testCompleteEndValidation() public virtual { + bytes32 validationID = _registerDefaultValidator(); + _initializeEndValidation({ + validationID: validationID, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP, + expectedNonce: 1, + includeUptime: false, + force: false + }); + + bytes memory subnetValidatorRegistrationMessage = + ValidatorMessages.packSubnetValidatorRegistrationMessage(validationID, false); + + _mockGetPChainWarpMessage(subnetValidatorRegistrationMessage, true); + + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidationPeriodEnded(validationID, ValidatorStatus.Completed); + + validatorManager.completeEndValidation(0); + } + + function testCompleteInvalidatedValidation() public { + bytes32 validationID = _setUpInitializeValidatorRegistration( + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + DEFAULT_WEIGHT, + DEFAULT_EXPIRY, + DEFAULT_BLS_PUBLIC_KEY + ); + bytes memory subnetValidatorRegistrationMessage = + ValidatorMessages.packSubnetValidatorRegistrationMessage(validationID, false); + + _mockGetPChainWarpMessage(subnetValidatorRegistrationMessage, true); + + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidationPeriodEnded(validationID, ValidatorStatus.Invalidated); + + validatorManager.completeEndValidation(0); + } + + function testInitialWeightsTooLow() public { + vm.prank(address(123)); + IValidatorManager manager = _setUp(); + + _mockGetBlockchainID(); + vm.expectRevert(abi.encodeWithSelector(ValidatorManager.InvalidTotalWeight.selector, 4)); + manager.initializeValidatorSet(_defaultSubnetConversionDataWeightsTooLow(), 0); + } + + function testRemoveValidatorTotalWeight5() public { + // Use prank here, because otherwise each test will end up with a different contract address, leading to a different subnet conversion hash. + vm.prank(address(123)); + IValidatorManager manager = _setUp(); + + _mockGetBlockchainID(); + _mockGetPChainWarpMessage( + ValidatorMessages.packSubnetConversionMessage( + bytes32(hex"1d72565851401e05d6351ebf5443d9bdc04953f3233da1345af126e7e4be7464") + ), + true + ); + manager.initializeValidatorSet(_defaultSubnetConversionDataTotalWeight5(), 0); + + bytes32 validationID = sha256(abi.encodePacked(DEFAULT_SUBNET_ID, uint32(0))); + vm.expectRevert(abi.encodeWithSelector(ValidatorManager.InvalidTotalWeight.selector, 4)); + _forceInitializeEndValidation(validationID, false); + } + + function testCumulativeChurnRegistration() public { + uint64 churnThreshold = + uint64(DEFAULT_STARTING_TOTAL_WEIGHT) * DEFAULT_MAXIMUM_CHURN_PERCENTAGE / 100; + _beforeSend(_weightToValue(churnThreshold), address(this)); + + // First registration should succeed + _registerValidator({ + nodeID: _newNodeID(), + subnetID: DEFAULT_SUBNET_ID, + weight: churnThreshold, + registrationExpiry: DEFAULT_EXPIRY, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP + }); + + _beforeSend(DEFAULT_MINIMUM_STAKE_AMOUNT, address(this)); + + // Second call should fail + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.MaxChurnRateExceeded.selector, + churnThreshold + _valueToWeight(DEFAULT_MINIMUM_STAKE_AMOUNT) + ) + ); + _initializeValidatorRegistration( + ValidatorRegistrationInput({ + nodeID: DEFAULT_NODE_ID, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER, + registrationExpiry: DEFAULT_REGISTRATION_TIMESTAMP + 1 + }), + _valueToWeight(DEFAULT_MINIMUM_STAKE_AMOUNT) + ); + } + + function testCumulativeChurnRegistrationAndEndValidation() public { + // Registration should succeed + bytes32 validationID = _registerValidator({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: _valueToWeight(DEFAULT_MINIMUM_STAKE_AMOUNT), + registrationExpiry: DEFAULT_EXPIRY, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP + }); + + uint64 churnThreshold = + uint64(DEFAULT_STARTING_TOTAL_WEIGHT) * DEFAULT_MAXIMUM_CHURN_PERCENTAGE / 100; + _beforeSend(_weightToValue(churnThreshold), address(this)); + + // Registration should succeed + _registerValidator({ + nodeID: _newNodeID(), + subnetID: DEFAULT_SUBNET_ID, + weight: churnThreshold, + registrationExpiry: DEFAULT_EXPIRY + 25 hours, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP + 25 hours + }); + + // Second call should fail + // The first registration churn amount is not part of the new churn amount since + // a new churn period has started. + vm.expectRevert( + abi.encodeWithSelector( + ValidatorManager.MaxChurnRateExceeded.selector, + _valueToWeight(DEFAULT_MINIMUM_STAKE_AMOUNT) + churnThreshold + ) + ); + _initializeEndValidation(validationID, false); + } + + function testValidatorManagerStorageSlot() public view { + assertEq( + _erc7201StorageSlot("ValidatorManager"), + validatorManager.VALIDATOR_MANAGER_STORAGE_LOCATION() + ); + } + + function _newNodeID() internal returns (bytes memory) { + nodeIDCounter++; + return abi.encodePacked(sha256(new bytes(nodeIDCounter))); + } + + function _setUpInitializeValidatorRegistration( + bytes memory nodeID, + bytes32 subnetID, + uint64 weight, + uint64 registrationExpiry, + bytes memory blsPublicKey + ) internal returns (bytes32 validationID) { + (validationID,) = ValidatorMessages.packRegisterSubnetValidatorMessage( + ValidatorMessages.ValidationPeriod({ + nodeID: nodeID, + subnetID: subnetID, + blsPublicKey: blsPublicKey, + registrationExpiry: registrationExpiry, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER, + weight: weight + }) + ); + (, bytes memory registerSubnetValidatorMessage) = ValidatorMessages + .packRegisterSubnetValidatorMessage( + ValidatorMessages.ValidationPeriod({ + subnetID: subnetID, + nodeID: nodeID, + blsPublicKey: blsPublicKey, + registrationExpiry: registrationExpiry, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER, + weight: weight + }) + ); + vm.warp(registrationExpiry - 1); + _mockSendWarpMessage(registerSubnetValidatorMessage, bytes32(0)); + + _beforeSend(_weightToValue(weight), address(this)); + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidationPeriodCreated(validationID, nodeID, bytes32(0), weight, registrationExpiry); + + _initializeValidatorRegistration( + ValidatorRegistrationInput({ + nodeID: nodeID, + blsPublicKey: blsPublicKey, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER, + registrationExpiry: registrationExpiry + }), + weight + ); + } + + function _registerValidator( + bytes memory nodeID, + bytes32 subnetID, + uint64 weight, + uint64 registrationExpiry, + bytes memory blsPublicKey, + uint64 registrationTimestamp + ) internal returns (bytes32 validationID) { + validationID = _setUpInitializeValidatorRegistration( + nodeID, subnetID, weight, registrationExpiry, blsPublicKey + ); + bytes memory subnetValidatorRegistrationMessage = + ValidatorMessages.packSubnetValidatorRegistrationMessage(validationID, true); + + _mockGetPChainWarpMessage(subnetValidatorRegistrationMessage, true); + + vm.warp(registrationTimestamp); + vm.expectEmit(true, true, true, true, address(validatorManager)); + emit ValidationPeriodRegistered(validationID, weight, registrationTimestamp); + + validatorManager.completeValidatorRegistration(0); + } + + function _initializeEndValidation( + bytes32 validationID, + uint64 registrationTimestamp, + uint64 completionTimestamp, + uint64 expectedNonce, + bool includeUptime, + bool force + ) internal { + bytes memory setValidatorWeightPayload = + ValidatorMessages.packSubnetValidatorWeightMessage(validationID, expectedNonce, 0); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); + + if (includeUptime) { + bytes memory uptimeMsg = ValidatorMessages.packValidationUptimeMessage( + validationID, completionTimestamp - registrationTimestamp + ); + _mockGetUptimeWarpMessage(uptimeMsg, true); + _mockGetBlockchainID(); + } + + vm.warp(completionTimestamp); + if (force) { + _forceInitializeEndValidation(validationID, includeUptime); + } else { + _initializeEndValidation(validationID, includeUptime); + } + } + + function _registerDefaultValidator() internal returns (bytes32 validationID) { + return _registerValidator({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: DEFAULT_WEIGHT, + registrationExpiry: DEFAULT_EXPIRY, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP + }); + } + + function _mockSendWarpMessage(bytes memory payload, bytes32 expectedMessageID) internal { + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(expectedMessageID) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.sendWarpMessage, payload) + ); + } + + function _mockGetPChainWarpMessage(bytes memory expectedPayload, bool valid) internal { + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: validatorManager.P_CHAIN_BLOCKCHAIN_ID(), + originSenderAddress: address(0), + payload: expectedPayload + }), + valid + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + } + + function _mockGetUptimeWarpMessage(bytes memory expectedPayload, bool valid) internal { + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: DEFAULT_SOURCE_BLOCKCHAIN_ID, + originSenderAddress: address(0), + payload: expectedPayload + }), + valid + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + } + + function _mockGetBlockchainID() internal { + _mockGetBlockchainID(DEFAULT_SOURCE_BLOCKCHAIN_ID); + } + + function _mockGetBlockchainID(bytes32 blockchainID) internal { + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getBlockchainID.selector), + abi.encode(blockchainID) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeWithSelector(IWarpMessenger.getBlockchainID.selector) + ); + } + + function _mockInitializeValidatorSet() internal { + _mockGetPChainWarpMessage( + ValidatorMessages.packSubnetConversionMessage(DEFAULT_SUBNET_CONVERSION_ID), true + ); + } + + function _initializeValidatorRegistration( + ValidatorRegistrationInput memory input, + uint64 weight + ) internal virtual returns (bytes32); + + function _initializeEndValidation(bytes32 validationID, bool includeUptime) internal virtual; + + function _forceInitializeEndValidation( + bytes32 validationID, + bool includeUptime + ) internal virtual; + + function _setUp() internal virtual returns (IValidatorManager); + + function _beforeSend(uint256 amount, address spender) internal virtual; + + function _defaultSubnetConversionData() internal view returns (SubnetConversionData memory) { + InitialValidator[] memory initialValidators = new InitialValidator[](2); + // The first initial validator has a high weight relative to the default PoS validator weight + // to avoid churn issues + initialValidators[0] = InitialValidator({ + nodeID: DEFAULT_INITIAL_VALIDATOR_NODE_ID_1, + weight: DEFAULT_INITIAL_VALIDATOR_WEIGHT, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY + }); + // The second initial validator has a low weight so that it can be safely removed in tests + initialValidators[1] = InitialValidator({ + nodeID: DEFAULT_INITIAL_VALIDATOR_NODE_ID_2, + weight: DEFAULT_WEIGHT, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY + }); + return SubnetConversionData({ + subnetID: DEFAULT_SUBNET_ID, + validatorManagerBlockchainID: DEFAULT_SOURCE_BLOCKCHAIN_ID, + validatorManagerAddress: address(validatorManager), + initialValidators: initialValidators + }); + } + + function _defaultSubnetConversionDataWeightsTooLow() + internal + view + returns (SubnetConversionData memory) + { + InitialValidator[] memory initialValidators = new InitialValidator[](2); + + initialValidators[0] = InitialValidator({ + nodeID: DEFAULT_INITIAL_VALIDATOR_NODE_ID_1, + weight: 1, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY + }); + initialValidators[1] = InitialValidator({ + nodeID: DEFAULT_INITIAL_VALIDATOR_NODE_ID_2, + weight: 3, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY + }); + + return SubnetConversionData({ + subnetID: DEFAULT_SUBNET_ID, + validatorManagerBlockchainID: DEFAULT_SOURCE_BLOCKCHAIN_ID, + validatorManagerAddress: address(validatorManager), + initialValidators: initialValidators + }); + } + + function _defaultSubnetConversionDataTotalWeight5() + internal + view + returns (SubnetConversionData memory) + { + InitialValidator[] memory initialValidators = new InitialValidator[](2); + + initialValidators[0] = InitialValidator({ + nodeID: DEFAULT_INITIAL_VALIDATOR_NODE_ID_1, + weight: 1, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY + }); + initialValidators[1] = InitialValidator({ + nodeID: DEFAULT_INITIAL_VALIDATOR_NODE_ID_2, + weight: 4, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY + }); + + return SubnetConversionData({ + subnetID: DEFAULT_SUBNET_ID, + validatorManagerBlockchainID: DEFAULT_SOURCE_BLOCKCHAIN_ID, + validatorManagerAddress: address(validatorManager), + initialValidators: initialValidators + }); + } + + // This needs to be kept in line with the contract conversions, but we can't make external calls + // to the contract and use vm.expectRevert at the same time. + // These are okay to use for PoA as well, because they're just used for conversions inside the tests. + function _valueToWeight(uint256 value) internal pure returns (uint64) { + return uint64(value / 1e12); + } + + // This needs to be kept in line with the contract conversions, but we can't make external calls + // to the contract and use vm.expectRevert at the same time. + // These are okay to use for PoA as well, because they're just used for conversions inside the tests. + function _weightToValue(uint64 weight) internal pure returns (uint256) { + return uint256(weight) * 1e12; + } + + function _erc7201StorageSlot(bytes memory storageName) internal pure returns (bytes32) { + return keccak256( + abi.encode( + uint256(keccak256(abi.encodePacked("avalanche-icm.storage.", storageName))) - 1 + ) + ) & ~bytes32(uint256(0xff)); + } +} +// solhint-enable no-empty-blocks diff --git a/contracts/validator-manager/tests/ValidatorMessagesTests.t.sol b/contracts/validator-manager/tests/ValidatorMessagesTests.t.sol new file mode 100644 index 000000000..12fe198c9 --- /dev/null +++ b/contracts/validator-manager/tests/ValidatorMessagesTests.t.sol @@ -0,0 +1,98 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {ValidatorMessages} from "../ValidatorMessages.sol"; +import {PChainOwner} from "../interfaces/IValidatorManager.sol"; + +contract ValidatorMessagesTest is Test { + bytes32 public constant DEFAULT_SUBNET_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes public constant DEFAULT_NODE_ID = + bytes(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes public constant DEFAULT_BLS_PUBLIC_KEY = bytes( + hex"123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" + ); + bytes32 public constant DEFAULT_VALIDATION_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + uint64 public constant DEFAULT_WEIGHT = 1e6; + uint64 public constant DEFAULT_EXPIRY = 1000; + // solhint-disable-next-line var-name-mixedcase + PChainOwner public DEFAULT_P_CHAIN_OWNER; + + function setUp() public { + address[] memory addresses = new address[](1); + addresses[0] = 0x1234567812345678123456781234567812345678; + DEFAULT_P_CHAIN_OWNER = PChainOwner({threshold: 1, addresses: addresses}); + } + + function testRegisterSubnetValidatorMessage() public view { + (bytes32 validationID, bytes memory packed) = ValidatorMessages + .packRegisterSubnetValidatorMessage( + ValidatorMessages.ValidationPeriod({ + subnetID: DEFAULT_SUBNET_ID, + nodeID: DEFAULT_NODE_ID, + registrationExpiry: DEFAULT_EXPIRY, + blsPublicKey: DEFAULT_BLS_PUBLIC_KEY, + remainingBalanceOwner: DEFAULT_P_CHAIN_OWNER, + disableOwner: DEFAULT_P_CHAIN_OWNER, + weight: DEFAULT_WEIGHT + }) + ); + + ValidatorMessages.ValidationPeriod memory info = + ValidatorMessages.unpackRegisterSubnetValidatorMessage(packed); + assertEq(info.subnetID, DEFAULT_SUBNET_ID); + assertEq(info.nodeID, DEFAULT_NODE_ID); + assertEq(info.weight, DEFAULT_WEIGHT); + assertEq(info.registrationExpiry, DEFAULT_EXPIRY); + assertEq(info.blsPublicKey, DEFAULT_BLS_PUBLIC_KEY); + + (bytes32 recoveredID,) = ValidatorMessages.packRegisterSubnetValidatorMessage(info); + assertEq(recoveredID, validationID); + } + + function testSubnetValidatorRegistrationMessage() public pure { + bytes memory packed = + ValidatorMessages.packSubnetValidatorRegistrationMessage(DEFAULT_VALIDATION_ID, true); + (bytes32 validationID, bool valid) = + ValidatorMessages.unpackSubnetValidatorRegistrationMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assert(valid); + } + + function testSetSubnetValidatorWeightMessage() public pure { + bytes memory packed = ValidatorMessages.packSubnetValidatorWeightMessage( + DEFAULT_VALIDATION_ID, 100, DEFAULT_WEIGHT + ); + (bytes32 validationID, uint64 nonce, uint64 weight) = + ValidatorMessages.unpackSubnetValidatorWeightMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assertEq(nonce, 100); + assertEq(weight, DEFAULT_WEIGHT); + } + + function testSubnetValidatorWeightUpdateMessag() public pure { + bytes memory packed = ValidatorMessages.packSubnetValidatorWeightMessage( + DEFAULT_VALIDATION_ID, 100, DEFAULT_WEIGHT + ); + (bytes32 validationID, uint64 nonce, uint64 weight) = + ValidatorMessages.unpackSubnetValidatorWeightMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assertEq(nonce, 100); + assertEq(weight, DEFAULT_WEIGHT); + } + + function testValidationUptimeMessage() public pure { + bytes memory packed = + ValidatorMessages.packValidationUptimeMessage(DEFAULT_VALIDATION_ID, 100); + (bytes32 validationID, uint64 uptime) = + ValidatorMessages.unpackValidationUptimeMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assertEq(uptime, 100); + } +} diff --git a/go.mod b/go.mod index e10c64822..e1679544d 100644 --- a/go.mod +++ b/go.mod @@ -3,33 +3,36 @@ module github.com/ava-labs/teleporter go 1.22.8 require ( - github.com/ava-labs/avalanchego v1.11.11 + github.com/ava-labs/avalanchego v1.12.0-initial-poc.5 github.com/supranational/blst v0.3.11 // indirect ) require ( - github.com/ava-labs/subnet-evm v0.6.9 + github.com/ava-labs/awm-relayer v1.4.1-0.20241010161724-2db445c994d6 + github.com/ava-labs/subnet-evm v0.6.10 github.com/ethereum/go-ethereum v1.13.14 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.20.4 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 golang.org/x/tools v0.26.0 + google.golang.org/protobuf v1.35.1 ) require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect - github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732 // indirect + github.com/ava-labs/coreth v0.13.8 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect @@ -58,7 +61,6 @@ require ( github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect @@ -67,11 +69,12 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/rpc v1.2.0 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect @@ -80,27 +83,27 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackpal/gateway v1.0.6 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/klauspost/compress v1.15.15 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pingcap/errors v0.11.4 // indirect github.com/pires/go-proxyproto v0.6.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/rs/cors v1.7.0 // indirect @@ -140,10 +143,9 @@ require ( golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.3.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/grpc v1.64.1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 56b8188b8..761e8a12c 100644 --- a/go.sum +++ b/go.sum @@ -56,12 +56,14 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanchego v1.11.11 h1:MIQq8xRavRj4ZXHA4G+aMiymig7SOScGOG1SApmMvBc= -github.com/ava-labs/avalanchego v1.11.11/go.mod h1:yFx3V31Jy9NFa8GZlgGnwiVf8KGjeF2+Uc99l9Scd/8= -github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732 h1:wlhGJbmb7s3bU2QWtxKjscGjfHknQiq+cVhhUjONsB8= -github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732/go.mod h1:RkQLaQ961Xe/sUb3ycn4Qi18vPPuEetTqDf2eDcquAs= -github.com/ava-labs/subnet-evm v0.6.9 h1:0FSPjbysSudOlMD/d0ivkli50d2ixpX3sXCi7XHfPbc= -github.com/ava-labs/subnet-evm v0.6.9/go.mod h1:dw4kg0o58dvYlndj2ZcwB7hioRc1kjg00yXYrcSmnj8= +github.com/ava-labs/avalanchego v1.12.0-initial-poc.5 h1:gW4xAqZNvkA4gP8M9yDyd7YUzuwfQbbCR+hgd1ztOto= +github.com/ava-labs/avalanchego v1.12.0-initial-poc.5/go.mod h1:qSHmog3wMVjo/ruIAQo0ppXAilyni07NIu5K88RyhWE= +github.com/ava-labs/awm-relayer v1.4.1-0.20241010161724-2db445c994d6 h1:WdFWoZ8clWfTPp3cKyWYTsveMKW/0SQzWk8U1aCcdnw= +github.com/ava-labs/awm-relayer v1.4.1-0.20241010161724-2db445c994d6/go.mod h1:6eqh3V1Og40gXmZUOP6tCrlmMEcVuj9l737yYh1s8uw= +github.com/ava-labs/coreth v0.13.8 h1:f14X3KgwHl9LwzfxlN6S4bbn5VA2rhEsNnHaRLSTo/8= +github.com/ava-labs/coreth v0.13.8/go.mod h1:t3BSv/eQv0AlDPMfEDCMMoD/jq1RkUsbFzQAFg5qBcE= +github.com/ava-labs/subnet-evm v0.6.10 h1:uIh6bFMA4GCMVMQ3agBPxTMlYHL8FBR5FrhMR+drfKI= +github.com/ava-labs/subnet-evm v0.6.10/go.mod h1:dw4kg0o58dvYlndj2ZcwB7hioRc1kjg00yXYrcSmnj8= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -96,8 +98,9 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -231,8 +234,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -316,12 +319,12 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk= github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -329,6 +332,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= @@ -376,8 +381,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -415,8 +420,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -436,6 +439,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -480,15 +485,15 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -964,10 +969,10 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -986,8 +991,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1000,8 +1005,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/lib/forge-std b/lib/forge-std index 1714bee72..c28115db8 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 1714bee72e286e73f76e320d110e0eaf5c4e649d +Subproject commit c28115db8d90ebffb41953cf83aac63130f4bd40 diff --git a/lib/subnet-evm b/lib/subnet-evm index a42c7c151..566b5bca7 160000 --- a/lib/subnet-evm +++ b/lib/subnet-evm @@ -1 +1 @@ -Subproject commit a42c7c1518d4cf7f8220ff0c5b946f055e8f3b34 +Subproject commit 566b5bca78fcd748e596c0581554c30b93eda2a1 diff --git a/scripts/abi_bindings.sh b/scripts/abi_bindings.sh index 737b13eec..10713f2b2 100755 --- a/scripts/abi_bindings.sh +++ b/scripts/abi_bindings.sh @@ -16,7 +16,11 @@ export ARCH=$(uname -m) [ $ARCH = x86_64 ] && ARCH=amd64 echo "ARCH set to $ARCH" -DEFAULT_CONTRACT_LIST="TeleporterMessenger TeleporterRegistry ExampleERC20 TestMessenger ValidatorSetSig" +DEFAULT_CONTRACT_LIST="TeleporterMessenger TeleporterRegistry ExampleERC20 ExampleRewardCalculator TestMessenger ValidatorSetSig NativeTokenStakingManager ERC20TokenStakingManager PoAValidatorManager" + +PROXY_LIST="TransparentUpgradeableProxy ProxyAdmin" + +SUBNET_EVM_LIST="INativeMinter" CONTRACT_LIST= HELP= @@ -50,7 +54,7 @@ go install github.com/ava-labs/subnet-evm/cmd/abigen@${SUBNET_EVM_VERSION} # compilations that did not generate new ABI files. echo "Building Contracts" cd $TELEPORTER_PATH -forge build --force --extra-output-files abi bin +forge build --skip test --optimizer-runs 100 --force --extra-output-files abi bin function convertToLower() { if [ "$ARCH" = 'arm64' ]; then @@ -60,6 +64,30 @@ function convertToLower() { fi } +function generate_bindings() { + local contract_names=("$@") + for contract_name in "${contract_names[@]}" + do + path=$(find . -name $contract_name.sol) + dir=$(dirname $path) + abi_file=$TELEPORTER_PATH/out/$contract_name.sol/$contract_name.abi.json + if ! [ -f $abi_file ]; then + echo "Error: Contract $contract_name abi file not found" + exit 1 + fi + + echo "Generating Go bindings for $contract_name..." + gen_path=$TELEPORTER_PATH/abi-bindings/go/$dir/$contract_name + mkdir -p $gen_path + $GOPATH/bin/abigen --abi $abi_file \ + --pkg $(convertToLower $contract_name) \ + --bin $TELEPORTER_PATH/out/$contract_name.sol/$contract_name.bin \ + --type $contract_name \ + --out $gen_path/$contract_name.go + echo "Done generating Go bindings for $contract_name." + done +} + contract_names=($CONTRACT_LIST) # If CONTRACT_LIST is empty, use DEFAULT_CONTRACT_LIST @@ -68,25 +96,20 @@ if [[ -z "${CONTRACT_LIST}" ]]; then fi cd $TELEPORTER_PATH/contracts -for contract_name in "${contract_names[@]}" -do - path=$(find . -name $contract_name.sol) - dir=$(dirname $path) - abi_file=$TELEPORTER_PATH/out/$contract_name.sol/$contract_name.abi.json - if ! [ -f $abi_file ]; then - echo "Error: Contract $contract_name abi file not found" - exit 1 - fi +generate_bindings "${contract_names[@]}" - echo "Generating Go bindings for $contract_name..." - gen_path=$TELEPORTER_PATH/abi-bindings/go/$dir/$contract_name - mkdir -p $gen_path - $GOPATH/bin/abigen --abi $abi_file \ - --pkg $(convertToLower $contract_name) \ - --bin $TELEPORTER_PATH/out/$contract_name.sol/$contract_name.bin \ - --type $contract_name \ - --out $gen_path/$contract_name.go - echo "Done generating Go bindings for $contract_name." -done +contract_names=($PROXY_LIST) +cd $TELEPORTER_PATH/ +forge build --skip test --force --extra-output-files abi bin --contracts lib/openzeppelin-contracts/contracts/proxy/transparent + +cd $TELEPORTER_PATH/lib/openzeppelin-contracts/contracts/proxy/transparent +generate_bindings "${contract_names[@]}" + +contract_names=($SUBNET_EVM_LIST) +cd $TELEPORTER_PATH/ +forge build --skip test --force --extra-output-files abi bin --contracts lib/subnet-evm/contracts/contracts/interfaces + +cd $TELEPORTER_PATH/lib/subnet-evm/contracts/contracts/interfaces +generate_bindings "${contract_names[@]}" exit 0 diff --git a/scripts/local/e2e_test.sh b/scripts/local/e2e_test.sh index 77e516a2d..fd5647981 100755 --- a/scripts/local/e2e_test.sh +++ b/scripts/local/e2e_test.sh @@ -9,6 +9,55 @@ TELEPORTER_PATH=$( cd ../.. && pwd ) +function printHelp() { + echo "Usage: ./scripts/local/e2e_test.sh [--component component]" + echo "" + printUsage +} + +function printUsage() { + cat << EOF +Arguments: + --components component1,component2 Comma separated list of test suites to run. Valid components are: + $(echo $valid_components | tr ' ' '\n' | sort | tr '\n' ' ') + (default: all) +Options: + --help Print this help message +EOF +} + +valid_components=$(ls -d $TELEPORTER_PATH/tests/local/*/ | xargs -n 1 basename) +components= + +while [ $# -gt 0 ]; do + case "$1" in + --components) + if [[ $2 != --* ]]; then + components=$2 + else + echo "Invalid components $2" && printHelp && exit 1 + fi + shift;; + --help) + printHelp && exit 0 ;; + *) + echo "Invalid option: $1" && printHelp && exit 1;; + esac + shift +done + +# Run all suites if no component is provided +if [ -z "$components" ]; then + components=$valid_components +fi + +# Exit if invalid component is provided +for component in $(echo $components | tr ',' ' '); do + if [[ $valid_components != *$component* ]]; then + echo "Invalid component $component" && exit 1 + fi +done + source "$TELEPORTER_PATH"/scripts/constants.sh source "$TELEPORTER_PATH"/scripts/versions.sh @@ -27,7 +76,7 @@ export AVALANCHEGO_BUILD_PATH=$BASEDIR/avalanchego cd $TELEPORTER_PATH if command -v forge &> /dev/null; then - forge build + forge build --skip test --optimizer-runs 100 else echo "Forge command not found, attempting to use from $HOME" $HOME/.foundry/bin/forge build @@ -38,15 +87,18 @@ cd "$TELEPORTER_PATH" # to install the ginkgo binary (required for test build and run) go install -v github.com/onsi/ginkgo/v2/ginkgo@${GINKGO_VERSION} -ginkgo build ./tests/local/ +for component in $(echo $components | tr ',' ' '); do + echo "Building e2e tests for $component" + ginkgo build ./tests/local/$component -# Run the tests -echo "Running e2e tests $RUN_E2E" -RUN_E2E=true ./tests/local/local.test \ - --ginkgo.vv \ - --ginkgo.label-filter=${GINKGO_LABEL_FILTER:-""} \ - --ginkgo.focus=${GINKGO_FOCUS:-""} \ - --ginkgo.trace + echo "Running e2e tests for $component" + RUN_E2E=true ./tests/local/$component/$component.test \ + --ginkgo.vv \ + --ginkgo.label-filter=${GINKGO_LABEL_FILTER:-""} \ + --ginkgo.focus=${GINKGO_FOCUS:-""} \ + --ginkgo.trace -echo "e2e tests passed" + echo "$component e2e tests passed" + echo "" +done exit 0 diff --git a/scripts/versions.sh b/scripts/versions.sh index a168ee2c2..efe3fb248 100755 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -16,11 +16,15 @@ function getDepVersion() { grep -m1 "^\s*$1" $TELEPORTER_PATH/go.mod | cut -d ' ' -f2 } -extract_commit() { +function extract_commit() { local version=$1 - if [[ $version == *-* ]]; then + + # Regex for a commit hash (assumed to be a 12+ character hex string) + commit_hash_regex="-([0-9a-f]{12,})$" + + if [[ "$version" =~ $commit_hash_regex ]]; then # Extract the substring after the last '-' - version=${version##*-} + version=${BASH_REMATCH[1]} fi echo "$version" } @@ -29,9 +33,10 @@ extract_commit() { AWM_RELAYER_VERSION=${AWM_RELAYER_VERSION:-'v1.0.0'} # Don't export them as they're used in the context of other calls -AVALANCHEGO_VERSION=${AVALANCHEGO_VERSION:-$(getDepVersion github.com/ava-labs/avalanchego)} -GINKGO_VERSION=${GINKGO_VERSION:-$(getDepVersion github.com/onsi/ginkgo/v2)} -SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-$(getDepVersion github.com/ava-labs/subnet-evm)} +AVALANCHEGO_VERSION=${AVALANCHEGO_VERSION:-$(extract_commit "$(getDepVersion github.com/ava-labs/avalanchego)")} +GINKGO_VERSION=${GINKGO_VERSION:-$(extract_commit "$(getDepVersion github.com/onsi/ginkgo/v2)")} +SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-$(extract_commit "$(getDepVersion github.com/ava-labs/subnet-evm)")} + # Set golangci-lint version GOLANGCI_LINT_VERSION=${GOLANGCI_LINT_VERSION:-'v1.60'} diff --git a/tests/flows/errors.go b/tests/flows/errors.go index c3efc7ec4..9ba39996c 100644 --- a/tests/flows/errors.go +++ b/tests/flows/errors.go @@ -1,5 +1,5 @@ package flows const ( - errTxReverted = "execution reverted" + ErrTxReverted = "execution reverted" ) diff --git a/tests/flows/validator_set_sig.go b/tests/flows/governance/validator_set_sig.go similarity index 94% rename from tests/flows/validator_set_sig.go rename to tests/flows/governance/validator_set_sig.go index 5daa0f364..cb32a09e8 100644 --- a/tests/flows/validator_set_sig.go +++ b/tests/flows/governance/validator_set_sig.go @@ -1,4 +1,4 @@ -package flows +package governance import ( "context" @@ -86,7 +86,7 @@ func ValidatorSetSig(network interfaces.LocalNetwork) { // Construct a ValidatorSetSig message with mock ERC20 as the target contract // and mint 100 tokens as the TxPayload - callData, err := erc20ABI.Pack("mint", big.NewInt(100)) + callData, err := erc20ABI.Pack("mint", validatorSetSigContractAddress, big.NewInt(100)) Expect(err).Should(BeNil()) vssMessage1 := validatorsetsig.ValidatorSetSigMessage{ @@ -100,7 +100,7 @@ func ValidatorSetSig(network interfaces.LocalNetwork) { // Construct a second ValidatorSetSig message with mock ERC20 as the target contract // and mint 50 tokens as the TxPayload - callData2, err := erc20ABI.Pack("mint", big.NewInt(50)) + callData2, err := erc20ABI.Pack("mint", validatorSetSigContractAddress, big.NewInt(50)) Expect(err).Should(BeNil()) vssMessage2 := validatorsetsig.ValidatorSetSigMessage{ ValidatorSetSigAddress: validatorSetSigContractAddress, @@ -112,13 +112,18 @@ func ValidatorSetSig(network interfaces.LocalNetwork) { } // Create a message for the case where validatorSetSig contract and targetContract are on the same chain. + // Construct a ValidatorSetSig message with mock ERC20 as the target contract + // and mint 100 tokens as the TxPayload + callData3, err := erc20ABI.Pack("mint", validatorSetSigContractAddress2, big.NewInt(100)) + Expect(err).Should(BeNil()) + vssMessage3 := validatorsetsig.ValidatorSetSigMessage{ ValidatorSetSigAddress: validatorSetSigContractAddress2, TargetContractAddress: exampleERC20ContractAddressB, TargetBlockchainID: subnetB.BlockchainID, Nonce: big.NewInt(0), Value: big.NewInt(0), - Payload: callData, + Payload: callData3, } // Create chain config file with off-chain validatorsetsig message @@ -138,7 +143,7 @@ func ValidatorSetSig(network interfaces.LocalNetwork) { network.SetChainConfigs(chainConfigs) restartCtx, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel() - network.RestartNodes(restartCtx, network.GetAllNodeIDs()) + network.RestartNodes(restartCtx, nil) // ************************************************************************************************ // Test Case 1: validatorChain (subnetB) != targetChain (subnetA) diff --git a/tests/flows/add_fee_amount.go b/tests/flows/teleporter/add_fee_amount.go similarity index 71% rename from tests/flows/add_fee_amount.go rename to tests/flows/teleporter/add_fee_amount.go index 0771d450d..abf6c7932 100644 --- a/tests/flows/add_fee_amount.go +++ b/tests/flows/teleporter/add_fee_amount.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -12,10 +12,10 @@ import ( . "github.com/onsi/gomega" ) -func AddFeeAmount(network interfaces.Network) { +func AddFeeAmount(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) - teleporterContractAddress := network.GetTeleporterContractAddress() + teleporterContractAddress := teleporter.TeleporterMessengerAddress(subnetAInfo) fundedAddress, fundedKey := network.GetFundedAccountInfo() ctx := context.Background() @@ -50,7 +50,13 @@ func AddFeeAmount(network interfaces.Network) { } sendCrossChainMsgReceipt, messageID := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) + ctx, + teleporter.TeleporterMessenger(subnetAInfo), + subnetAInfo, + subnetBInfo, + sendCrossChainMessageInput, + fundedKey, + ) // Add a fee amount to the message. additionalFeeAmount := big.NewInt(2) @@ -62,23 +68,30 @@ func AddFeeAmount(network interfaces.Network) { additionalFeeAmount, mockTokenAddress, fundedKey, - subnetAInfo.TeleporterMessenger, + teleporter.TeleporterMessenger(subnetAInfo), ) // Relay message from Subnet A to Subnet B - deliveryReceipt := network.RelayMessage(ctx, sendCrossChainMsgReceipt, subnetAInfo, subnetBInfo, true) + deliveryReceipt := teleporter.RelayTeleporterMessage( + ctx, + sendCrossChainMsgReceipt, + subnetAInfo, + subnetBInfo, + true, + fundedKey, + ) receiveEvent, err := utils.GetEventFromLogs( deliveryReceipt.Logs, - subnetBInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + teleporter.TeleporterMessenger(subnetBInfo).ParseReceiveCrossChainMessage) Expect(err).Should(BeNil()) // Check Teleporter message received on the destination (Subnet B) - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID) + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived(&bind.CallOpts{}, messageID) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Check the initial relayer reward amount on Subnet A. - initialRewardAmount, err := subnetAInfo.TeleporterMessenger.CheckRelayerRewardAmount( + initialRewardAmount, err := teleporter.TeleporterMessenger(subnetAInfo).CheckRelayerRewardAmount( &bind.CallOpts{}, receiveEvent.RewardRedeemer, mockTokenAddress) @@ -87,6 +100,7 @@ func AddFeeAmount(network interfaces.Network) { // Send a message from Subnet B back to Subnet A that includes the specific receipt for the message. sendSpecificReceiptsReceipt, sendSpecificReceiptsMessageID := utils.SendSpecifiedReceiptsAndWaitForAcceptance( ctx, + teleporter.TeleporterMessenger(subnetBInfo), subnetBInfo, subnetAInfo.BlockchainID, [][32]byte{receiveEvent.MessageID}, @@ -98,16 +112,19 @@ func AddFeeAmount(network interfaces.Network) { fundedKey) // Relay message containing the specific receipt from Subnet B to Subnet A - network.RelayMessage(ctx, sendSpecificReceiptsReceipt, subnetBInfo, subnetAInfo, true) + teleporter.RelayTeleporterMessage(ctx, sendSpecificReceiptsReceipt, subnetBInfo, subnetAInfo, true, fundedKey) // Check message delivered - delivered, err = subnetAInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, sendSpecificReceiptsMessageID) + delivered, err = teleporter.TeleporterMessenger(subnetAInfo).MessageReceived( + &bind.CallOpts{}, + sendSpecificReceiptsMessageID, + ) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Check the updated relayer reward amount expectedIncrease := new(big.Int).Add(initFeeAmount, additionalFeeAmount) - newRewardAmount, err := subnetAInfo.TeleporterMessenger.CheckRelayerRewardAmount( + newRewardAmount, err := teleporter.TeleporterMessenger(subnetAInfo).CheckRelayerRewardAmount( &bind.CallOpts{}, receiveEvent.RewardRedeemer, mockTokenAddress) @@ -117,7 +134,13 @@ func AddFeeAmount(network interfaces.Network) { // If the funded address is the one able to redeem the rewards, do so and check the reward amount is reset. if fundedAddress == receiveEvent.RewardRedeemer { utils.RedeemRelayerRewardsAndConfirm( - ctx, subnetAInfo, mockToken, mockTokenAddress, fundedKey, newRewardAmount, + ctx, + teleporter.TeleporterMessenger(subnetAInfo), + subnetAInfo, + mockToken, + mockTokenAddress, + fundedKey, + newRewardAmount, ) } } diff --git a/tests/flows/basic_send_receive.go b/tests/flows/teleporter/basic_send_receive.go similarity index 78% rename from tests/flows/basic_send_receive.go rename to tests/flows/teleporter/basic_send_receive.go index 8e4f8e036..c75f24a5a 100644 --- a/tests/flows/basic_send_receive.go +++ b/tests/flows/teleporter/basic_send_receive.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -13,10 +13,10 @@ import ( ) // Tests basic one-way send from Subnet A to Subnet B and vice versa -func BasicSendReceive(network interfaces.Network) { +func BasicSendReceive(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) - teleporterContractAddress := network.GetTeleporterContractAddress() + teleporterContractAddress := teleporter.TeleporterMessengerAddress(subnetAInfo) fundedAddress, fundedKey := network.GetFundedAccountInfo() // Send a transaction to Subnet A to issue a Warp Message from the Teleporter contract to Subnet B @@ -26,7 +26,7 @@ func BasicSendReceive(network interfaces.Network) { // This is only done if the test non-external networks because external networks may have // an arbitrarily high number of receipts to be cleared from a given queue from unrelated messages. if !network.IsExternalNetwork() { - utils.ClearReceiptQueue(ctx, network, fundedKey, subnetBInfo, subnetAInfo) + utils.ClearReceiptQueue(ctx, teleporter, subnetBInfo, subnetAInfo, fundedKey) } feeAmount := big.NewInt(1) @@ -59,6 +59,7 @@ func BasicSendReceive(network interfaces.Network) { receipt, teleporterMessageID := utils.SendCrossChainMessageAndWaitForAcceptance( ctx, + teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, @@ -67,14 +68,14 @@ func BasicSendReceive(network interfaces.Network) { expectedReceiptID := teleporterMessageID // Relay the message to the destination - deliveryReceipt := network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + deliveryReceipt := teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) receiveEvent, err := utils.GetEventFromLogs( deliveryReceipt.Logs, - subnetBInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + teleporter.TeleporterMessenger(subnetBInfo).ParseReceiveCrossChainMessage) Expect(err).Should(BeNil()) // Check Teleporter message received on the destination - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) @@ -85,6 +86,7 @@ func BasicSendReceive(network interfaces.Network) { sendCrossChainMessageInput.FeeInfo.Amount = big.NewInt(0) receipt, teleporterMessageID = utils.SendCrossChainMessageAndWaitForAcceptance( ctx, + teleporter.TeleporterMessenger(subnetBInfo), subnetBInfo, subnetAInfo, sendCrossChainMessageInput, @@ -92,7 +94,7 @@ func BasicSendReceive(network interfaces.Network) { ) // Relay the message to the destination - deliveryReceipt = network.RelayMessage(ctx, receipt, subnetBInfo, subnetAInfo, true) + deliveryReceipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetBInfo, subnetAInfo, true, fundedKey) // Check that the receipt was received for expected Teleporter message ID // This check is not performed for external networks because the specific receipt for this message @@ -101,11 +103,11 @@ func BasicSendReceive(network interfaces.Network) { Expect(utils.CheckReceiptReceived( deliveryReceipt, expectedReceiptID, - subnetAInfo.TeleporterMessenger)).Should(BeTrue()) + teleporter.TeleporterMessenger(subnetAInfo))).Should(BeTrue()) } // Check Teleporter message received on the destination - delivered, err = subnetAInfo.TeleporterMessenger.MessageReceived( + delivered, err = teleporter.TeleporterMessenger(subnetAInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) @@ -116,7 +118,7 @@ func BasicSendReceive(network interfaces.Network) { // networks since the specific receipt may not have been included in the message, as noted above. if !network.IsExternalNetwork() && receiveEvent.RewardRedeemer == fundedAddress { utils.RedeemRelayerRewardsAndConfirm( - ctx, subnetAInfo, feeToken, feeTokenAddress, fundedKey, feeAmount, + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, feeToken, feeTokenAddress, fundedKey, feeAmount, ) } } diff --git a/tests/flows/deliver_to_nonexistent_contract.go b/tests/flows/teleporter/deliver_to_nonexistent_contract.go similarity index 83% rename from tests/flows/deliver_to_nonexistent_contract.go rename to tests/flows/teleporter/deliver_to_nonexistent_contract.go index d5502b26e..e5787f999 100644 --- a/tests/flows/deliver_to_nonexistent_contract.go +++ b/tests/flows/teleporter/deliver_to_nonexistent_contract.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -14,7 +14,7 @@ import ( . "github.com/onsi/gomega" ) -func DeliverToNonExistentContract(network interfaces.Network) { +func DeliverToNonExistentContract(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -44,6 +44,7 @@ func DeliverToNonExistentContract(network interfaces.Network) { ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetAInfo), subnetAInfo, ) @@ -74,7 +75,10 @@ func DeliverToNonExistentContract(network interfaces.Network) { // Wait for the transaction to be mined receipt := utils.WaitForTransactionSuccess(ctx, subnetAInfo, tx.Hash()) - sendEvent, err := utils.GetEventFromLogs(receipt.Logs, subnetAInfo.TeleporterMessenger.ParseSendCrossChainMessage) + sendEvent, err := utils.GetEventFromLogs( + receipt.Logs, + teleporter.TeleporterMessenger(subnetAInfo).ParseSendCrossChainMessage, + ) Expect(err).Should(BeNil()) Expect(sendEvent.DestinationBlockchainID[:]).Should(Equal(subnetBInfo.BlockchainID[:])) @@ -84,16 +88,16 @@ func DeliverToNonExistentContract(network interfaces.Network) { // Relay the message to the destination // log.Info("Relaying the message to the destination") - receipt = network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + receipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) receiveEvent, err := - utils.GetEventFromLogs(receipt.Logs, subnetAInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + utils.GetEventFromLogs(receipt.Logs, teleporter.TeleporterMessenger(subnetAInfo).ParseReceiveCrossChainMessage) Expect(err).Should(BeNil()) // // Check that the message was successfully relayed // log.Info("Checking the message was successfully relayed") - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) @@ -106,7 +110,7 @@ func DeliverToNonExistentContract(network interfaces.Network) { log.Info("Checking the message was not successfully executed") executionFailedEvent, err := utils.GetEventFromLogs( receipt.Logs, - subnetBInfo.TeleporterMessenger.ParseMessageExecutionFailed, + teleporter.TeleporterMessenger(subnetAInfo).ParseMessageExecutionFailed, ) Expect(err).Should(BeNil()) Expect(executionFailedEvent.MessageID).Should(Equal(receiveEvent.MessageID)) @@ -119,6 +123,7 @@ func DeliverToNonExistentContract(network interfaces.Network) { ctx, deployerKey, deployerAddress, + teleporter.TeleporterRegistryAddress(subnetBInfo), subnetBInfo, ) @@ -132,6 +137,7 @@ func DeliverToNonExistentContract(network interfaces.Network) { receipt = utils.RetryMessageExecutionAndWaitForAcceptance( ctx, subnetAInfo.BlockchainID, + teleporter.TeleporterMessenger(subnetBInfo), subnetBInfo, receiveEvent.Message, fundedKey, @@ -139,7 +145,7 @@ func DeliverToNonExistentContract(network interfaces.Network) { log.Info("Checking the message was successfully executed") messageExecutedEvent, err := utils.GetEventFromLogs( receipt.Logs, - subnetBInfo.TeleporterMessenger.ParseMessageExecuted, + teleporter.TeleporterMessenger(subnetAInfo).ParseMessageExecuted, ) Expect(err).Should(BeNil()) Expect(messageExecutedEvent.MessageID).Should(Equal(receiveEvent.MessageID)) diff --git a/tests/flows/deliver_to_wrong_chain.go b/tests/flows/teleporter/deliver_to_wrong_chain.go similarity index 85% rename from tests/flows/deliver_to_wrong_chain.go rename to tests/flows/teleporter/deliver_to_wrong_chain.go index c0c406584..1c87ccdd2 100644 --- a/tests/flows/deliver_to_wrong_chain.go +++ b/tests/flows/teleporter/deliver_to_wrong_chain.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -15,7 +15,7 @@ import ( . "github.com/onsi/gomega" ) -func DeliverToWrongChain(network interfaces.Network) { +func DeliverToWrongChain(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, subnetCInfo := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -23,7 +23,7 @@ func DeliverToWrongChain(network interfaces.Network) { // // Get the expected teleporter message ID for Subnet C // - expectedAtoCMessageID, err := subnetAInfo.TeleporterMessenger.GetNextMessageID( + expectedAtoCMessageID, err := teleporter.TeleporterMessenger(subnetAInfo).GetNextMessageID( &bind.CallOpts{}, subnetCInfo.BlockchainID, ) @@ -52,6 +52,7 @@ func DeliverToWrongChain(network interfaces.Network) { receipt, _ := utils.SendCrossChainMessageAndWaitForAcceptance( ctx, + teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, @@ -62,12 +63,12 @@ func DeliverToWrongChain(network interfaces.Network) { // // Try to relay the message to subnet C, should fail // - network.RelayMessage(ctx, receipt, subnetAInfo, subnetCInfo, false) + teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetCInfo, false, fundedKey) } else { // // Wait for external relayer to properly deliver the message to subnet B // - deliveryReceipt := network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + deliveryReceipt := teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) deliveryTx, isPending, err := subnetBInfo.RPCClient.TransactionByHash(ctx, deliveryReceipt.TxHash) Expect(err).Should(BeNil()) Expect(isPending).Should(BeFalse()) @@ -83,7 +84,7 @@ func DeliverToWrongChain(network interfaces.Network) { // // Check that the message was not received on the Subnet C // - delivered, err := subnetCInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetCInfo).MessageReceived( &bind.CallOpts{}, expectedAtoCMessageID, ) Expect(err).Should(BeNil()) diff --git a/tests/flows/insufficient_gas.go b/tests/flows/teleporter/insufficient_gas.go similarity index 76% rename from tests/flows/insufficient_gas.go rename to tests/flows/teleporter/insufficient_gas.go index bd5761f08..5af9f4ddb 100644 --- a/tests/flows/insufficient_gas.go +++ b/tests/flows/teleporter/insufficient_gas.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -10,7 +10,7 @@ import ( . "github.com/onsi/gomega" ) -func InsufficientGas(network interfaces.Network) { +func InsufficientGas(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -21,6 +21,7 @@ func InsufficientGas(network interfaces.Network) { ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetAInfo), subnetAInfo, ) // Deploy TestMessenger to Subnets B @@ -28,6 +29,7 @@ func InsufficientGas(network interfaces.Network) { ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetBInfo), subnetBInfo, ) @@ -44,24 +46,27 @@ func InsufficientGas(network interfaces.Network) { // Wait for the transaction to be mined receipt := utils.WaitForTransactionSuccess(ctx, subnetAInfo, tx.Hash()) - event, err := utils.GetEventFromLogs(receipt.Logs, subnetAInfo.TeleporterMessenger.ParseSendCrossChainMessage) + event, err := utils.GetEventFromLogs( + receipt.Logs, + teleporter.TeleporterMessenger(subnetAInfo).ParseSendCrossChainMessage, + ) Expect(err).Should(BeNil()) Expect(event.DestinationBlockchainID[:]).Should(Equal(subnetBInfo.BlockchainID[:])) messageID := event.MessageID // Relay message from SubnetA to SubnetB - receipt = network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + receipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) // Check Teleporter message received on the destination delivered, err := - subnetBInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID) + teleporter.TeleporterMessenger(subnetBInfo).MessageReceived(&bind.CallOpts{}, messageID) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Check message execution failed event failedMessageExecutionEvent, err := utils.GetEventFromLogs( - receipt.Logs, subnetBInfo.TeleporterMessenger.ParseMessageExecutionFailed, + receipt.Logs, teleporter.TeleporterMessenger(subnetBInfo).ParseMessageExecutionFailed, ) Expect(err).Should(BeNil()) Expect(failedMessageExecutionEvent.MessageID[:]).Should(Equal(messageID[:])) @@ -72,11 +77,15 @@ func InsufficientGas(network interfaces.Network) { receipt = utils.RetryMessageExecutionAndWaitForAcceptance( ctx, subnetAInfo.BlockchainID, + teleporter.TeleporterMessenger(subnetBInfo), subnetBInfo, failedMessageExecutionEvent.Message, fundedKey, ) - executedEvent, err := utils.GetEventFromLogs(receipt.Logs, subnetBInfo.TeleporterMessenger.ParseMessageExecuted) + executedEvent, err := utils.GetEventFromLogs( + receipt.Logs, + teleporter.TeleporterMessenger(subnetBInfo).ParseMessageExecuted, + ) Expect(err).Should(BeNil()) Expect(executedEvent.MessageID[:]).Should(Equal(messageID[:])) Expect(executedEvent.SourceBlockchainID[:]).Should(Equal(subnetAInfo.BlockchainID[:])) diff --git a/tests/flows/check_upgrade_access.go b/tests/flows/teleporter/registry/check_upgrade_access.go similarity index 90% rename from tests/flows/check_upgrade_access.go rename to tests/flows/teleporter/registry/check_upgrade_access.go index 023c47dd7..027db6017 100644 --- a/tests/flows/check_upgrade_access.go +++ b/tests/flows/teleporter/registry/check_upgrade_access.go @@ -1,17 +1,19 @@ -package flows +package registry import ( "context" "math/big" "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/teleporter/tests/flows" "github.com/ava-labs/teleporter/tests/interfaces" "github.com/ava-labs/teleporter/tests/utils" "github.com/ethereum/go-ethereum/crypto" + . "github.com/onsi/gomega" ) -func CheckUpgradeAccess(network interfaces.Network) { +func CheckUpgradeAccess(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetInfo := network.GetPrimaryNetworkInfo() fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -19,11 +21,12 @@ func CheckUpgradeAccess(network interfaces.Network) { // Deploy TestMessenger to the subnet // ctx := context.Background() - teleporterAddress := network.GetTeleporterContractAddress() + teleporterAddress := teleporter.TeleporterMessengerAddress(subnetInfo) _, testMessenger := utils.DeployTestMessenger( ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetInfo), subnetInfo, ) @@ -53,7 +56,7 @@ func CheckUpgradeAccess(network interfaces.Network) { Expect(err).Should(BeNil()) _, err = testMessenger.PauseTeleporterAddress(nonOwnerOpts, teleporterAddress) Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(ContainSubstring(errTxReverted)) + Expect(err.Error()).Should(ContainSubstring(flows.ErrTxReverted)) // Check that the teleporter address is not paused, because previous call should have failed isPaused, err := testMessenger.IsTeleporterAddressPaused(&bind.CallOpts{}, teleporterAddress) @@ -84,7 +87,7 @@ func CheckUpgradeAccess(network interfaces.Network) { // Try to call unpauseTeleporterAddress from the previous owner account _, err = testMessenger.UnpauseTeleporterAddress(ownerOpts, teleporterAddress) Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(ContainSubstring(errTxReverted)) + Expect(err.Error()).Should(ContainSubstring(flows.ErrTxReverted)) // Make sure the teleporter address is still paused isPaused, err = testMessenger.IsTeleporterAddressPaused(&bind.CallOpts{}, teleporterAddress) diff --git a/tests/flows/pause_teleporter.go b/tests/flows/teleporter/registry/pause_teleporter.go similarity index 88% rename from tests/flows/pause_teleporter.go rename to tests/flows/teleporter/registry/pause_teleporter.go index 8cde4a3ad..58fd4ded2 100644 --- a/tests/flows/pause_teleporter.go +++ b/tests/flows/teleporter/registry/pause_teleporter.go @@ -1,4 +1,4 @@ -package flows +package registry import ( "context" @@ -9,7 +9,7 @@ import ( . "github.com/onsi/gomega" ) -func PauseTeleporter(network interfaces.Network) { +func PauseTeleporter(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -18,17 +18,19 @@ func PauseTeleporter(network interfaces.Network) { // Deploy TestMessenger to Subnets A and B // ctx := context.Background() - teleporterAddress := network.GetTeleporterContractAddress() + teleporterAddress := teleporter.TeleporterMessengerAddress(subnetAInfo) _, testMessengerA := utils.DeployTestMessenger( ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetAInfo), subnetAInfo, ) testMessengerAddressB, testMessengerB := utils.DeployTestMessenger( ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetBInfo), subnetBInfo, ) @@ -51,7 +53,7 @@ func PauseTeleporter(network interfaces.Network) { // Send a message from subnet A to subnet B, which should fail utils.SendExampleCrossChainMessageAndVerify( ctx, - network, + teleporter, subnetAInfo, testMessengerA, subnetBInfo, @@ -77,7 +79,7 @@ func PauseTeleporter(network interfaces.Network) { // Send a message from subnet A to subnet B again, which should now succeed utils.SendExampleCrossChainMessageAndVerify( ctx, - network, + teleporter, subnetAInfo, testMessengerA, subnetBInfo, diff --git a/tests/flows/teleporter_registry.go b/tests/flows/teleporter/registry/teleporter_registry.go similarity index 80% rename from tests/flows/teleporter_registry.go rename to tests/flows/teleporter/registry/teleporter_registry.go index 11049fe0d..a43ae276b 100644 --- a/tests/flows/teleporter_registry.go +++ b/tests/flows/teleporter/registry/teleporter_registry.go @@ -1,4 +1,4 @@ -package flows +package registry import ( "context" @@ -7,6 +7,7 @@ import ( "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/teleporter/tests/interfaces" "github.com/ava-labs/teleporter/tests/utils" + "github.com/ethereum/go-ethereum/common" . "github.com/onsi/gomega" ) @@ -14,7 +15,7 @@ const ( teleporterByteCodeFile = "./out/TeleporterMessenger.sol/TeleporterMessenger.json" ) -func TeleporterRegistry(network interfaces.LocalNetwork) { +func TeleporterRegistry(network interfaces.LocalNetwork, teleporter utils.TeleporterTestInfo) { // Deploy dApp on both chains that use Teleporter Registry // Deploy version 2 of Teleporter to both chains // Construct AddProtocolVersion txs for both chains @@ -37,34 +38,42 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(cChainInfo), cChainInfo, ) testMessengerContractB, testMessengerB := utils.DeployTestMessenger( ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetBInfo), subnetBInfo, ) // Deploy the new version of Teleporter to both chains - newTeleporterAddress := utils.DeployNewTeleporterVersion(ctx, network, fundedKey, teleporterByteCodeFile) + var newTeleporterAddress common.Address + for _, subnet := range network.GetAllSubnetsInfo() { + newTeleporterAddress = utils.DeployNewTeleporterVersion(ctx, teleporter, subnet, fundedKey, teleporterByteCodeFile) + } networkID := network.GetNetworkID() // Create chain config file with off chain message for each chain offchainMessageC, warpEnabledChainConfigC := utils.InitOffChainMessageChainConfig( networkID, cChainInfo, + teleporter.TeleporterRegistryAddress(cChainInfo), newTeleporterAddress, 2, ) offchainMessageB, warpEnabledChainConfigB := utils.InitOffChainMessageChainConfig( networkID, subnetBInfo, + teleporter.TeleporterRegistryAddress(subnetBInfo), newTeleporterAddress, 2, ) offchainMessageA, warpEnabledChainConfigA := utils.InitOffChainMessageChainConfig( networkID, subnetAInfo, + teleporter.TeleporterRegistryAddress(subnetAInfo), newTeleporterAddress, 2, ) @@ -79,12 +88,12 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { network.SetChainConfigs(chainConfigs) restartCtx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() - network.RestartNodes(restartCtx, network.GetAllNodeIDs()) + network.RestartNodes(restartCtx, nil) // Call addProtocolVersion on subnetB to register the new Teleporter version utils.AddProtocolVersionAndWaitForAcceptance( ctx, - network, + *teleporter[subnetBInfo.BlockchainID], subnetBInfo, newTeleporterAddress, fundedKey, @@ -95,7 +104,7 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { // Message should be received successfully since we haven't updated mininum Teleporter version yet. utils.SendExampleCrossChainMessageAndVerify( ctx, - network, + teleporter, cChainInfo, testMessengerC, subnetBInfo, @@ -110,7 +119,7 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { opts, err := bind.NewKeyedTransactorWithChainID(fundedKey, subnetBInfo.EVMChainID) Expect(err).Should(BeNil()) - latestVersionB, err := subnetBInfo.TeleporterRegistry.LatestVersion(&bind.CallOpts{}) + latestVersionB, err := teleporter.TeleporterRegistry(subnetBInfo).LatestVersion(&bind.CallOpts{}) Expect(err).Should(BeNil()) minTeleporterVersion, err := testMessengerB.GetMinTeleporterVersion(&bind.CallOpts{}) Expect(err).Should(BeNil()) @@ -132,7 +141,7 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { // Message should fail since we updated minimum Teleporter version. utils.SendExampleCrossChainMessageAndVerify( ctx, - network, + teleporter, cChainInfo, testMessengerC, subnetBInfo, @@ -143,14 +152,15 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { false, ) - // Update the subnets to use new Teleporter messengers - network.SetTeleporterContractAddress(newTeleporterAddress) - cChainInfo = network.GetPrimaryNetworkInfo() - subnetAInfo, subnetBInfo = utils.GetTwoSubnets(network) + // Update teleporter with the new TeleporterMessengers + for _, subnet := range network.GetAllSubnetsInfo() { + teleporter.SetTeleporter(newTeleporterAddress, subnet) + teleporter.InitializeBlockchainID(subnet, fundedKey) + } utils.SendExampleCrossChainMessageAndVerify( ctx, - network, + teleporter, subnetBInfo, testMessengerB, cChainInfo, @@ -164,7 +174,7 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { // Call addProtocolVersion on subnetA to register the new Teleporter version utils.AddProtocolVersionAndWaitForAcceptance( ctx, - network, + *teleporter[cChainInfo.BlockchainID], cChainInfo, newTeleporterAddress, fundedKey, @@ -175,7 +185,7 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { // Teleporter versions should match, so message should be received successfully. utils.SendExampleCrossChainMessageAndVerify( ctx, - network, + teleporter, subnetBInfo, testMessengerB, cChainInfo, @@ -190,18 +200,18 @@ func TeleporterRegistry(network interfaces.LocalNetwork) { // to register the new Teleporter version utils.AddProtocolVersionAndWaitForAcceptance( ctx, - network, + *teleporter[subnetAInfo.BlockchainID], subnetAInfo, newTeleporterAddress, fundedKey, offchainMessageA, ) - latestVersionA, err := subnetAInfo.TeleporterRegistry.LatestVersion(&bind.CallOpts{}) + latestVersionA, err := teleporter.TeleporterRegistry(subnetAInfo).LatestVersion(&bind.CallOpts{}) Expect(err).Should(BeNil()) Expect(latestVersionA.Cmp(latestVersionB)).Should(Equal(0)) - latestVersionC, err := cChainInfo.TeleporterRegistry.LatestVersion(&bind.CallOpts{}) + latestVersionC, err := teleporter.TeleporterRegistry(cChainInfo).LatestVersion(&bind.CallOpts{}) Expect(err).Should(BeNil()) Expect(latestVersionC.Cmp(latestVersionB)).Should(Equal(0)) } diff --git a/tests/flows/relay_message_twice.go b/tests/flows/teleporter/relay_message_twice.go similarity index 78% rename from tests/flows/relay_message_twice.go rename to tests/flows/teleporter/relay_message_twice.go index 3c91b7cd9..dc28cc763 100644 --- a/tests/flows/relay_message_twice.go +++ b/tests/flows/teleporter/relay_message_twice.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -14,7 +14,7 @@ import ( . "github.com/onsi/gomega" ) -func RelayMessageTwice(network interfaces.Network) { +func RelayMessageTwice(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -41,19 +41,19 @@ func RelayMessageTwice(network interfaces.Network) { "destinationBlockchainID", subnetBInfo.BlockchainID, ) receipt, teleporterMessageID := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey, + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey, ) // // Relay the message to the destination // - network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) // // Check Teleporter message received on the destination // log.Info("Checking the message was received on the destination") - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) @@ -63,5 +63,5 @@ func RelayMessageTwice(network interfaces.Network) { // Attempt to send the same message again, should fail // log.Info("Relaying the same Teleporter message again on the destination") - network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, false) + teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, false, fundedKey) } diff --git a/tests/flows/relayer_modifies_message.go b/tests/flows/teleporter/relayer_modifies_message.go similarity index 87% rename from tests/flows/relayer_modifies_message.go rename to tests/flows/teleporter/relayer_modifies_message.go index a0999f6b1..32c1385d4 100644 --- a/tests/flows/relayer_modifies_message.go +++ b/tests/flows/teleporter/relayer_modifies_message.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -22,7 +22,7 @@ import ( ) // Disallow this test from being run on anything but a local network, since it requires special behavior by the relayer -func RelayerModifiesMessage(network interfaces.LocalNetwork) { +func RelayerModifiesMessage(network interfaces.LocalNetwork, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -43,35 +43,40 @@ func RelayerModifiesMessage(network interfaces.LocalNetwork) { } receipt, messageID := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) // Relay the message to the destination // Relayer modifies the message in flight relayAlteredMessage( ctx, + teleporter, receipt, subnetAInfo, subnetBInfo, network) // Check Teleporter message was not received on the destination - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID) + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived(&bind.CallOpts{}, messageID) Expect(err).Should(BeNil()) Expect(delivered).Should(BeFalse()) } func relayAlteredMessage( ctx context.Context, + teleporter utils.TeleporterTestInfo, sourceReceipt *types.Receipt, source interfaces.SubnetTestInfo, destination interfaces.SubnetTestInfo, network interfaces.LocalNetwork, ) { // Fetch the Teleporter message from the logs - sendEvent, err := utils.GetEventFromLogs(sourceReceipt.Logs, source.TeleporterMessenger.ParseSendCrossChainMessage) + sendEvent, err := utils.GetEventFromLogs( + sourceReceipt.Logs, + teleporter.TeleporterMessenger(source).ParseSendCrossChainMessage, + ) Expect(err).Should(BeNil()) - signedWarpMessage := network.ConstructSignedWarpMessage(ctx, sourceReceipt, source, destination) + signedWarpMessage := utils.ConstructSignedWarpMessage(ctx, sourceReceipt, source, destination) // Construct the transaction to send the Warp message to the destination chain _, fundedKey := network.GetFundedAccountInfo() @@ -80,7 +85,7 @@ func relayAlteredMessage( signedWarpMessage, &sendEvent.Message, sendEvent.Message.RequiredGasLimit, - network.GetTeleporterContractAddress(), + teleporter.TeleporterMessengerAddress(source), fundedKey, destination, ) diff --git a/tests/flows/resubmit_altered_message.go b/tests/flows/teleporter/resubmit_altered_message.go similarity index 77% rename from tests/flows/resubmit_altered_message.go rename to tests/flows/teleporter/resubmit_altered_message.go index 18435a9df..dcc47c75f 100644 --- a/tests/flows/resubmit_altered_message.go +++ b/tests/flows/teleporter/resubmit_altered_message.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -13,7 +13,7 @@ import ( . "github.com/onsi/gomega" ) -func ResubmitAlteredMessage(network interfaces.Network) { +func ResubmitAlteredMessage(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -34,18 +34,21 @@ func ResubmitAlteredMessage(network interfaces.Network) { } receipt, messageID := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) // Relay the message to the destination - receipt = network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + receipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) log.Info("Checking the message was received on the destination") - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID) + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived(&bind.CallOpts{}, messageID) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Get the Teleporter message from receive event - event, err := utils.GetEventFromLogs(receipt.Logs, subnetBInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + event, err := utils.GetEventFromLogs( + receipt.Logs, + teleporter.TeleporterMessenger(subnetBInfo).ParseReceiveCrossChainMessage, + ) Expect(err).Should(BeNil()) Expect(event.MessageID[:]).Should(Equal(messageID[:])) teleporterMessage := event.Message @@ -61,7 +64,7 @@ func ResubmitAlteredMessage(network interfaces.Network) { log.Info("Submitting the altered Teleporter message on the source chain") opts, err := bind.NewKeyedTransactorWithChainID(fundedKey, subnetAInfo.EVMChainID) Expect(err).Should(BeNil()) - tx, err := subnetAInfo.TeleporterMessenger.RetrySendCrossChainMessage(opts, teleporterMessage) + tx, err := teleporter.TeleporterMessenger(subnetAInfo).RetrySendCrossChainMessage(opts, teleporterMessage) Expect(err).ShouldNot(BeNil()) // We expect the tx to be nil because the Warp message failed verification, which happens in the predicate diff --git a/tests/flows/retry_successful_execution.go b/tests/flows/teleporter/retry_successful_execution.go similarity index 74% rename from tests/flows/retry_successful_execution.go rename to tests/flows/teleporter/retry_successful_execution.go index f9834bbc5..a90cb5305 100644 --- a/tests/flows/retry_successful_execution.go +++ b/tests/flows/teleporter/retry_successful_execution.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -11,7 +11,7 @@ import ( . "github.com/onsi/gomega" ) -func RetrySuccessfulExecution(network interfaces.Network) { +func RetrySuccessfulExecution(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -25,12 +25,14 @@ func RetrySuccessfulExecution(network interfaces.Network) { ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetAInfo), subnetAInfo, ) testMessengerContractAddressB, subnetBTestMessenger := utils.DeployTestMessenger( ctx, fundedKey, fundedAddress, + teleporter.TeleporterRegistryAddress(subnetBInfo), subnetBInfo, ) @@ -54,7 +56,10 @@ func RetrySuccessfulExecution(network interfaces.Network) { // Wait for the transaction to be mined receipt := utils.WaitForTransactionSuccess(ctx, subnetAInfo, tx.Hash()) - event, err := utils.GetEventFromLogs(receipt.Logs, subnetAInfo.TeleporterMessenger.ParseSendCrossChainMessage) + event, err := utils.GetEventFromLogs( + receipt.Logs, + teleporter.TeleporterMessenger(subnetAInfo).ParseSendCrossChainMessage, + ) Expect(err).Should(BeNil()) Expect(event.DestinationBlockchainID[:]).Should(Equal(subnetBInfo.BlockchainID[:])) @@ -63,16 +68,16 @@ func RetrySuccessfulExecution(network interfaces.Network) { // // Relay the message to the destination // - receipt = network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + receipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) receiveEvent, err := - utils.GetEventFromLogs(receipt.Logs, subnetBInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + utils.GetEventFromLogs(receipt.Logs, teleporter.TeleporterMessenger(subnetBInfo).ParseReceiveCrossChainMessage) Expect(err).Should(BeNil()) deliveredTeleporterMessage := receiveEvent.Message // // Check Teleporter message received on the destination // - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) @@ -90,8 +95,11 @@ func RetrySuccessfulExecution(network interfaces.Network) { // optsB, err := bind.NewKeyedTransactorWithChainID(fundedKey, subnetBInfo.EVMChainID) Expect(err).Should(BeNil()) - tx, err = - subnetBInfo.TeleporterMessenger.RetryMessageExecution(optsB, subnetAInfo.BlockchainID, deliveredTeleporterMessage) + tx, err = teleporter.TeleporterMessenger(subnetBInfo).RetryMessageExecution( + optsB, + subnetAInfo.BlockchainID, + deliveredTeleporterMessage, + ) Expect(err).Should(Not(BeNil())) Expect(tx).Should(BeNil()) } diff --git a/tests/flows/send_specific_receipts.go b/tests/flows/teleporter/send_specific_receipts.go similarity index 72% rename from tests/flows/send_specific_receipts.go rename to tests/flows/teleporter/send_specific_receipts.go index 3e165a311..baf958f9c 100644 --- a/tests/flows/send_specific_receipts.go +++ b/tests/flows/teleporter/send_specific_receipts.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "bytes" @@ -16,10 +16,10 @@ import ( . "github.com/onsi/gomega" ) -func SendSpecificReceipts(network interfaces.Network) { +func SendSpecificReceipts(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) - teleporterContractAddress := network.GetTeleporterContractAddress() + teleporterContractAddress := teleporter.TeleporterMessengerAddress(subnetAInfo) _, fundedKey := network.GetFundedAccountInfo() ctx := context.Background() @@ -27,7 +27,7 @@ func SendSpecificReceipts(network interfaces.Network) { // This is only done if the test non-external networks because external networks may have // an arbitrarily high number of receipts to be cleared from a given queue from unrelated messages. if !network.IsExternalNetwork() { - utils.ClearReceiptQueue(ctx, network, fundedKey, subnetBInfo, subnetAInfo) + utils.ClearReceiptQueue(ctx, teleporter, subnetBInfo, subnetAInfo, fundedKey) } // Use mock token as the fee token @@ -61,41 +61,56 @@ func SendSpecificReceipts(network interfaces.Network) { // Send first message from Subnet A to Subnet B with fee amount 5 sendCrossChainMsgReceipt, messageID1 := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) // Relay the message from SubnetA to SubnetB - deliveryReceipt1 := network.RelayMessage(ctx, sendCrossChainMsgReceipt, subnetAInfo, subnetBInfo, true) + deliveryReceipt1 := teleporter.RelayTeleporterMessage( + ctx, + sendCrossChainMsgReceipt, + subnetAInfo, + subnetBInfo, + true, + fundedKey, + ) receiveEvent1, err := utils.GetEventFromLogs( deliveryReceipt1.Logs, - subnetBInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + teleporter.TeleporterMessenger(subnetBInfo).ParseReceiveCrossChainMessage) Expect(err).Should(BeNil()) Expect(receiveEvent1.MessageID[:]).Should(Equal(messageID1[:])) // Check that the first message was delivered - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID1) + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived(&bind.CallOpts{}, messageID1) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Send second message from Subnet A to Subnet B with fee amount 5 sendCrossChainMsgReceipt, messageID2 := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey) // Relay the message from SubnetA to SubnetB - deliveryReceipt2 := network.RelayMessage(ctx, sendCrossChainMsgReceipt, subnetAInfo, subnetBInfo, true) + deliveryReceipt2 := teleporter.RelayTeleporterMessage( + ctx, + sendCrossChainMsgReceipt, + subnetAInfo, + subnetBInfo, + true, + fundedKey, + ) receiveEvent2, err := utils.GetEventFromLogs( deliveryReceipt2.Logs, - subnetBInfo.TeleporterMessenger.ParseReceiveCrossChainMessage) + teleporter.TeleporterMessenger(subnetBInfo).ParseReceiveCrossChainMessage) Expect(err).Should(BeNil()) Expect(receiveEvent2.MessageID[:]).Should(Equal(messageID2[:])) // Check that the second message was delivered - delivered, err = subnetBInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID2) + delivered, err = teleporter.TeleporterMessenger(subnetBInfo).MessageReceived(&bind.CallOpts{}, messageID2) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Call send specific receipts to get reward of relaying two messages receipt, messageID := utils.SendSpecifiedReceiptsAndWaitForAcceptance( ctx, + teleporter.TeleporterMessenger(subnetBInfo), subnetBInfo, subnetAInfo.BlockchainID, [][32]byte{messageID1, messageID2}, @@ -108,21 +123,28 @@ func SendSpecificReceipts(network interfaces.Network) { ) // Relay message from Subnet B to Subnet A - receipt = network.RelayMessage(ctx, receipt, subnetBInfo, subnetAInfo, true) + receipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetBInfo, subnetAInfo, true, fundedKey) // Check that the message back to Subnet A was delivered - delivered, err = subnetAInfo.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, messageID) + delivered, err = teleporter.TeleporterMessenger(subnetAInfo).MessageReceived(&bind.CallOpts{}, messageID) Expect(err).Should(BeNil()) Expect(delivered).Should(BeTrue()) // Check that the expected receipts were received and emitted ReceiptReceived - Expect(utils.CheckReceiptReceived(receipt, messageID1, subnetAInfo.TeleporterMessenger)).Should(BeTrue()) - Expect(utils.CheckReceiptReceived(receipt, messageID2, subnetAInfo.TeleporterMessenger)).Should(BeTrue()) + Expect(utils.CheckReceiptReceived(receipt, messageID1, teleporter.TeleporterMessenger(subnetAInfo))).Should(BeTrue()) + Expect(utils.CheckReceiptReceived(receipt, messageID2, teleporter.TeleporterMessenger(subnetAInfo))).Should(BeTrue()) // Check the reward amounts. // Even on external networks, the relayer should only have the expected fee amount // for this asset because the asset contract was newly deployed by this test. - checkExpectedRewardAmounts(subnetAInfo, receiveEvent1, receiveEvent2, mockTokenAddress, relayerFeePerMessage) + checkExpectedRewardAmounts( + teleporter, + subnetAInfo, + receiveEvent1, + receiveEvent2, + mockTokenAddress, + relayerFeePerMessage, + ) // If the network is internal to the test application, send a message from Subnet B to Subnet A to trigger // the "regular" method of delivering receipts. The next message from B->A will contain the same receipts @@ -144,12 +166,12 @@ func SendSpecificReceipts(network interfaces.Network) { // This message will also have the same receipts as the previous message receipt, messageID = utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetBInfo, subnetAInfo, sendCrossChainMessageInput, fundedKey) + ctx, teleporter.TeleporterMessenger(subnetBInfo), subnetBInfo, subnetAInfo, sendCrossChainMessageInput, fundedKey) // Relay message from Subnet B to Subnet A - receipt = network.RelayMessage(ctx, receipt, subnetBInfo, subnetAInfo, true) + receipt = teleporter.RelayTeleporterMessage(ctx, receipt, subnetBInfo, subnetAInfo, true, fundedKey) // Check delivered - delivered, err = subnetAInfo.TeleporterMessenger.MessageReceived( + delivered, err = teleporter.TeleporterMessenger(subnetAInfo).MessageReceived( &bind.CallOpts{}, messageID) Expect(err).Should(BeNil()) @@ -157,12 +179,12 @@ func SendSpecificReceipts(network interfaces.Network) { // Check that the expected receipts were included in the message but did not emit ReceiptReceived // because they were previously received - Expect(utils.CheckReceiptReceived(receipt, messageID1, subnetAInfo.TeleporterMessenger)).Should(BeFalse()) - Expect(utils.CheckReceiptReceived(receipt, messageID2, subnetAInfo.TeleporterMessenger)).Should(BeFalse()) + Expect(utils.CheckReceiptReceived(receipt, messageID1, teleporter.TeleporterMessenger(subnetAInfo))).Should(BeFalse()) + Expect(utils.CheckReceiptReceived(receipt, messageID2, teleporter.TeleporterMessenger(subnetAInfo))).Should(BeFalse()) receiveEvent, err := utils.GetEventFromLogs( receipt.Logs, - subnetAInfo.TeleporterMessenger.ParseReceiveCrossChainMessage, + teleporter.TeleporterMessenger(subnetAInfo).ParseReceiveCrossChainMessage, ) Expect(err).Should(BeNil()) log.Info("Receipt included", "count", len(receiveEvent.Message.Receipts), "receipts", receiveEvent.Message.Receipts) @@ -180,7 +202,14 @@ func SendSpecificReceipts(network interfaces.Network) { receiveEvent.Message.Receipts)).Should(BeTrue()) // Check the reward amount remains the same - checkExpectedRewardAmounts(subnetAInfo, receiveEvent1, receiveEvent2, mockTokenAddress, relayerFeePerMessage) + checkExpectedRewardAmounts( + teleporter, + subnetAInfo, + receiveEvent1, + receiveEvent2, + mockTokenAddress, + relayerFeePerMessage, + ) } } @@ -212,6 +241,7 @@ func receiptIncluded( // assumed that the {tokenAddress} was used as the fee asset for each of the messages, // and that each message individually had a fee of {feePerMessage}. func checkExpectedRewardAmounts( + teleporter utils.TeleporterTestInfo, sourceSubnet interfaces.SubnetTestInfo, receiveEvent1 *teleportermessenger.TeleporterMessengerReceiveCrossChainMessage, receiveEvent2 *teleportermessenger.TeleporterMessengerReceiveCrossChainMessage, @@ -223,20 +253,20 @@ func checkExpectedRewardAmounts( // it should be able to redeem {feePerMessage}*2. Otherwise, // each distinct reward redeemer should be able to redeem {feePerMessage}. if receiveEvent1.RewardRedeemer == receiveEvent2.RewardRedeemer { - amount, err := sourceSubnet.TeleporterMessenger.CheckRelayerRewardAmount( + amount, err := teleporter[sourceSubnet.BlockchainID].TeleporterMessenger.CheckRelayerRewardAmount( &bind.CallOpts{}, receiveEvent1.RewardRedeemer, tokenAddress) Expect(err).Should(BeNil()) Expect(amount).Should(Equal(new(big.Int).Mul(feePerMessage, big.NewInt(2)))) } else { - amount1, err := sourceSubnet.TeleporterMessenger.CheckRelayerRewardAmount( + amount1, err := teleporter[sourceSubnet.BlockchainID].TeleporterMessenger.CheckRelayerRewardAmount( &bind.CallOpts{}, receiveEvent1.RewardRedeemer, tokenAddress) Expect(err).Should(BeNil()) Expect(amount1).Should(Equal(feePerMessage)) - amount2, err := sourceSubnet.TeleporterMessenger.CheckRelayerRewardAmount( + amount2, err := teleporter[sourceSubnet.BlockchainID].TeleporterMessenger.CheckRelayerRewardAmount( &bind.CallOpts{}, receiveEvent2.RewardRedeemer, tokenAddress) diff --git a/tests/flows/teleporter_message_ids.go b/tests/flows/teleporter/teleporter_message_ids.go similarity index 70% rename from tests/flows/teleporter_message_ids.go rename to tests/flows/teleporter/teleporter_message_ids.go index 1ae8285b3..a00d0cf17 100644 --- a/tests/flows/teleporter_message_ids.go +++ b/tests/flows/teleporter/teleporter_message_ids.go @@ -1,7 +1,7 @@ -// (c) 2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. +// // (c) 2024, Ava Labs, Inc. All rights reserved. +// // See the file LICENSE for licensing terms. -package flows +package teleporter import ( "math/big" @@ -9,21 +9,22 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ava-labs/teleporter/tests/utils" teleporterutils "github.com/ava-labs/teleporter/utils/teleporter-utils" "github.com/ethereum/go-ethereum/common" . "github.com/onsi/gomega" ) // Tests Teleporter message ID calculation -func CalculateMessageID(network interfaces.Network) { +func CalculateMessageID(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetInfo := network.GetPrimaryNetworkInfo() - teleporterContractAddress := network.GetTeleporterContractAddress() + teleporterContractAddress := teleporter.TeleporterMessengerAddress(subnetInfo) sourceBlockchainID := common.HexToHash("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd") destinationBlockchainID := common.HexToHash("0x1234567812345678123456781234567812345678123456781234567812345678") nonce := big.NewInt(42) - expectedMessageID, err := subnetInfo.TeleporterMessenger.CalculateMessageID( + expectedMessageID, err := teleporter.TeleporterMessenger(subnetInfo).CalculateMessageID( &bind.CallOpts{}, sourceBlockchainID, destinationBlockchainID, diff --git a/tests/flows/unallowed_relayer.go b/tests/flows/teleporter/unallowed_relayer.go similarity index 81% rename from tests/flows/unallowed_relayer.go rename to tests/flows/teleporter/unallowed_relayer.go index 155f55079..0da726cee 100644 --- a/tests/flows/unallowed_relayer.go +++ b/tests/flows/teleporter/unallowed_relayer.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -13,7 +13,7 @@ import ( . "github.com/onsi/gomega" ) -func UnallowedRelayer(network interfaces.Network) { +func UnallowedRelayer(network interfaces.Network, teleporter utils.TeleporterTestInfo) { subnetAInfo := network.GetPrimaryNetworkInfo() subnetBInfo, _ := utils.GetTwoSubnets(network) fundedAddress, fundedKey := network.GetFundedAccountInfo() @@ -43,18 +43,18 @@ func UnallowedRelayer(network interfaces.Network) { "destinationBlockchainID", subnetBInfo.BlockchainID, ) receipt, teleporterMessageID := utils.SendCrossChainMessageAndWaitForAcceptance( - ctx, subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey, + ctx, teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey, ) // // Relay the message to the destination // - network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, false) + teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, false, fundedKey) // // Check Teleporter message was not received on the destination // - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) diff --git a/tests/flows/validator_churn.go b/tests/flows/teleporter/validator_churn.go similarity index 82% rename from tests/flows/validator_churn.go rename to tests/flows/teleporter/validator_churn.go index fd5f832e1..da7ec7016 100644 --- a/tests/flows/validator_churn.go +++ b/tests/flows/teleporter/validator_churn.go @@ -1,4 +1,4 @@ -package flows +package teleporter import ( "context" @@ -17,9 +17,9 @@ import ( const newNodeCount = 2 -func ValidatorChurn(network interfaces.LocalNetwork) { +func ValidatorChurn(network interfaces.LocalNetwork, teleporter utils.TeleporterTestInfo) { subnetAInfo, subnetBInfo := utils.GetTwoSubnets(network) - teleporterContractAddress := network.GetTeleporterContractAddress() + teleporterContractAddress := teleporter.TeleporterMessengerAddress(subnetAInfo) fundedAddress, fundedKey := network.GetFundedAccountInfo() ctx := context.Background() @@ -42,18 +42,22 @@ func ValidatorChurn(network interfaces.LocalNetwork) { receipt, teleporterMessageID := utils.SendCrossChainMessageAndWaitForAcceptance( ctx, + teleporter.TeleporterMessenger(subnetAInfo), subnetAInfo, subnetBInfo, sendCrossChainMessageInput, fundedKey, ) - sendEvent, err := utils.GetEventFromLogs(receipt.Logs, subnetAInfo.TeleporterMessenger.ParseSendCrossChainMessage) + sendEvent, err := utils.GetEventFromLogs( + receipt.Logs, + teleporter.TeleporterMessenger(subnetAInfo).ParseSendCrossChainMessage, + ) Expect(err).Should(BeNil()) sentTeleporterMessage := sendEvent.Message // Construct the signed warp message - signedWarpMessage := network.ConstructSignedWarpMessage(ctx, receipt, subnetAInfo, subnetBInfo) + signedWarpMessage := utils.ConstructSignedWarpMessage(ctx, receipt, subnetAInfo, subnetBInfo) // // Modify the validator set on Subnet A @@ -94,7 +98,7 @@ func ValidatorChurn(network interfaces.LocalNetwork) { utils.SendTransactionAndWaitForFailure(ctx, subnetBInfo, signedTx) // Verify the message was not delivered - delivered, err := subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err := teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) @@ -106,7 +110,7 @@ func ValidatorChurn(network interfaces.LocalNetwork) { log.Info("Retrying message sending on source chain") optsA, err := bind.NewKeyedTransactorWithChainID(fundedKey, subnetAInfo.EVMChainID) Expect(err).Should(BeNil()) - tx, err := subnetAInfo.TeleporterMessenger.RetrySendCrossChainMessage( + tx, err := teleporter.TeleporterMessenger(subnetAInfo).RetrySendCrossChainMessage( optsA, sentTeleporterMessage, ) Expect(err).Should(BeNil()) @@ -114,10 +118,10 @@ func ValidatorChurn(network interfaces.LocalNetwork) { // Wait for the transaction to be mined receipt = utils.WaitForTransactionSuccess(ctx, subnetAInfo, tx.Hash()) - network.RelayMessage(ctx, receipt, subnetAInfo, subnetBInfo, true) + teleporter.RelayTeleporterMessage(ctx, receipt, subnetAInfo, subnetBInfo, true, fundedKey) // Verify the message was delivered - delivered, err = subnetBInfo.TeleporterMessenger.MessageReceived( + delivered, err = teleporter.TeleporterMessenger(subnetBInfo).MessageReceived( &bind.CallOpts{}, teleporterMessageID, ) Expect(err).Should(BeNil()) diff --git a/tests/flows/validator-manager/erc20_token_staking.go b/tests/flows/validator-manager/erc20_token_staking.go new file mode 100644 index 000000000..b720b475b --- /dev/null +++ b/tests/flows/validator-manager/erc20_token_staking.go @@ -0,0 +1,267 @@ +package staking + +import ( + "context" + "log" + "math/big" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ava-labs/teleporter/tests/utils" + . "github.com/onsi/gomega" +) + +/* + * Registers a erc20 token staking validator on a subnet. The steps are as follows: + * - Deploy the ERCTokenStakingManager + * - Initiate validator registration + * - Deliver the Warp message to the P-Chain (not implemented) + * - Aggregate P-Chain signatures on the response Warp message + * - Deliver the Warp message to the subnet + * - Verify that the validator is registered in the staking contract + * + * Delists the validator from the subnet. The steps are as follows: + * - Initiate validator delisting + * - Deliver the Warp message to the P-Chain (not implemented) + * - Aggregate P-Chain signatures on the response Warp message + * - Deliver the Warp message to the subnet + * - Verify that the validator is delisted from the staking contract + */ +func ERC20TokenStakingManager(network interfaces.LocalNetwork) { + // Get the subnets info + cChainInfo := network.GetPrimaryNetworkInfo() + subnetAInfo, _ := utils.GetTwoSubnets(network) + _, fundedKey := network.GetFundedAccountInfo() + pChainInfo := utils.GetPChainInfo(cChainInfo) + + signatureAggregator := utils.NewSignatureAggregator( + cChainInfo.NodeURIs[0], + []ids.ID{ + subnetAInfo.SubnetID, + }, + ) + ctx := context.Background() + + // Deploy the staking manager contract + stakingManagerAddress, stakingManager, _, erc20 := utils.DeployAndInitializeERC20TokenStakingManager( + ctx, + fundedKey, + subnetAInfo, + pChainInfo, + ) + + nodes := utils.ConvertSubnet( + ctx, + subnetAInfo, + network, + stakingManagerAddress, + fundedKey, + ) + + // Initialize the validator set on the subnet + log.Println("Initializing validator set") + initialValidationIDs := utils.InitializeERC20TokenValidatorSet( + ctx, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + network, + signatureAggregator, + nodes, + ) + + // + // Delist one initial validator + // + utils.InitializeAndCompleteEndInitialERC20Validation( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + initialValidationIDs[0], + 0, + nodes[0].Weight, + ) + + // + // Register the validator as PoS + // + expiry := uint64(time.Now().Add(24 * time.Hour).Unix()) + validationID := utils.InitializeAndCompleteERC20ValidatorRegistration( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + erc20, + expiry, + nodes[0], + ) + + // + // Register a delegator + // + var delegationID ids.ID + { + log.Println("Registering delegator") + delegatorStake, err := stakingManager.WeightToValue( + &bind.CallOpts{}, + nodes[0].Weight, + ) + Expect(err).Should(BeNil()) + delegatorStake.Div(delegatorStake, big.NewInt(10)) + delegatorWeight, err := stakingManager.ValueToWeight( + &bind.CallOpts{}, + delegatorStake, + ) + Expect(err).Should(BeNil()) + newValidatorWeight := nodes[0].Weight + delegatorWeight + + nonce := uint64(1) + + receipt := utils.InitializeERC20DelegatorRegistration( + ctx, + fundedKey, + subnetAInfo, + validationID, + delegatorStake, + erc20, + stakingManagerAddress, + stakingManager, + ) + initRegistrationEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorAdded, + ) + Expect(err).Should(BeNil()) + delegationID = initRegistrationEvent.DelegationID + + // Gather subnet-evm Warp signatures for the SubnetValidatorWeightUpdateMessage & relay to the P-Chain + signedWarpMessage := utils.ConstructSignedWarpMessage(context.Background(), receipt, subnetAInfo, pChainInfo) + + // Issue a tx to update the validator's weight on the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + utils.PChainProposerVMWorkaround(network) + utils.AdvanceProposerVM(ctx, subnetAInfo, fundedKey, 5) + + // Construct a SubnetValidatorWeightUpdateMessage Warp message from the P-Chain + registrationSignedMessage := utils.ConstructSubnetValidatorWeightUpdateMessage( + validationID, + nonce, + newValidatorWeight, + subnetAInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = utils.CompleteERC20DelegatorRegistration( + ctx, + fundedKey, + delegationID, + subnetAInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + // Check that the validator is registered in the staking contract + registrationEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorRegistered, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(registrationEvent.DelegationID[:]).Should(Equal(delegationID[:])) + } + + // + // Delist the delegator + // + { + log.Println("Delisting delegator") + nonce := uint64(2) + receipt := utils.InitializeEndERC20Delegation( + ctx, + fundedKey, + subnetAInfo, + stakingManager, + delegationID, + ) + delegatorRemovalEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(delegatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(delegatorRemovalEvent.DelegationID[:]).Should(Equal(delegationID[:])) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + signedWarpMessage := utils.ConstructSignedWarpMessage(context.Background(), receipt, subnetAInfo, pChainInfo) + Expect(err).Should(BeNil()) + + // Issue a tx to update the validator's weight on the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + utils.PChainProposerVMWorkaround(network) + utils.AdvanceProposerVM(ctx, subnetAInfo, fundedKey, 5) + + // Construct a SubnetValidatorWeightUpdateMessage Warp message from the P-Chain + signedMessage := utils.ConstructSubnetValidatorWeightUpdateMessage( + validationID, + nonce, + nodes[0].Weight, + subnetAInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = utils.CompleteEndERC20Delegation( + ctx, + fundedKey, + delegationID, + subnetAInfo, + stakingManagerAddress, + signedMessage, + ) + + // Check that the delegator has been delisted from the staking contract + registrationEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegationEnded, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(registrationEvent.DelegationID[:]).Should(Equal(delegationID[:])) + } + + // + // Delist the validator + // + utils.InitializeAndCompleteEndERC20Validation( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + validationID, + expiry, + nodes[0], + 1, + ) +} diff --git a/tests/flows/validator-manager/native_token_staking.go b/tests/flows/validator-manager/native_token_staking.go new file mode 100644 index 000000000..80a7961b0 --- /dev/null +++ b/tests/flows/validator-manager/native_token_staking.go @@ -0,0 +1,266 @@ +package staking + +import ( + "context" + "log" + "math/big" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ava-labs/teleporter/tests/utils" + . "github.com/onsi/gomega" +) + +/* + * Registers a native token staking validator on a subnet. The steps are as follows: + * - Deploy the NativeTokenStakingManager + * - Initiate validator registration + * - Deliver the Warp message to the P-Chain (not implemented) + * - Aggregate P-Chain signatures on the response Warp message + * - Deliver the Warp message to the subnet + * - Verify that the validator is registered in the staking contract + * + * Delists the validator from the subnet. The steps are as follows: + * - Initiate validator delisting + * - Deliver the Warp message to the P-Chain (not implemented) + * - Aggregate P-Chain signatures on the response Warp message + * - Deliver the Warp message to the subnet + * - Verify that the validator is delisted from the staking contract + */ +func NativeTokenStakingManager(network interfaces.LocalNetwork) { + // Get the subnets info + cChainInfo := network.GetPrimaryNetworkInfo() + subnetAInfo, _ := utils.GetTwoSubnets(network) + _, fundedKey := network.GetFundedAccountInfo() + pChainInfo := utils.GetPChainInfo(cChainInfo) + + signatureAggregator := utils.NewSignatureAggregator( + cChainInfo.NodeURIs[0], + []ids.ID{ + subnetAInfo.SubnetID, + }, + ) + ctx := context.Background() + + // Deploy the staking manager contract + stakingManagerAddress, stakingManager := utils.DeployAndInitializeNativeTokenStakingManager( + ctx, + fundedKey, + subnetAInfo, + pChainInfo, + ) + + utils.AddNativeMinterAdmin(ctx, subnetAInfo, fundedKey, stakingManagerAddress) + + nodes := utils.ConvertSubnet( + ctx, + subnetAInfo, + network, + stakingManagerAddress, + fundedKey, + ) + + // Initialize the validator set on the subnet + log.Println("Initializing validator set") + initialValidationIDs := utils.InitializeNativeTokenValidatorSet( + ctx, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + network, + signatureAggregator, + nodes, + ) + + // + // Delist one initial validator + // + utils.InitializeAndCompleteEndInitialNativeValidation( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + initialValidationIDs[0], + 0, + nodes[0].Weight, + ) + + // + // Register the validator as PoS + // + expiry := uint64(time.Now().Add(24 * time.Hour).Unix()) + validationID := utils.InitializeAndCompleteNativeValidatorRegistration( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + expiry, + nodes[0], + ) + + // + // Register a delegator + // + var delegationID ids.ID + { + log.Println("Registering delegator") + delegatorStake, err := stakingManager.WeightToValue( + &bind.CallOpts{}, + nodes[0].Weight, + ) + Expect(err).Should(BeNil()) + delegatorStake.Div(delegatorStake, big.NewInt(10)) + delegatorWeight, err := stakingManager.ValueToWeight( + &bind.CallOpts{}, + delegatorStake, + ) + Expect(err).Should(BeNil()) + newValidatorWeight := nodes[0].Weight + delegatorWeight + + nonce := uint64(1) + + receipt := utils.InitializeNativeDelegatorRegistration( + ctx, + fundedKey, + subnetAInfo, + validationID, + delegatorStake, + stakingManagerAddress, + stakingManager, + ) + initRegistrationEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorAdded, + ) + Expect(err).Should(BeNil()) + delegationID = initRegistrationEvent.DelegationID + + // Gather subnet-evm Warp signatures for the SubnetValidatorWeightUpdateMessage & relay to the P-Chain + signedWarpMessage := utils.ConstructSignedWarpMessage(context.Background(), receipt, subnetAInfo, pChainInfo) + + // Issue a tx to update the validator's weight on the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + utils.PChainProposerVMWorkaround(network) + utils.AdvanceProposerVM(ctx, subnetAInfo, fundedKey, 5) + + // Construct a SubnetValidatorWeightUpdateMessage Warp message from the P-Chain + registrationSignedMessage := utils.ConstructSubnetValidatorWeightUpdateMessage( + validationID, + nonce, + newValidatorWeight, + subnetAInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = utils.CompleteNativeDelegatorRegistration( + ctx, + fundedKey, + delegationID, + subnetAInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + // Check that the validator is registered in the staking contract + registrationEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorRegistered, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(registrationEvent.DelegationID[:]).Should(Equal(delegationID[:])) + } + // + // Delist the delegator + // + { + log.Println("Delisting delegator") + nonce := uint64(2) + receipt := utils.InitializeEndNativeDelegation( + ctx, + fundedKey, + subnetAInfo, + stakingManager, + delegationID, + ) + delegatorRemovalEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(delegatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(delegatorRemovalEvent.DelegationID[:]).Should(Equal(delegationID[:])) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + signedWarpMessage := utils.ConstructSignedWarpMessage(context.Background(), receipt, subnetAInfo, pChainInfo) + Expect(err).Should(BeNil()) + + // Issue a tx to update the validator's weight on the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + utils.PChainProposerVMWorkaround(network) + utils.AdvanceProposerVM(ctx, subnetAInfo, fundedKey, 5) + + // Construct a SubnetValidatorWeightUpdateMessage Warp message from the P-Chain + signedMessage := utils.ConstructSubnetValidatorWeightUpdateMessage( + validationID, + nonce, + nodes[0].Weight, + subnetAInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = utils.CompleteEndNativeDelegation( + ctx, + fundedKey, + delegationID, + subnetAInfo, + stakingManagerAddress, + signedMessage, + ) + + // Check that the delegator has been delisted from the staking contract + registrationEvent, err := utils.GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegationEnded, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(registrationEvent.DelegationID[:]).Should(Equal(delegationID[:])) + } + + // + // Delist the validator + // + utils.InitializeAndCompleteEndNativeValidation( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + stakingManager, + stakingManagerAddress, + validationID, + expiry, + nodes[0], + 1, + ) +} diff --git a/tests/flows/validator-manager/poa_to_pos.go b/tests/flows/validator-manager/poa_to_pos.go new file mode 100644 index 000000000..1d7a04d72 --- /dev/null +++ b/tests/flows/validator-manager/poa_to_pos.go @@ -0,0 +1,285 @@ +package staking + +import ( + "context" + "log" + "math/big" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + nativetokenstakingmanager "github.com/ava-labs/teleporter/abi-bindings/go/validator-manager/NativeTokenStakingManager" + poavalidatormanager "github.com/ava-labs/teleporter/abi-bindings/go/validator-manager/PoAValidatorManager" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ava-labs/teleporter/tests/utils" + "github.com/ethereum/go-ethereum/crypto" + + . "github.com/onsi/gomega" +) + +/* + * Register a PoA validator manager on a L1 with a proxy. The steps are as follows: + * - Generate random address to be the owner address + * - Fund native assets to the owner address + * - Deploy the PoAValidatorManager contract + * - Deploy a TransparentUpgradeableProxy contract that points to the PoAValidatorManager + * - Call initialize on the PoAValidatorManager through the proxy + * - Initialize and complete PoA validator registration + * + * Migrates the proxy to a PoS validator manager. The steps are as follows: + * - Deploy the PoSValidatorManager contract + * - Upgrade the TransparentUpgradeableProxy to point to the PoSValidatorManager + * - Call initialize on the PoSValidatorManager through the proxy + * - Check that previous validator is still active + * - Initialize and complete PoS validator registration + * - Attempt to delist previous PoA validator with wrong owner and check that it fails + * - Delist the previous PoA validator properly + * - Delist the PoS validator + */ +func PoAMigrationToPoS(network interfaces.LocalNetwork) { + cChainInfo := network.GetPrimaryNetworkInfo() + subnetAInfo, _ := utils.GetTwoSubnets(network) + _, fundedKey := network.GetFundedAccountInfo() + pChainInfo := utils.GetPChainInfo(cChainInfo) + + signatureAggregator := utils.NewSignatureAggregator( + cChainInfo.NodeURIs[0], + []ids.ID{ + subnetAInfo.SubnetID, + }, + ) + + // Generate random address to be the owner address + ownerKey, err := crypto.GenerateKey() + Expect(err).Should(BeNil()) + ownerAddress := crypto.PubkeyToAddress(ownerKey.PublicKey) + + // Transfer native assets to the owner account + ctx := context.Background() + fundAmount := big.NewInt(1e18) // 10avax + fundAmount.Mul(fundAmount, big.NewInt(10)) + utils.SendNativeTransfer( + ctx, + subnetAInfo, + fundedKey, + ownerAddress, + fundAmount, + ) + + // Deploy PoAValidatorManager contract + implAddress, _ := utils.DeployPoAValidatorManager( + ctx, + fundedKey, + subnetAInfo, + ) + + // Deploy TransparentUpgradeableProxy contract pointing to PoAValidatorManager + proxyAddress, proxyAdmin, poaValidatorManager := utils.DeployTransparentUpgradeableProxy( + ctx, + subnetAInfo, + fundedKey, + implAddress, + poavalidatormanager.NewPoAValidatorManager, + ) + opts, err := bind.NewKeyedTransactorWithChainID( + fundedKey, + subnetAInfo.EVMChainID, + ) + Expect(err).Should(BeNil()) + + tx, err := poaValidatorManager.Initialize( + opts, + poavalidatormanager.ValidatorManagerSettings{ + SubnetID: subnetAInfo.SubnetID, + ChurnPeriodSeconds: uint64(0), + MaximumChurnPercentage: uint8(20), + }, + ownerAddress, + ) + Expect(err).Should(BeNil()) + utils.WaitForTransactionSuccess(context.Background(), subnetAInfo, tx.Hash()) + + nodes := utils.ConvertSubnet( + ctx, + subnetAInfo, + network, + proxyAddress, + fundedKey, + ) + + // Initialize the validator set on the subnet + log.Println("Initializing validator set") + initialValidationIDs := utils.InitializePoAValidatorSet( + ctx, + fundedKey, + subnetAInfo, + pChainInfo, + poaValidatorManager, + proxyAddress, + network, + signatureAggregator, + nodes, + ) + + // + // Delist one initial validator + // + utils.InitializeAndCompleteEndInitialPoAValidation( + ctx, + network, + signatureAggregator, + ownerKey, + fundedKey, + subnetAInfo, + pChainInfo, + poaValidatorManager, + proxyAddress, + initialValidationIDs[0], + 0, + nodes[0].Weight, + ) + + // Try to call with invalid owner + opts, err = bind.NewKeyedTransactorWithChainID(fundedKey, subnetAInfo.EVMChainID) + Expect(err).Should(BeNil()) + + _, err = poaValidatorManager.InitializeValidatorRegistration( + opts, + poavalidatormanager.ValidatorRegistrationInput{ + NodeID: nodes[0].NodeID[:], + RegistrationExpiry: uint64(time.Now().Add(24 * time.Hour).Unix()), + BlsPublicKey: nodes[0].NodePoP.PublicKey[:], + }, + nodes[0].Weight, + ) + Expect(err).ShouldNot(BeNil()) + + // + // Re-register the validator as a SoV validator + // + expiry := uint64(time.Now().Add(24 * time.Hour).Unix()) + poaValidationID := utils.InitializeAndCompletePoAValidatorRegistration( + ctx, + network, + signatureAggregator, + ownerKey, + fundedKey, + subnetAInfo, + pChainInfo, + poaValidatorManager, + proxyAddress, + expiry, + nodes[0], + ) + poaValidator, err := poaValidatorManager.GetValidator(&bind.CallOpts{}, poaValidationID) + Expect(err).Should(BeNil()) + poaNodeID := poaValidator.NodeID + + /* + ****************** + * Migrate PoAValidatorManager to PoSValidatorManager + ****************** + */ + + // Deploy PoSValidatorManager contract + newImplAddress, _ := utils.DeployNativeTokenStakingManager( + ctx, + fundedKey, + subnetAInfo, + ) + + // Upgrade the TransparentUpgradeableProxy contract to use the new logic contract + tx, err = proxyAdmin.UpgradeAndCall(opts, proxyAddress, newImplAddress, []byte{}) + Expect(err).Should(BeNil()) + utils.WaitForTransactionSuccess(ctx, subnetAInfo, tx.Hash()) + + // Change the proxy contract type to NativeTokenStakingManager and initialize it + posValidatorManager, err := nativetokenstakingmanager.NewNativeTokenStakingManager( + proxyAddress, + subnetAInfo.RPCClient, + ) + Expect(err).Should(BeNil()) + + utils.AddNativeMinterAdmin(ctx, subnetAInfo, fundedKey, proxyAddress) + + rewardCalculatorAddress, _ := utils.DeployExampleRewardCalculator( + ctx, + fundedKey, + subnetAInfo, + uint64(10), + ) + + tx, err = posValidatorManager.Initialize( + opts, + nativetokenstakingmanager.PoSValidatorManagerSettings{ + BaseSettings: nativetokenstakingmanager.ValidatorManagerSettings{ + SubnetID: subnetAInfo.SubnetID, + ChurnPeriodSeconds: utils.DefaultChurnPeriodSeconds, + MaximumChurnPercentage: utils.DefaultMaxChurnPercentage, + }, + MinimumStakeAmount: big.NewInt(0).SetUint64(utils.DefaultMinStakeAmount), + MaximumStakeAmount: big.NewInt(0).SetUint64(utils.DefaultMaxStakeAmount), + MinimumStakeDuration: utils.DefaultMinStakeDurationSeconds, + MinimumDelegationFeeBips: utils.DefaultMinDelegateFeeBips, + MaximumStakeMultiplier: utils.DefaultMaxStakeMultiplier, + WeightToValueFactor: big.NewInt(0).SetUint64(utils.DefaultWeightToValueFactor), + RewardCalculator: rewardCalculatorAddress, + }, + ) + Expect(err).Should(BeNil()) + utils.WaitForTransactionSuccess(context.Background(), subnetAInfo, tx.Hash()) + + // Check that previous validator is still registered + validationID, err := posValidatorManager.RegisteredValidators(&bind.CallOpts{}, poaNodeID) + Expect(err).Should(BeNil()) + Expect(validationID[:]).Should(Equal(poaValidationID[:])) + + // + // Remove the PoA validator and re-register as a PoS validator + // + + utils.InitializeAndCompleteEndNativeValidation( + ctx, + network, + signatureAggregator, + ownerKey, + subnetAInfo, + pChainInfo, + posValidatorManager, + proxyAddress, + poaValidationID, + expiry, + nodes[0], + 1, + ) + + expiry2 := uint64(time.Now().Add(24 * time.Hour).Unix()) + posValidationID := utils.InitializeAndCompleteNativeValidatorRegistration( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + posValidatorManager, + proxyAddress, + expiry2, + nodes[0], + ) + + // Delist the PoS validator + utils.InitializeAndCompleteEndNativeValidation( + ctx, + network, + signatureAggregator, + fundedKey, + subnetAInfo, + pChainInfo, + posValidatorManager, + proxyAddress, + posValidationID, + expiry2, + nodes[0], + 1, + ) +} diff --git a/tests/interfaces/local_network.go b/tests/interfaces/local_network.go index 3206ee3c4..2639cc662 100644 --- a/tests/interfaces/local_network.go +++ b/tests/interfaces/local_network.go @@ -2,38 +2,16 @@ package interfaces import ( "context" - "crypto/ecdsa" "github.com/ava-labs/avalanchego/ids" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ethereum/go-ethereum/common" + pwallet "github.com/ava-labs/avalanchego/wallet/chain/p/wallet" ) type LocalNetwork interface { Network AddSubnetValidators(ctx context.Context, subnetID ids.ID, count uint) - ConstructSignedWarpMessage( - ctx context.Context, - sourceReceipt *types.Receipt, - source SubnetTestInfo, - destination SubnetTestInfo, - ) *avalancheWarp.Message - GetAllNodeIDs() []ids.NodeID SetChainConfigs(chainConfigs map[string]string) RestartNodes(ctx context.Context, nodeIDs []ids.NodeID) - DeployTeleporterContractToCChain( - transactionBytes []byte, - deployerAddress common.Address, - contractAddress common.Address, - fundedKey *ecdsa.PrivateKey, - ) - DeployTeleporterContractToAllChains( - transactionBytes []byte, - deployerAddress common.Address, - contractAddress common.Address, - fundedKey *ecdsa.PrivateKey, - ) GetNetworkID() uint32 - Dir() string + GetPChainWallet() pwallet.Wallet } diff --git a/tests/interfaces/network.go b/tests/interfaces/network.go index f71afdfef..204813dfb 100644 --- a/tests/interfaces/network.go +++ b/tests/interfaces/network.go @@ -1,12 +1,8 @@ package interfaces import ( - "context" "crypto/ecdsa" - "github.com/ava-labs/avalanchego/ids" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ethereum/go-ethereum/common" ) @@ -23,12 +19,6 @@ type Network interface { // use GetPrimaryNetworkInfo() and GetSubnetsInfo() instead. GetAllSubnetsInfo() []SubnetTestInfo - // Returns the Teleporter contract address for all subnets in this network. - GetTeleporterContractAddress() common.Address - - // Sets the Teleporter contract address for all subnets in this network. - SetTeleporterContractAddress(address common.Address) - // An address and corresponding key that has native tokens on each of the subnets in this network. GetFundedAccountInfo() (common.Address, *ecdsa.PrivateKey) @@ -40,24 +30,4 @@ type Network interface { // BLS signatures, and false for testnet networks where test application does not necessarily have // connections with each validator. SupportsIndependentRelaying() bool - - // GetSignedMessage returns the signed Warp message for the specified Warp message ID. - GetSignedMessage( - ctx context.Context, - source SubnetTestInfo, - destination SubnetTestInfo, - messageID ids.ID, - ) *avalancheWarp.Message - - // For implementations where SupportsIndependentRelaying() is true, relays the specified message between the - // two subnets,and returns the receipt of the transaction the message was delivered in. - // For implementations where SupportsIndependentRelaying() is false, waits for the specific message to be relayed - // by an external relayer, and returns the receipt of the transaction the message was delivered in. - RelayMessage( - ctx context.Context, - sourceReceipt *types.Receipt, - source SubnetTestInfo, - destination SubnetTestInfo, - expectSuccess bool, - ) *types.Receipt } diff --git a/tests/interfaces/subnet_test_info.go b/tests/interfaces/subnet_test_info.go index 10fa3f8a4..0ab8e6807 100644 --- a/tests/interfaces/subnet_test_info.go +++ b/tests/interfaces/subnet_test_info.go @@ -5,23 +5,15 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/subnet-evm/ethclient" - teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/TeleporterMessenger" - teleporterregistry "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/registry/TeleporterRegistry" - "github.com/ethereum/go-ethereum/common" ) // Tracks information about a test subnet used for executing tests against. type SubnetTestInfo struct { - SubnetName string - SubnetID ids.ID - BlockchainID ids.ID - NodeURIs []string - WSClient ethclient.Client - RPCClient ethclient.Client - EVMChainID *big.Int - TeleporterRegistry *teleporterregistry.TeleporterRegistry - TeleporterMessenger *teleportermessenger.TeleporterMessenger - - // TeleporterRegistryAddress is unique across subnets. - TeleporterRegistryAddress common.Address + SubnetName string + SubnetID ids.ID + BlockchainID ids.ID + NodeURIs []string + WSClient ethclient.Client + RPCClient ethclient.Client + EVMChainID *big.Int } diff --git a/tests/local/governance/governance_suite_test.go b/tests/local/governance/governance_suite_test.go new file mode 100644 index 000000000..731b61330 --- /dev/null +++ b/tests/local/governance/governance_suite_test.go @@ -0,0 +1,77 @@ +package governance_test + +import ( + "context" + "os" + "testing" + "time" + + governanceFlows "github.com/ava-labs/teleporter/tests/flows/governance" + "github.com/ava-labs/teleporter/tests/local" + "github.com/ethereum/go-ethereum/log" + "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +const ( + teleporterByteCodeFile = "./out/TeleporterMessenger.sol/TeleporterMessenger.json" + warpGenesisTemplateFile = "./tests/utils/warp-genesis-template.json" + + teleporterMessengerLabel = "TeleporterMessenger" + upgradabilityLabel = "upgradability" + utilsLabel = "utils" + validatorSetSigLabel = "ValidatorSetSig" + validatorManagerLabel = "ValidatorManager" +) + +var ( + LocalNetworkInstance *local.LocalNetwork +) + +func TestGovernance(t *testing.T) { + if os.Getenv("RUN_E2E") == "" { + t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") + } + + RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecs(t, "Teleporter e2e test") +} + +// Define the Teleporter before and after suite functions. +var _ = ginkgo.BeforeSuite(func() { + // Create the local network instance + ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) + defer cancel() + LocalNetworkInstance = local.NewLocalNetwork( + ctx, + "teleporter-test-local-network", + warpGenesisTemplateFile, + []local.SubnetSpec{ + { + Name: "A", + EVMChainID: 12345, + NodeCount: 2, + }, + { + Name: "B", + EVMChainID: 54321, + NodeCount: 2, + }, + }, + 2, + ) + log.Info("Started local network") +}) + +var _ = ginkgo.AfterSuite(func() { + LocalNetworkInstance.TearDownNetwork() +}) + +var _ = ginkgo.Describe("[Governance integration tests]", func() { + // Governance tests + ginkgo.It("Deliver ValidatorSetSig signed message", + ginkgo.Label(validatorSetSigLabel), + func() { + governanceFlows.ValidatorSetSig(LocalNetworkInstance) + }) +}) diff --git a/tests/local/network.go b/tests/local/network.go index 33e27a8a7..2839b082c 100644 --- a/tests/local/network.go +++ b/tests/local/network.go @@ -3,8 +3,9 @@ package local import ( "context" "crypto/ecdsa" + "encoding/base64" + "encoding/hex" "encoding/json" - "math/big" "os" "slices" "sort" @@ -14,24 +15,18 @@ import ( "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" + "github.com/ava-labs/avalanchego/upgrade" "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/vms/platformvm" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + pwallet "github.com/ava-labs/avalanchego/wallet/chain/p/wallet" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/subnet-evm/ethclient" - subnetEvmInterfaces "github.com/ava-labs/subnet-evm/interfaces" - "github.com/ava-labs/subnet-evm/precompile/contracts/warp" - "github.com/ava-labs/subnet-evm/rpc" subnetEvmTestUtils "github.com/ava-labs/subnet-evm/tests/utils" - warpBackend "github.com/ava-labs/subnet-evm/warp" - - teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/TeleporterMessenger" - teleporterregistry "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/registry/TeleporterRegistry" "github.com/ava-labs/teleporter/tests/interfaces" "github.com/ava-labs/teleporter/tests/utils" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" . "github.com/onsi/gomega" @@ -41,37 +36,32 @@ var _ interfaces.LocalNetwork = &LocalNetwork{} // Implements Network, pointing to the network setup in local_network_setup.go type LocalNetwork struct { - teleporterContractAddress common.Address - primaryNetworkInfo *interfaces.SubnetTestInfo - subnetsInfo map[ids.ID]*interfaces.SubnetTestInfo + primaryNetworkInfo *interfaces.SubnetTestInfo + subnetsInfo map[ids.ID]*interfaces.SubnetTestInfo extraNodes []*tmpnet.Node // to add as more subnet validators in the tests globalFundedKey *ecdsa.PrivateKey + pChainWallet pwallet.Wallet // Internal vars only used to set up the local network - tmpnet *tmpnet.Network - warpChainConfigPath string + tmpnet *tmpnet.Network } const ( - fundedKeyStr = "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027" - warpEnabledChainConfig = `{ - "warp-api-enabled": true, - "eth-apis":["eth","eth-filter","net","admin","web3", - "internal-eth","internal-blockchain","internal-transaction", - "internal-debug","internal-account","internal-personal", - "debug","debug-tracer","debug-file-tracer","debug-handler"] - }` + fundedKeyStr = "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027" + timeout = 120 * time.Second ) type SubnetSpec struct { - Name string - EVMChainID uint64 + Name string + EVMChainID uint64 + NodeCount int + + // Optional fields TeleporterContractAddress common.Address TeleporterDeployedBytecode string TeleporterDeployerAddress common.Address - NodeCount int } func NewLocalNetwork( @@ -86,14 +76,16 @@ func NewLocalNetwork( // Create extra nodes to be used to add more validators later extraNodes := subnetEvmTestUtils.NewTmpnetNodes(extraNodeCount) - f, err := os.CreateTemp(os.TempDir(), "config.json") + var allNodes []*tmpnet.Node + allNodes = append(allNodes, extraNodes...) // to be appended w/ subnet validators + + fundedKey, err := hex.DecodeString(fundedKeyStr) Expect(err).Should(BeNil()) - _, err = f.Write([]byte(warpEnabledChainConfig)) + globalFundedKey, err := secp256k1.ToPrivateKey(fundedKey) Expect(err).Should(BeNil()) - warpChainConfigPath := f.Name() - var allNodes []*tmpnet.Node - allNodes = append(allNodes, extraNodes...) // to be appended w/ subnet validators + globalFundedECDSAKey := globalFundedKey.ToECDSA() + Expect(err).Should(BeNil()) var subnets []*tmpnet.Subnet for _, subnetSpec := range subnetSpecs { @@ -109,20 +101,32 @@ func NewLocalNetwork( subnetSpec.TeleporterDeployedBytecode, subnetSpec.TeleporterDeployerAddress, ), - subnetEvmTestUtils.DefaultChainConfig, + utils.WarpEnabledChainConfig, nodes..., ) + subnet.OwningKey = globalFundedKey subnets = append(subnets, subnet) } network := subnetEvmTestUtils.NewTmpnetNetwork( name, allNodes, - tmpnet.FlagsMap{}, + utils.WarpEnabledChainConfig, subnets..., ) Expect(network).ShouldNot(BeNil()) + // Activate Etna + upgrades := upgrade.Default + upgrades.EtnaTime = time.Now().Add(-1 * time.Minute) + upgradeJSON, err := json.Marshal(upgrades) + Expect(err).Should(BeNil()) + + upgradeBase64 := base64.StdEncoding.EncodeToString(upgradeJSON) + network.DefaultFlags.SetDefaults(tmpnet.FlagsMap{ + config.UpgradeFileContentKey: upgradeBase64, + }) + avalancheGoBuildPath, ok := os.LookupEnv("AVALANCHEGO_BUILD_PATH") Expect(ok).Should(Equal(true)) @@ -138,26 +142,39 @@ func NewLocalNetwork( ) Expect(err).Should(BeNil()) - globalFundedKey, err := crypto.HexToECDSA(fundedKeyStr) - Expect(err).Should(BeNil()) - // Issue transactions to activate the proposerVM fork on the chains for _, subnet := range network.Subnets { - setupProposerVM(ctx, globalFundedKey, network, subnet.SubnetID) + utils.SetupProposerVM(ctx, globalFundedECDSAKey, network, subnet.SubnetID) } localNetwork := &LocalNetwork{ - primaryNetworkInfo: &interfaces.SubnetTestInfo{}, - subnetsInfo: make(map[ids.ID]*interfaces.SubnetTestInfo), - extraNodes: extraNodes, - globalFundedKey: globalFundedKey, - tmpnet: network, - warpChainConfigPath: warpChainConfigPath, + primaryNetworkInfo: &interfaces.SubnetTestInfo{}, + subnetsInfo: make(map[ids.ID]*interfaces.SubnetTestInfo), + extraNodes: extraNodes, + globalFundedKey: globalFundedECDSAKey, + tmpnet: network, } for _, subnet := range network.Subnets { localNetwork.setSubnetValues(subnet) } localNetwork.setPrimaryNetworkValues() + + // Create the P-Chain wallet to issue transactions + kc := secp256k1fx.NewKeychain(globalFundedKey) + localNetwork.GetSubnetsInfo() + var subnetIDs []ids.ID + for _, subnet := range localNetwork.GetSubnetsInfo() { + subnetIDs = append(subnetIDs, subnet.SubnetID) + } + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: localNetwork.GetPrimaryNetworkInfo().NodeURIs[0], + AVAXKeychain: kc, + EthKeychain: kc, + SubnetIDs: subnetIDs, + }) + Expect(err).Should(BeNil()) + localNetwork.pChainWallet = wallet.P() + return localNetwork } @@ -200,9 +217,6 @@ func (n *LocalNetwork) setPrimaryNetworkValues() { n.primaryNetworkInfo.WSClient = chainWSClient n.primaryNetworkInfo.RPCClient = chainRPCClient n.primaryNetworkInfo.EVMChainID = chainIDInt - - // TeleporterMessenger is set in SetTeleporterContractAddress - // TeleporterRegistryAddress is set in DeployTeleporterRegistryContracts } func (n *LocalNetwork) setSubnetValues(subnet *tmpnet.Subnet) { @@ -245,129 +259,6 @@ func (n *LocalNetwork) setSubnetValues(subnet *tmpnet.Subnet) { n.subnetsInfo[subnetID].WSClient = chainWSClient n.subnetsInfo[subnetID].RPCClient = chainRPCClient n.subnetsInfo[subnetID].EVMChainID = chainIDInt - - // TeleporterMessenger is set in SetTeleporterContractAddress - // TeleporterRegistryAddress is set in DeployTeleporterRegistryContracts -} - -func (n *LocalNetwork) deployTeleporterToChain( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - transactionBytes []byte, - deployerAddress common.Address, - contractAddress common.Address, - fundedKey *ecdsa.PrivateKey, -) { - // Fund the deployer address - fundAmount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(11)) // 11 AVAX - fundDeployerTx := utils.CreateNativeTransferTransaction( - ctx, subnetInfo, fundedKey, deployerAddress, fundAmount, - ) - utils.SendTransactionAndWaitForSuccess(ctx, subnetInfo, fundDeployerTx) - - log.Info("Finished funding Teleporter deployer", "blockchainID", subnetInfo.BlockchainID.Hex()) - - // Deploy Teleporter contract - rpcClient, err := rpc.DialContext( - ctx, - utils.HttpToRPCURI(subnetInfo.NodeURIs[0], subnetInfo.BlockchainID.String()), - ) - Expect(err).Should(BeNil()) - defer rpcClient.Close() - - txHash := common.Hash{} - err = rpcClient.CallContext(ctx, &txHash, "eth_sendRawTransaction", hexutil.Encode(transactionBytes)) - Expect(err).Should(BeNil()) - utils.WaitForTransactionSuccess(ctx, subnetInfo, txHash) - - teleporterCode, err := subnetInfo.RPCClient.CodeAt(ctx, contractAddress, nil) - Expect(err).Should(BeNil()) - Expect(len(teleporterCode)).Should(BeNumerically(">", 2)) // 0x is an EOA, contract returns the bytecode - - log.Info("Finished deploying Teleporter contract", "blockchainID", subnetInfo.BlockchainID.Hex()) -} - -// DeployTeleporterContractToCChain deploys the Teleporter contract to the C-Chain. -// The caller is responsible for generating the deployment transaction information -func (n *LocalNetwork) DeployTeleporterContractToCChain( - transactionBytes []byte, - deployerAddress common.Address, - contractAddress common.Address, - fundedKey *ecdsa.PrivateKey, -) { - log.Info("Deploying Teleporter contract to C-Chain", "contractAddress", contractAddress.String()) - - ctx := context.Background() - n.deployTeleporterToChain( - ctx, - n.GetPrimaryNetworkInfo(), - transactionBytes, - deployerAddress, - contractAddress, - fundedKey, - ) - - log.Info("Deployed Teleporter contracts to C-Chain") -} - -// DeployTeleporterContractToAllChains deploys the Teleporter contract to the C-Chain and all subnets. -// The caller is responsible for generating the deployment transaction information -func (n *LocalNetwork) DeployTeleporterContractToAllChains( - transactionBytes []byte, - deployerAddress common.Address, - contractAddress common.Address, - fundedKey *ecdsa.PrivateKey, -) { - log.Info("Deploying Teleporter contract to C-Chain and all subnets", "contractAddress", contractAddress.String()) - - ctx := context.Background() - for _, subnetInfo := range n.GetAllSubnetsInfo() { - n.deployTeleporterToChain(ctx, subnetInfo, transactionBytes, deployerAddress, contractAddress, fundedKey) - } - - log.Info("Deployed Teleporter contracts to C-Chain and all subnets") -} - -func (n *LocalNetwork) DeployTeleporterRegistryContracts( - teleporterAddress common.Address, - deployerKey *ecdsa.PrivateKey, -) { - log.Info("Deploying TeleporterRegistry contract to subnets") - ctx := context.Background() - - entries := []teleporterregistry.ProtocolRegistryEntry{ - { - Version: big.NewInt(1), - ProtocolAddress: teleporterAddress, - }, - } - - subnets := n.GetAllSubnetsInfo() - for _, subnetInfo := range subnets { - opts, err := bind.NewKeyedTransactorWithChainID(deployerKey, subnetInfo.EVMChainID) - Expect(err).Should(BeNil()) - teleporterRegistryAddress, tx, teleporterRegistry, err := teleporterregistry.DeployTeleporterRegistry( - opts, subnetInfo.RPCClient, entries, - ) - Expect(err).Should(BeNil()) - // Wait for the transaction to be mined - utils.WaitForTransactionSuccess(ctx, subnetInfo, tx.Hash()) - - if subnetInfo.SubnetID == constants.PrimaryNetworkID { - n.primaryNetworkInfo.TeleporterRegistryAddress = teleporterRegistryAddress - n.primaryNetworkInfo.TeleporterRegistry = teleporterRegistry - } else { - n.subnetsInfo[subnetInfo.SubnetID].TeleporterRegistryAddress = teleporterRegistryAddress - n.subnetsInfo[subnetInfo.SubnetID].TeleporterRegistry = teleporterRegistry - } - - log.Info("Deployed TeleporterRegistry contract", - "subnet", subnetInfo.SubnetID.Hex(), - "address", teleporterRegistryAddress.Hex(), - ) - } - - log.Info("Deployed TeleporterRegistry contracts to all subnets") } // Returns all subnet info sorted in lexicographic order of SubnetName. @@ -392,26 +283,6 @@ func (n *LocalNetwork) GetAllSubnetsInfo() []interfaces.SubnetTestInfo { return append(subnets, n.GetPrimaryNetworkInfo()) } -func (n *LocalNetwork) GetTeleporterContractAddress() common.Address { - return n.teleporterContractAddress -} - -func (n *LocalNetwork) SetTeleporterContractAddress(newTeleporterAddress common.Address) { - n.teleporterContractAddress = newTeleporterAddress - subnets := n.GetAllSubnetsInfo() - for _, subnetInfo := range subnets { - teleporterMessenger, err := teleportermessenger.NewTeleporterMessenger( - n.teleporterContractAddress, subnetInfo.RPCClient, - ) - Expect(err).Should(BeNil()) - if subnetInfo.SubnetID == constants.PrimaryNetworkID { - n.primaryNetworkInfo.TeleporterMessenger = teleporterMessenger - } else { - n.subnetsInfo[subnetInfo.SubnetID].TeleporterMessenger = teleporterMessenger - } - } -} - func (n *LocalNetwork) GetFundedAccountInfo() (common.Address, *ecdsa.PrivateKey) { fundedAddress := crypto.PubkeyToAddress(n.globalFundedKey.PublicKey) return fundedAddress, n.globalFundedKey @@ -427,45 +298,6 @@ func (n *LocalNetwork) SupportsIndependentRelaying() bool { return true } -func (n *LocalNetwork) RelayMessage(ctx context.Context, - sourceReceipt *types.Receipt, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - expectSuccess bool, -) *types.Receipt { - // Fetch the Teleporter message from the logs - sendEvent, err := utils.GetEventFromLogs(sourceReceipt.Logs, source.TeleporterMessenger.ParseSendCrossChainMessage) - Expect(err).Should(BeNil()) - - signedWarpMessage := n.ConstructSignedWarpMessage(ctx, sourceReceipt, source, destination) - - // Construct the transaction to send the Warp message to the destination chain - signedTx := utils.CreateReceiveCrossChainMessageTransaction( - ctx, - signedWarpMessage, - sendEvent.Message.RequiredGasLimit, - n.teleporterContractAddress, - n.globalFundedKey, - destination, - ) - - log.Info("Sending transaction to destination chain") - if !expectSuccess { - return utils.SendTransactionAndWaitForFailure(ctx, destination, signedTx) - } - - receipt := utils.SendTransactionAndWaitForSuccess(ctx, destination, signedTx) - - // Check the transaction logs for the ReceiveCrossChainMessage event emitted by the Teleporter contract - receiveEvent, err := utils.GetEventFromLogs( - receipt.Logs, - destination.TeleporterMessenger.ParseReceiveCrossChainMessage, - ) - Expect(err).Should(BeNil()) - Expect(receiveEvent.SourceBlockchainID[:]).Should(Equal(source.BlockchainID[:])) - return receipt -} - func (n *LocalNetwork) setAllSubnetValues() { subnetIDs := n.GetSubnetsInfo() Expect(len(subnetIDs)).Should(Equal(2)) @@ -484,7 +316,6 @@ func (n *LocalNetwork) TearDownNetwork() { Expect(n).ShouldNot(BeNil()) Expect(n.tmpnet).ShouldNot(BeNil()) Expect(n.tmpnet.Stop(context.Background())).Should(BeNil()) - Expect(os.Remove(n.warpChainConfigPath)).Should(BeNil()) } func (n *LocalNetwork) AddSubnetValidators(ctx context.Context, subnetID ids.ID, count uint) { @@ -533,22 +364,18 @@ func (n *LocalNetwork) AddSubnetValidators(ctx context.Context, subnetID ids.ID, n.setAllSubnetValues() } -// GetAllNodeIDs returns a slice that copies the NodeID's of all nodes in the network -func (n *LocalNetwork) GetAllNodeIDs() []ids.NodeID { - nodeIDs := make([]ids.NodeID, len(n.tmpnet.Nodes)) - for i, node := range n.tmpnet.Nodes { - nodeIDs[i] = node.NodeID - } - return nodeIDs -} - +// Restarts the nodes with the given nodeIDs. If nodeIDs is empty, restarts all nodes. func (n *LocalNetwork) RestartNodes(ctx context.Context, nodeIDs []ids.NodeID) { log.Info("Restarting nodes", "nodeIDs", nodeIDs) var nodes []*tmpnet.Node - for _, nodeID := range nodeIDs { - for _, node := range n.tmpnet.Nodes { - if node.NodeID == nodeID { - nodes = append(nodes, node) + if len(nodeIDs) == 0 { + nodes = n.tmpnet.Nodes + } else { + for _, nodeID := range nodeIDs { + for _, node := range n.tmpnet.Nodes { + if node.NodeID == nodeID { + nodes = append(nodes, node) + } } } } @@ -613,75 +440,6 @@ func (n *LocalNetwork) SetChainConfigs(chainConfigs map[string]string) { } } -func (n *LocalNetwork) ConstructSignedWarpMessage( - ctx context.Context, - sourceReceipt *types.Receipt, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, -) *avalancheWarp.Message { - log.Info("Fetching relevant warp logs from the newly produced block") - logs, err := source.RPCClient.FilterLogs(ctx, subnetEvmInterfaces.FilterQuery{ - BlockHash: &sourceReceipt.BlockHash, - Addresses: []common.Address{warp.Module.Address}, - }) - Expect(err).Should(BeNil()) - Expect(len(logs)).Should(Equal(1)) - - // Check for relevant warp log from subscription and ensure that it matches - // the log extracted from the last block. - txLog := logs[0] - log.Info("Parsing logData as unsigned warp message") - unsignedMsg, err := warp.UnpackSendWarpEventDataToMessage(txLog.Data) - Expect(err).Should(BeNil()) - - // Set local variables for the duration of the test - unsignedWarpMessageID := unsignedMsg.ID() - log.Info( - "Parsed unsignedWarpMsg", - "unsignedWarpMessageID", unsignedWarpMessageID, - "unsignedWarpMessage", unsignedMsg, - ) - - // Loop over each client on source chain to ensure they all have time to accept the block. - // Note: if we did not confirm this here, the next stage could be racy since it assumes every node - // has accepted the block. - waitForAllValidatorsToAcceptBlock(ctx, source.NodeURIs, source.BlockchainID, sourceReceipt.BlockNumber.Uint64()) - - // Get the aggregate signature for the Warp message - log.Info("Fetching aggregate signature from the source chain validators") - return n.GetSignedMessage(ctx, source, destination, unsignedWarpMessageID) -} - -func (n *LocalNetwork) GetSignedMessage( - ctx context.Context, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - unsignedWarpMessageID ids.ID, -) *avalancheWarp.Message { - Expect(len(source.NodeURIs)).Should(BeNumerically(">", 0)) - warpClient, err := warpBackend.NewClient(source.NodeURIs[0], source.BlockchainID.String()) - Expect(err).Should(BeNil()) - - signingSubnetID := source.SubnetID - if source.SubnetID == constants.PrimaryNetworkID { - signingSubnetID = destination.SubnetID - } - - // Get the aggregate signature for the Warp message - signedWarpMessageBytes, err := warpClient.GetMessageAggregateSignature( - ctx, - unsignedWarpMessageID, - warp.WarpDefaultQuorumNumerator, - signingSubnetID.String(), - ) - Expect(err).Should(BeNil()) - - signedWarpMsg, err := avalancheWarp.ParseMessage(signedWarpMessageBytes) - Expect(err).Should(BeNil()) - - return signedWarpMsg -} - func (n *LocalNetwork) GetNetworkID() uint32 { return n.tmpnet.Genesis.NetworkID } @@ -689,3 +447,7 @@ func (n *LocalNetwork) GetNetworkID() uint32 { func (n *LocalNetwork) Dir() string { return n.tmpnet.Dir } + +func (n *LocalNetwork) GetPChainWallet() pwallet.Wallet { + return n.pChainWallet +} diff --git a/tests/local/network_utils.go b/tests/local/network_utils.go deleted file mode 100644 index da166a6e0..000000000 --- a/tests/local/network_utils.go +++ /dev/null @@ -1,62 +0,0 @@ -package local - -import ( - "context" - "crypto/ecdsa" - "slices" - "time" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" - "github.com/ava-labs/subnet-evm/ethclient" - subnetEvmUtils "github.com/ava-labs/subnet-evm/tests/utils" - "github.com/ava-labs/teleporter/tests/utils" - "github.com/ethereum/go-ethereum/log" - - . "github.com/onsi/gomega" -) - -// Issues txs to activate the proposer VM fork on the specified subnet index in the manager -func setupProposerVM(ctx context.Context, fundedKey *ecdsa.PrivateKey, network *tmpnet.Network, subnetID ids.ID) { - subnetDetails := network.Subnets[slices.IndexFunc( - network.Subnets, - func(s *tmpnet.Subnet) bool { return s.SubnetID == subnetID }, - )] - - chainID := subnetDetails.Chains[0].ChainID - - nodeURI, err := network.GetURIForNodeID(subnetDetails.ValidatorIDs[0]) - Expect(err).Should(BeNil()) - uri := utils.HttpToWebsocketURI(nodeURI, chainID.String()) - - client, err := ethclient.Dial(uri) - Expect(err).Should(BeNil()) - chainIDInt, err := client.ChainID(ctx) - Expect(err).Should(BeNil()) - - err = subnetEvmUtils.IssueTxsToActivateProposerVMFork(ctx, chainIDInt, fundedKey, client) - Expect(err).Should(BeNil()) -} - -// Blocks until all validators specified in nodeURIs have reached the specified block height -func waitForAllValidatorsToAcceptBlock(ctx context.Context, nodeURIs []string, blockchainID ids.ID, height uint64) { - cctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - for i, uri := range nodeURIs { - chainAWSURI := utils.HttpToWebsocketURI(uri, blockchainID.String()) - log.Debug("Creating ethclient for blockchain", "blockchainID", blockchainID.String(), "wsURI", chainAWSURI) - client, err := ethclient.Dial(chainAWSURI) - Expect(err).Should(BeNil()) - defer client.Close() - - // Loop until each node has advanced to >= the height of the block that emitted the warp log - for { - block, err := client.BlockByNumber(cctx, nil) - Expect(err).Should(BeNil()) - if block.NumberU64() >= height { - log.Debug("Client accepted the block containing SendWarpMessage", "client", i, "height", block.NumberU64()) - break - } - } - } -} diff --git a/tests/local/e2e_test.go b/tests/local/teleporter/teleporter_suite_test.go similarity index 64% rename from tests/local/e2e_test.go rename to tests/local/teleporter/teleporter_suite_test.go index 4cda1c10c..17fe35e1a 100644 --- a/tests/local/e2e_test.go +++ b/tests/local/teleporter/teleporter_suite_test.go @@ -1,7 +1,4 @@ -// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package local +package teleporter_test import ( "context" @@ -9,7 +6,10 @@ import ( "testing" "time" - "github.com/ava-labs/teleporter/tests/flows" + teleporterFlows "github.com/ava-labs/teleporter/tests/flows/teleporter" + registryFlows "github.com/ava-labs/teleporter/tests/flows/teleporter/registry" + "github.com/ava-labs/teleporter/tests/local" + "github.com/ava-labs/teleporter/tests/utils" deploymentUtils "github.com/ava-labs/teleporter/utils/deployment-utils" "github.com/ethereum/go-ethereum/log" "github.com/onsi/ginkgo/v2" @@ -24,13 +24,15 @@ const ( upgradabilityLabel = "upgradability" utilsLabel = "utils" validatorSetSigLabel = "ValidatorSetSig" + validatorManagerLabel = "ValidatorManager" ) var ( - LocalNetworkInstance *LocalNetwork + LocalNetworkInstance *local.LocalNetwork + TeleporterInfo utils.TeleporterTestInfo ) -func TestE2E(t *testing.T) { +func TestTeleporter(t *testing.T) { if os.Getenv("RUN_E2E") == "" { t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") } @@ -53,11 +55,11 @@ var _ = ginkgo.BeforeSuite(func() { // Create the local network instance ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) defer cancel() - LocalNetworkInstance = NewLocalNetwork( + LocalNetworkInstance = local.NewLocalNetwork( ctx, "teleporter-test-local-network", warpGenesisTemplateFile, - []SubnetSpec{ + []local.SubnetSpec{ { Name: "A", EVMChainID: 12345, @@ -77,32 +79,31 @@ var _ = ginkgo.BeforeSuite(func() { }, 2, ) + TeleporterInfo = utils.NewTeleporterTestInfo(LocalNetworkInstance.GetAllSubnetsInfo()) log.Info("Started local network") // Only need to deploy Teleporter on the C-Chain since it is included in the genesis of the subnet chains. _, fundedKey := LocalNetworkInstance.GetFundedAccountInfo() - LocalNetworkInstance.DeployTeleporterContractToCChain( + TeleporterInfo.DeployTeleporterMessenger( + ctx, + LocalNetworkInstance.GetPrimaryNetworkInfo(), teleporterDeployerTransaction, teleporterDeployerAddress, teleporterContractAddress, fundedKey, ) - LocalNetworkInstance.SetTeleporterContractAddress(teleporterContractAddress) - - // Deploy the Teleporter registry contracts to all subnets and the C-Chain. - LocalNetworkInstance.DeployTeleporterRegistryContracts(teleporterContractAddress, fundedKey) - - ginkgo.AddReportEntry( - "network directory with node logs & configs; useful in the case of failures", - LocalNetworkInstance.tmpnet.Dir, - ginkgo.ReportEntryVisibilityFailureOrVerbose, - ) + for _, subnet := range LocalNetworkInstance.GetAllSubnetsInfo() { + TeleporterInfo.SetTeleporter(teleporterContractAddress, subnet) + TeleporterInfo.InitializeBlockchainID(subnet, fundedKey) + TeleporterInfo.DeployTeleporterRegistry(subnet, fundedKey) + } log.Info("Set up ginkgo before suite") }) var _ = ginkgo.AfterSuite(func() { LocalNetworkInstance.TearDownNetwork() + LocalNetworkInstance = nil }) var _ = ginkgo.Describe("[Teleporter integration tests]", func() { @@ -110,91 +111,83 @@ var _ = ginkgo.Describe("[Teleporter integration tests]", func() { ginkgo.It("Send a message from Subnet A to Subnet B, and one from B to A", ginkgo.Label(teleporterMessengerLabel), func() { - flows.BasicSendReceive(LocalNetworkInstance) + teleporterFlows.BasicSendReceive(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Deliver to the wrong chain", ginkgo.Label(teleporterMessengerLabel), func() { - flows.DeliverToWrongChain(LocalNetworkInstance) + teleporterFlows.DeliverToWrongChain(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Deliver to non-existent contract", ginkgo.Label(teleporterMessengerLabel), func() { - flows.DeliverToNonExistentContract(LocalNetworkInstance) + teleporterFlows.DeliverToNonExistentContract(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Retry successful execution", ginkgo.Label(teleporterMessengerLabel), func() { - flows.RetrySuccessfulExecution(LocalNetworkInstance) + teleporterFlows.RetrySuccessfulExecution(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Unallowed relayer", ginkgo.Label(teleporterMessengerLabel), func() { - flows.UnallowedRelayer(LocalNetworkInstance) + teleporterFlows.UnallowedRelayer(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Relay message twice", ginkgo.Label(teleporterMessengerLabel), func() { - flows.RelayMessageTwice(LocalNetworkInstance) + teleporterFlows.RelayMessageTwice(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Add additional fee amount", ginkgo.Label(teleporterMessengerLabel), func() { - flows.AddFeeAmount(LocalNetworkInstance) + teleporterFlows.AddFeeAmount(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Send specific receipts", ginkgo.Label(teleporterMessengerLabel), func() { - flows.SendSpecificReceipts(LocalNetworkInstance) + teleporterFlows.SendSpecificReceipts(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Insufficient gas", ginkgo.Label(teleporterMessengerLabel), func() { - flows.InsufficientGas(LocalNetworkInstance) + teleporterFlows.InsufficientGas(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Resubmit altered message", ginkgo.Label(teleporterMessengerLabel), func() { - flows.ResubmitAlteredMessage(LocalNetworkInstance) - }) - ginkgo.It("Check upgrade access", - ginkgo.Label(upgradabilityLabel), - func() { - flows.CheckUpgradeAccess(LocalNetworkInstance) - }) - ginkgo.It("Pause and Unpause Teleporter", - ginkgo.Label(upgradabilityLabel), - func() { - flows.PauseTeleporter(LocalNetworkInstance) + teleporterFlows.ResubmitAlteredMessage(LocalNetworkInstance, TeleporterInfo) }) ginkgo.It("Calculate Teleporter message IDs", ginkgo.Label(utilsLabel), func() { - flows.CalculateMessageID(LocalNetworkInstance) + teleporterFlows.CalculateMessageID(LocalNetworkInstance, TeleporterInfo) }) - - // The following tests require special behavior by the relayer, so we only run them on a local network ginkgo.It("Relayer modifies message", ginkgo.Label(teleporterMessengerLabel), func() { - flows.RelayerModifiesMessage(LocalNetworkInstance) + teleporterFlows.RelayerModifiesMessage(LocalNetworkInstance, TeleporterInfo) }) + ginkgo.It("Validator churn", + ginkgo.Label(teleporterMessengerLabel), + func() { + teleporterFlows.ValidatorChurn(LocalNetworkInstance, TeleporterInfo) + }) + + // Teleporter Registry tests ginkgo.It("Teleporter registry", ginkgo.Label(upgradabilityLabel), func() { - flows.TeleporterRegistry(LocalNetworkInstance) + registryFlows.TeleporterRegistry(LocalNetworkInstance, TeleporterInfo) }) - ginkgo.It("Deliver ValidatorSetSig signed message", - ginkgo.Label(validatorSetSigLabel), + ginkgo.It("Check upgrade access", + ginkgo.Label(upgradabilityLabel), func() { - flows.ValidatorSetSig(LocalNetworkInstance) + registryFlows.CheckUpgradeAccess(LocalNetworkInstance, TeleporterInfo) }) - ginkgo.It("Validator churn", - ginkgo.Label(teleporterMessengerLabel), + ginkgo.It("Pause and Unpause Teleporter", + ginkgo.Label(upgradabilityLabel), func() { - flows.ValidatorChurn(LocalNetworkInstance) + registryFlows.PauseTeleporter(LocalNetworkInstance, TeleporterInfo) }) - // Since the validator churn test modifies the network topology, we put it last for now. - // It should not affect the other tests, but we get some errors if we run it before the other tests. - // TODO: we should fix this so that the order of the tests does not matter. }) diff --git a/tests/local/validator-manager/validator_manager_suite_test.go b/tests/local/validator-manager/validator_manager_suite_test.go new file mode 100644 index 000000000..1b2ab223f --- /dev/null +++ b/tests/local/validator-manager/validator_manager_suite_test.go @@ -0,0 +1,88 @@ +package validator_manager_test + +import ( + "context" + "os" + "testing" + "time" + + validatorManagerFlows "github.com/ava-labs/teleporter/tests/flows/validator-manager" + "github.com/ava-labs/teleporter/tests/local" + "github.com/ethereum/go-ethereum/log" + "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +const ( + teleporterByteCodeFile = "./out/TeleporterMessenger.sol/TeleporterMessenger.json" + warpGenesisTemplateFile = "./tests/utils/warp-genesis-template.json" + + teleporterMessengerLabel = "TeleporterMessenger" + upgradabilityLabel = "upgradability" + utilsLabel = "utils" + validatorSetSigLabel = "ValidatorSetSig" + validatorManagerLabel = "ValidatorManager" +) + +var ( + LocalNetworkInstance *local.LocalNetwork +) + +func TestValidatorManager(t *testing.T) { + if os.Getenv("RUN_E2E") == "" { + t.Skip("Environment variable RUN_E2E not set; skipping E2E tests") + } + + RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecs(t, "Teleporter e2e test") +} + +// Define the Teleporter before and after suite functions. +var _ = ginkgo.BeforeEach(func() { + // Create the local network instance + ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) + defer cancel() + LocalNetworkInstance = local.NewLocalNetwork( + ctx, + "teleporter-test-local-network", + warpGenesisTemplateFile, + []local.SubnetSpec{ + { + Name: "A", + EVMChainID: 12345, + NodeCount: 2, + }, + { + Name: "B", + EVMChainID: 54321, + NodeCount: 2, + }, + }, + 2, + ) + log.Info("Started local network") +}) + +var _ = ginkgo.AfterEach(func() { + LocalNetworkInstance.TearDownNetwork() + LocalNetworkInstance = nil +}) + +var _ = ginkgo.Describe("[Validator manager integration tests]", func() { + // Validator Manager tests + ginkgo.It("Native token staking manager", + ginkgo.Label(validatorManagerLabel), + func() { + validatorManagerFlows.NativeTokenStakingManager(LocalNetworkInstance) + }) + ginkgo.It("ERC20 token staking manager", + ginkgo.Label(validatorManagerLabel), + func() { + validatorManagerFlows.ERC20TokenStakingManager(LocalNetworkInstance) + }) + ginkgo.It("PoA migration to PoS", + ginkgo.Label(validatorManagerLabel), + func() { + validatorManagerFlows.PoAMigrationToPoS(LocalNetworkInstance) + }) +}) diff --git a/tests/testnet/main/run_testnet_flows.go b/tests/testnet/main/run_testnet_flows.go deleted file mode 100644 index 440a02711..000000000 --- a/tests/testnet/main/run_testnet_flows.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "github.com/ethereum/go-ethereum/log" - - "github.com/ava-labs/teleporter/tests/flows" - "github.com/ava-labs/teleporter/tests/interfaces" - "github.com/ava-labs/teleporter/tests/testnet" - "github.com/onsi/gomega" -) - -func runFlow(flowName string, flow func(interfaces.Network), network interfaces.Network) { - log.Info("Running test", "flowName", flowName) - flow(network) - log.Info("Finished running test", "flowName", flowName) -} - -func main() { - // Register a failure handler that panics - gomega.RegisterFailHandler(func(message string, callerSkip ...int) { - panic(message) - }) - - // Create the new network instances - network, err := testnet.NewTestNetwork() - if err != nil { - panic(err) - } - - // Run the Teleporter test flows. - // Note that the following flows are not able to run against testnet because they - // require the tests to be able to relay messages independently or modifying validator sets. - // - RelayerModifiesMessage - // - UnallowedRelayer - // - ValidatorSetChrun - // - TeleporterRegistry - runFlow("AddFeeAmount", flows.AddFeeAmount, network) - runFlow("BasicSendRecevie", flows.BasicSendReceive, network) - runFlow("DeliverToNonExistentContract", flows.DeliverToNonExistentContract, network) - runFlow("DeliverToWrongChain", flows.DeliverToWrongChain, network) - runFlow("InsufficientGas", flows.InsufficientGas, network) - runFlow("RelayMessageTwice", flows.RelayMessageTwice, network) - runFlow("ResubmitAlteredMessage", flows.ResubmitAlteredMessage, network) - runFlow("RetrySuccessfulExecution", flows.RetrySuccessfulExecution, network) - runFlow("SendSpecificReceipts", flows.SendSpecificReceipts, network) - log.Info("Finished Teleporter test flows") - - // Run the upgradability test flows - runFlow("CheckUpgradeAccess", flows.CheckUpgradeAccess, network) - runFlow("PauseTeleporter", flows.PauseTeleporter, network) - log.Info("Finished upgradability test flows") -} diff --git a/tests/testnet/network.go b/tests/testnet/network.go deleted file mode 100644 index 4a29710ee..000000000 --- a/tests/testnet/network.go +++ /dev/null @@ -1,372 +0,0 @@ -package testnet - -import ( - "context" - "crypto/ecdsa" - "errors" - "net/http" - "net/http/cookiejar" - "os" - "time" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/ethclient" - "github.com/ava-labs/subnet-evm/precompile/contracts/warp" - "github.com/ava-labs/subnet-evm/rpc" - warpBackend "github.com/ava-labs/subnet-evm/warp" - teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/TeleporterMessenger" - teleporterregistry "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/registry/TeleporterRegistry" - "github.com/ava-labs/teleporter/tests/interfaces" - "github.com/ava-labs/teleporter/tests/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - - . "github.com/onsi/gomega" -) - -const ( - subnetAPrefix = "subnet_a" - subnetBPrefix = "subnet_b" - subnetCPrefix = "subnet_c" - cChainPrefix = "c_chain" - teleporterContractAddress = "teleporter_contract_address" - teleporterRegistryAddressSuffix = "_teleporter_registry_address" - subnetIDSuffix = "_subnet_id" - blockchainIDSuffix = "_blockchain_id" - rpcURLSuffix = "_rpc_url" - wsURLSuffix = "_ws_url" - userAddress = "user_address" - userPrivateKey = "user_private_key" - - receiveCrossChainMessageEventName = "ReceiveCrossChainMessage" - receiveCrossChainMessageLookBackBlocks = 500 - - privateKeyHexLength = 64 -) - -var errInvalidPrivateKeyString = errors.New("invalid private key string") - -var _ interfaces.Network = &testNetwork{} - -type testNetwork struct { - teleporterContractAddress common.Address - primaryNetwork *interfaces.SubnetTestInfo - subnetsInfo map[ids.ID]*interfaces.SubnetTestInfo - fundedAddress common.Address - fundedKey *ecdsa.PrivateKey -} - -func initializeSubnetInfo( - subnetPrefix string, - teleporterContractAddress common.Address, -) (interfaces.SubnetTestInfo, error) { - subnetIDStr := os.Getenv(subnetPrefix + subnetIDSuffix) - subnetID, err := ids.FromString(subnetIDStr) - if err != nil { - log.Info("Error decoding subnet ID", "subnetPrefix", subnetPrefix) - return interfaces.SubnetTestInfo{}, err - } - - blockchainIDStr := os.Getenv(subnetPrefix + blockchainIDSuffix) - blockchainID, err := ids.FromString(blockchainIDStr) - if err != nil { - log.Info("Error decoding blockchain ID", "subnetPrefix", subnetPrefix) - return interfaces.SubnetTestInfo{}, err - } - - rpcURLStr := os.Getenv(subnetPrefix + rpcURLSuffix) - - // Create the client using a cookiejar to try to use the same node for each - // request when using public RPC endpoints. Having requests routed to different - // nodes behind a load balancer may cause issues with nodes serving slightly stale - // data from before they see recently accepted transactions. Responses generally - // have cookies identifying which node served the request, and those cookies can - // be added to the cookiejar to be included on future requests to attempt to have - // the same node serve it. - // See here: https://docs.avax.network/tooling/rpc-providers#sticky-sessions - jar, err := cookiejar.New(nil) - if err != nil { - return interfaces.SubnetTestInfo{}, err - } - - httpClient := &http.Client{ - Jar: jar, - } - - rpcClient, err := rpc.DialOptions( - context.Background(), - rpcURLStr, - rpc.WithHTTPClient(httpClient), - ) - if err != nil { - return interfaces.SubnetTestInfo{}, err - } - - ethClient := ethclient.NewClient(rpcClient) - - evmChainID, err := ethClient.ChainID(context.Background()) - if err != nil { - return interfaces.SubnetTestInfo{}, err - } - - teleporterRegistryAddressStr := os.Getenv(subnetPrefix + teleporterRegistryAddressSuffix) - if !common.IsHexAddress(teleporterRegistryAddressStr) { - return interfaces.SubnetTestInfo{}, errors.New("invalid teleporter regirstry address") - } - teleporterRegistryAddress := common.HexToAddress(teleporterRegistryAddressStr) - - teleporterMessenger, err := teleportermessenger.NewTeleporterMessenger( - teleporterContractAddress, ethClient, - ) - if err != nil { - return interfaces.SubnetTestInfo{}, err - } - - teleporterRegistry, err := teleporterregistry.NewTeleporterRegistry(teleporterRegistryAddress, ethClient) - if err != nil { - return interfaces.SubnetTestInfo{}, err - } - - return interfaces.SubnetTestInfo{ - SubnetID: subnetID, - BlockchainID: blockchainID, - NodeURIs: []string{}, // no specific node URIs for a testnet subnet, only RPC endpoints. - RPCClient: ethClient, - WSClient: nil, - EVMChainID: evmChainID, - TeleporterRegistryAddress: teleporterRegistryAddress, - TeleporterRegistry: teleporterRegistry, - TeleporterMessenger: teleporterMessenger, - }, nil -} - -func NewTestNetwork() (*testNetwork, error) { - teleporterContractAddressStr := os.Getenv(teleporterContractAddress) - teleporterContractAddress := common.HexToAddress(teleporterContractAddressStr) - log.Info("Set teleporter contract address", "teleporterContractAddress", teleporterContractAddressStr) - - subnetAInfo, err := initializeSubnetInfo(subnetAPrefix, teleporterContractAddress) - if err != nil { - return nil, err - } - - subnetBInfo, err := initializeSubnetInfo(subnetBPrefix, teleporterContractAddress) - if err != nil { - return nil, err - } - - cChainInfo, err := initializeSubnetInfo(cChainPrefix, teleporterContractAddress) - if err != nil { - return nil, err - } - log.Info("Set testnet subnet info", subnetAPrefix, subnetAInfo, subnetBPrefix, subnetBInfo) - - fundedAddressStr := os.Getenv(userAddress) - fundedKeyStr := os.Getenv(userPrivateKey) - if len(fundedKeyStr) >= 2 && fundedKeyStr[0:2] == "0x" { - fundedKeyStr = fundedKeyStr[2:] - } - if len(fundedKeyStr) != privateKeyHexLength { - return nil, errInvalidPrivateKeyString - } - fundedKey, err := crypto.HexToECDSA(fundedKeyStr) - if err != nil { - return nil, err - } - log.Info("Set user funded address", "address", fundedAddressStr) - - subnetsInfo := make(map[ids.ID]*interfaces.SubnetTestInfo) - subnetsInfo[subnetAInfo.SubnetID] = &subnetAInfo - subnetsInfo[subnetBInfo.SubnetID] = &subnetBInfo - return &testNetwork{ - teleporterContractAddress: teleporterContractAddress, - primaryNetwork: &cChainInfo, - subnetsInfo: subnetsInfo, - fundedAddress: common.HexToAddress(fundedAddressStr), - fundedKey: fundedKey, - }, nil -} - -func (n *testNetwork) GetPrimaryNetworkInfo() interfaces.SubnetTestInfo { - return *n.primaryNetwork -} - -func (n *testNetwork) GetSubnetsInfo() []interfaces.SubnetTestInfo { - subnetsInfo := make([]interfaces.SubnetTestInfo, 0, len(n.subnetsInfo)) - for _, subnetInfo := range n.subnetsInfo { - subnetsInfo = append(subnetsInfo, *subnetInfo) - } - return subnetsInfo -} - -// Returns subnet info for all subnets, including the primary network -func (n *testNetwork) GetAllSubnetsInfo() []interfaces.SubnetTestInfo { - subnets := n.GetSubnetsInfo() - return append(subnets, n.GetPrimaryNetworkInfo()) -} - -func (n *testNetwork) GetTeleporterContractAddress() common.Address { - return n.teleporterContractAddress -} - -func (n *testNetwork) SetTeleporterContractAddress(newTeleporterAddress common.Address) { - n.teleporterContractAddress = newTeleporterAddress - subnets := n.GetAllSubnetsInfo() - for _, subnetInfo := range subnets { - teleporterMessenger, err := teleportermessenger.NewTeleporterMessenger( - n.teleporterContractAddress, subnetInfo.RPCClient, - ) - Expect(err).Should(BeNil()) - if subnetInfo.SubnetID == constants.PrimaryNetworkID { - n.primaryNetwork.TeleporterMessenger = teleporterMessenger - } else { - n.subnetsInfo[subnetInfo.SubnetID].TeleporterMessenger = teleporterMessenger - } - } -} - -func (n *testNetwork) GetFundedAccountInfo() (common.Address, *ecdsa.PrivateKey) { - return n.fundedAddress, n.fundedKey -} - -func (n *testNetwork) IsExternalNetwork() bool { - return true -} - -func (n *testNetwork) SupportsIndependentRelaying() bool { - // The test application cannot relay its own messages on testnets - // because it can't query validators directly for their BLS signatures. - return false -} - -// For testnet messages, rely on a separately deployed relayer to relay the message. -// The implementation checks for the deliver of the given message on the destination -// within a time window of {relayWaitTime} seconds, and returns the receipt of the -// transaction that delivered the message. -func (n *testNetwork) RelayMessage( - ctx context.Context, - sourceReceipt *types.Receipt, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - expectSuccess bool, -) *types.Receipt { - // Get the Teleporter message ID from the receipt - sendEvent, err := utils.GetEventFromLogs( - sourceReceipt.Logs, source.TeleporterMessenger.ParseSendCrossChainMessage, - ) - Expect(err).Should(BeNil()) - - teleporterMessageID := sendEvent.MessageID - - receipt, err := n.getMessageDeliveryTransactionReceipt(ctx, source.BlockchainID, destination, teleporterMessageID) - Expect(err).Should(BeNil()) - Expect(receipt).ShouldNot(BeNil()) - Expect(receipt.Status).Should(Equal(types.ReceiptStatusSuccessful)) - return receipt -} - -func (n *testNetwork) getMessageDeliveryTransactionReceipt( - ctx context.Context, - sourceBlockchainID ids.ID, - destination interfaces.SubnetTestInfo, - teleporterMessageID ids.ID, -) (*types.Receipt, error) { - // Wait until the message is delivered. - queryTicker := time.NewTicker(time.Millisecond * 500) - defer queryTicker.Stop() - - // Wait a maximum of 20 seconds. - cctx, cancel := context.WithTimeout(ctx, 20*time.Second) - defer cancel() - - for { - delivered, err := destination.TeleporterMessenger.MessageReceived(&bind.CallOpts{}, teleporterMessageID) - if err != nil { - return nil, err - } - if delivered { - break - } - - // Wait for the next round. - select { - case <-cctx.Done(): - return nil, cctx.Err() - case <-queryTicker.C: - } - } - - // Get the latest block height - currentBlockHeight, err := destination.RPCClient.BlockNumber(ctx) - if err != nil { - return nil, err - } - - var startBlock uint64 - if currentBlockHeight > receiveCrossChainMessageLookBackBlocks { - startBlock = currentBlockHeight - receiveCrossChainMessageLookBackBlocks - } else { - startBlock = 0 - } - - // Get the log event of the delivery. The log must be in the last {receiveCrossChainMessageLookBackBlocks} blocks. - logIter, err := destination.TeleporterMessenger.FilterReceiveCrossChainMessage( - &bind.FilterOpts{ - Start: startBlock, - Context: cctx, - }, - [][32]byte{teleporterMessageID}, - [][32]byte{sourceBlockchainID}, - nil, - ) - if err != nil { - return nil, err - } - - // There should be exactly one matching event. - if !logIter.Next() { - return nil, errors.New("failed to find ReceiveCrossChainMessage log for relayed message") - } - receiveEvent := logIter.Event - if logIter.Next() { - return nil, errors.New("found multiple ReceiveCrossChainMessage logs for relayed message") - } - - // The transaction should already be mined, but WaitMined will also wait for the eth_blockNumber - // endpoint to reflect the block that the transaction has been included in. - return utils.WaitMined(ctx, destination.RPCClient, receiveEvent.Raw.TxHash) -} - -func (n *testNetwork) GetSignedMessage( - ctx context.Context, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - unsignedWarpMessageID ids.ID, -) *avalancheWarp.Message { - Expect(len(source.NodeURIs)).Should(BeNumerically(">", 0)) - warpClient, err := warpBackend.NewClient(source.NodeURIs[0], source.BlockchainID.String()) - Expect(err).Should(BeNil()) - - signingSubnetID := source.SubnetID - if source.SubnetID == constants.PrimaryNetworkID { - signingSubnetID = destination.SubnetID - } - - signedWarpMessageBytes, err := warpClient.GetMessageAggregateSignature( - ctx, - unsignedWarpMessageID, - warp.WarpDefaultQuorumNumerator, - signingSubnetID.String(), - ) - Expect(err).Should(BeNil()) - - signedWarpMsg, err := avalancheWarp.ParseMessage(signedWarpMessageBytes) - Expect(err).Should(BeNil()) - - return signedWarpMsg -} diff --git a/tests/utils/chain.go b/tests/utils/chain.go new file mode 100644 index 000000000..2d872fdc2 --- /dev/null +++ b/tests/utils/chain.go @@ -0,0 +1,738 @@ +package utils + +import ( + "context" + "crypto/ecdsa" + "encoding/json" + "errors" + "fmt" + goLog "log" + "math/big" + "os" + "slices" + "strconv" + "strings" + "time" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/message" + "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" + avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + relayerConfig "github.com/ava-labs/awm-relayer/config" + "github.com/ava-labs/awm-relayer/peers" + "github.com/ava-labs/awm-relayer/signature-aggregator/aggregator" + sigAggConfig "github.com/ava-labs/awm-relayer/signature-aggregator/config" + "github.com/ava-labs/awm-relayer/signature-aggregator/metrics" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/eth/tracers" + "github.com/ava-labs/subnet-evm/ethclient" + subnetEvmInterfaces "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" + "github.com/ava-labs/subnet-evm/precompile/contracts/warp" + subnetEvmUtils "github.com/ava-labs/subnet-evm/tests/utils" + warpBackend "github.com/ava-labs/subnet-evm/warp" + nativeMinter "github.com/ava-labs/teleporter/abi-bindings/go/INativeMinter" + "github.com/ava-labs/teleporter/tests/interfaces" + gasUtils "github.com/ava-labs/teleporter/utils/gas-utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + . "github.com/onsi/gomega" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + CChainPathSpecifier = "C" +) + +var NativeTransferGas uint64 = 21_000 + +var WarpEnabledChainConfig = tmpnet.FlagsMap{ + "log-level": "debug", + "warp-api-enabled": true, + "local-txs-enabled": true, + "eth-apis": []string{ + "eth", + "eth-filter", + "net", + "admin", + "web3", + "internal-eth", + "internal-blockchain", + "internal-transaction", + "internal-debug", + "internal-account", + "internal-personal", + "debug", + "debug-tracer", + "debug-file-tracer", + "debug-handler", + }, +} + +type Node struct { + NodeID ids.NodeID + NodePoP *signer.ProofOfPossession + Weight uint64 +} + +// +// URL utils +// + +func HttpToWebsocketURI(uri string, blockchainID string) string { + return fmt.Sprintf("ws://%s/ext/bc/%s/ws", strings.TrimPrefix(uri, "http://"), blockchainID) +} + +func HttpToRPCURI(uri string, blockchainID string) string { + return fmt.Sprintf("http://%s/ext/bc/%s/rpc", strings.TrimPrefix(uri, "http://"), blockchainID) +} + +// Get the host and port from a URI. The URI should be in the format http://host:port or https://host:port +func GetURIHostAndPort(uri string) (string, uint32, error) { + // At a minimum uri should have http:// of 7 characters + Expect(len(uri)).Should(BeNumerically(">", 7)) + if uri[:7] == "http://" { + uri = uri[7:] + } else if uri[:8] == "https://" { + uri = uri[8:] + } else { + return "", 0, fmt.Errorf("invalid uri: %s", uri) + } + + // Split the uri into host and port + hostAndPort := strings.Split(uri, ":") + Expect(len(hostAndPort)).Should(Equal(2)) + + // Parse the port + port, err := strconv.ParseUint(hostAndPort[1], 10, 32) + if err != nil { + return "", 0, fmt.Errorf("failed to parse port: %w", err) + } + + return hostAndPort[0], uint32(port), nil +} + +// +// Transaction utils +// + +func CreateNativeTransferTransaction( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + fromKey *ecdsa.PrivateKey, + recipient common.Address, + amount *big.Int, +) *types.Transaction { + fromAddress := crypto.PubkeyToAddress(fromKey.PublicKey) + gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, fromAddress) + + tx := types.NewTx(&types.DynamicFeeTx{ + ChainID: subnetInfo.EVMChainID, + Nonce: nonce, + To: &recipient, + Gas: NativeTransferGas, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Value: amount, + }) + + return SignTransaction(tx, fromKey, subnetInfo.EVMChainID) +} + +func SendNativeTransfer( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + fromKey *ecdsa.PrivateKey, + recipient common.Address, + amount *big.Int, +) *types.Receipt { + tx := CreateNativeTransferTransaction(ctx, subnetInfo, fromKey, recipient, amount) + return SendTransactionAndWaitForSuccess(ctx, subnetInfo, tx) +} + +// Sends a tx, and waits for it to be mined. +// Asserts Receipt.status equals success. +func sendAndWaitForTransaction( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + tx *types.Transaction, + success bool, +) *types.Receipt { + err := subnetInfo.RPCClient.SendTransaction(ctx, tx) + Expect(err).Should(BeNil()) + + return waitForTransaction(ctx, subnetInfo, tx.Hash(), success) +} + +// Sends a tx, and waits for it to be mined. +// Asserts Receipt.status equals false. +func SendTransactionAndWaitForFailure( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + tx *types.Transaction, +) *types.Receipt { + return sendAndWaitForTransaction(ctx, subnetInfo, tx, false) +} + +// Sends a tx, and waits for it to be mined. +// Asserts Receipt.status equals true. +func SendTransactionAndWaitForSuccess( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + tx *types.Transaction, +) *types.Receipt { + return sendAndWaitForTransaction(ctx, subnetInfo, tx, true) +} + +// Waits for a transaction to be mined. +// Asserts Receipt.status equals true. +func WaitForTransactionSuccess( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + txHash common.Hash, +) *types.Receipt { + return waitForTransaction(ctx, subnetInfo, txHash, true) +} + +// Waits for a transaction to be mined. +// Asserts Receipt.status equals false. +func WaitForTransactionFailure( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + txHash common.Hash, +) *types.Receipt { + return waitForTransaction(ctx, subnetInfo, txHash, false) +} + +// Waits for a transaction to be mined. +// Asserts Receipt.status equals success. +func waitForTransaction( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + txHash common.Hash, + success bool, +) *types.Receipt { + cctx, cancel := context.WithTimeout(ctx, 20*time.Second) + defer cancel() + + receipt, err := WaitMined(cctx, subnetInfo.RPCClient, txHash) + Expect(err).Should(BeNil()) + + if success { + if receipt.Status == types.ReceiptStatusFailed { + TraceTransactionAndExit(ctx, subnetInfo.RPCClient, receipt.TxHash) + } + } else { + Expect(receipt.Status).Should(Equal(types.ReceiptStatusFailed)) + } + return receipt +} + +// Polls for a transaction receipt of the given txHash on each queryTicker tick until +// either a transaction receipt returned, or the context is cancelled or expired. +func waitForTransactionReceipt( + cctx context.Context, + rpcClient ethclient.Client, + txHash common.Hash, +) (*types.Receipt, error) { + queryTicker := time.NewTicker(200 * time.Millisecond) + defer queryTicker.Stop() + for { + receipt, err := rpcClient.TransactionReceipt(cctx, txHash) + if err == nil { + return receipt, nil + } + + if errors.Is(err, subnetEvmInterfaces.NotFound) { + log.Debug("Transaction not yet mined") + } else { + log.Error("Receipt retrieval failed", "err", err) + return nil, err + } + + // Wait for the next round. + select { + case <-cctx.Done(): + return nil, cctx.Err() + case <-queryTicker.C: + } + } +} + +// Signs a transaction using the provided key for the specified chainID +func SignTransaction(tx *types.Transaction, key *ecdsa.PrivateKey, chainID *big.Int) *types.Transaction { + txSigner := types.LatestSignerForChainID(chainID) + signedTx, err := types.SignTx(tx, txSigner, key) + Expect(err).Should(BeNil()) + + return signedTx +} + +// Returns the gasFeeCap, gasTipCap, and nonce the be used when constructing a transaction from fundedAddress +func CalculateTxParams( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + fundedAddress common.Address, +) (*big.Int, *big.Int, uint64) { + baseFee, err := subnetInfo.RPCClient.EstimateBaseFee(ctx) + Expect(err).Should(BeNil()) + + gasTipCap, err := subnetInfo.RPCClient.SuggestGasTipCap(ctx) + Expect(err).Should(BeNil()) + + nonce, err := subnetInfo.RPCClient.NonceAt(ctx, fundedAddress, nil) + Expect(err).Should(BeNil()) + + gasFeeCap := baseFee.Mul(baseFee, big.NewInt(gasUtils.BaseFeeFactor)) + gasFeeCap.Add(gasFeeCap, big.NewInt(gasUtils.MaxPriorityFeePerGas)) + + return gasFeeCap, gasTipCap, nonce +} + +// Gomega will print the transaction trace and exit +func TraceTransactionAndExit(ctx context.Context, rpcClient ethclient.Client, txHash common.Hash) { + Expect(TraceTransaction(ctx, rpcClient, txHash)).Should(Equal("")) +} + +func TraceTransaction(ctx context.Context, rpcClient ethclient.Client, txHash common.Hash) string { + var result interface{} + ct := "callTracer" + err := rpcClient.Client().Call(&result, "debug_traceTransaction", txHash.String(), tracers.TraceConfig{Tracer: &ct}) + Expect(err).Should(BeNil()) + + jsonStr, err := json.Marshal(result) + Expect(err).Should(BeNil()) + + return string(jsonStr) +} + +// +// Block utils +// + +// WaitMined waits for tx to be mined on the blockchain. +// It stops waiting when the context is canceled. +// Takes a tx hash instead of the full tx in the subnet-evm version of this function. +// Copied and modified from https://github.com/ava-labs/subnet-evm/blob/v0.6.0-fuji/accounts/abi/bind/util.go#L42 +func WaitMined(ctx context.Context, rpcClient ethclient.Client, txHash common.Hash) (*types.Receipt, error) { + now := time.Now() + receipt, err := waitForTransactionReceipt(ctx, rpcClient, txHash) + if err != nil { + return nil, err + } + since := time.Since(now) + goLog.Println("Transaction mined", "txHash", txHash.Hex(), "duration", since) + + // Check that the block height endpoint returns a block height as high as the block number that the transaction was + // included in. This is to workaround the issue where multiple nodes behind a public RPC endpoint see + // transactions/blocks at different points in time. Ideally, all nodes in the network should have seen this block + // and transaction before returning from WaitMined. The block height endpoint of public RPC endpoints is + // configured to return the lowest value currently returned by any node behind the load balancer, so waiting for + // it to be at least as high as the block height specified in the receipt should provide a relatively strong + // indication that the transaction has been seen widely throughout the network. + err = waitForBlockHeight(ctx, rpcClient, receipt.BlockNumber.Uint64()) + if err != nil { + return nil, err + } + + return receipt, nil +} + +// Polls for the eth_blockNumber endpoint for the latest blockheight on each queryTicker tick until +// either the returned height is greater than or equal to the expectedBlockNumber, or the context +// is cancelled or expired. +func waitForBlockHeight( + cctx context.Context, + rpcClient ethclient.Client, + expectedBlockNumber uint64, +) error { + queryTicker := time.NewTicker(2 * time.Second) + defer queryTicker.Stop() + for { + currentBlockNumber, err := rpcClient.BlockNumber(cctx) + if err != nil { + return err + } + + if currentBlockNumber >= expectedBlockNumber { + return nil + } else { + log.Info("Waiting for block height where transaction was included", + "blockNumber", expectedBlockNumber) + } + + // Wait for the next round. + select { + case <-cctx.Done(): + return cctx.Err() + case <-queryTicker.C: + } + } +} + +// +// Log utils +// + +// Returns the first log in 'logs' that is successfully parsed by 'parser' +// Errors and prints a trace of the transaction if no log is found. +func GetEventFromLogsOrTrace[T any]( + ctx context.Context, + receipt *types.Receipt, + subnetInfo interfaces.SubnetTestInfo, + parser func(log types.Log) (T, error), +) T { + log, err := GetEventFromLogs(receipt.Logs, parser) + if err != nil { + TraceTransactionAndExit(ctx, subnetInfo.RPCClient, receipt.TxHash) + } + return log +} + +// Returns the first log in 'logs' that is successfully parsed by 'parser' +func GetEventFromLogs[T any](logs []*types.Log, parser func(log types.Log) (T, error)) (T, error) { + for _, log := range logs { + event, err := parser(*log) + if err == nil { + return event, nil + } + } + return *new(T), fmt.Errorf("failed to find %T event in receipt logs", *new(T)) +} + +// +// Account utils +// + +func PrivateKeyToAddress(k *ecdsa.PrivateKey) common.Address { + return crypto.PubkeyToAddress(k.PublicKey) +} + +// Throws a Gomega error if there is a mismatch +func CheckBalance(ctx context.Context, addr common.Address, expectedBalance *big.Int, rpcClient ethclient.Client) { + bal, err := rpcClient.BalanceAt(ctx, addr, nil) + Expect(err).Should(BeNil()) + ExpectBigEqual(bal, expectedBalance) +} + +// +// Big int utils +// + +func ExpectBigEqual(v1 *big.Int, v2 *big.Int) { + // Compare strings, so gomega will print the numbers if they differ + Expect(v1.String()).Should(Equal(v2.String())) +} + +func BigIntSub(v1 *big.Int, v2 *big.Int) *big.Int { + return big.NewInt(0).Sub(v1, v2) +} + +func BigIntMul(v1 *big.Int, v2 *big.Int) *big.Int { + return big.NewInt(0).Mul(v1, v2) +} + +// +// Network utils +// + +func GetPChainInfo(cChainInfo interfaces.SubnetTestInfo) interfaces.SubnetTestInfo { + pChainBlockchainID, err := info.NewClient(cChainInfo.NodeURIs[0]).GetBlockchainID(context.Background(), "P") + Expect(err).Should(BeNil()) + return interfaces.SubnetTestInfo{ + BlockchainID: pChainBlockchainID, + SubnetID: ids.Empty, + } +} + +func GetTwoSubnets(network interfaces.Network) ( + interfaces.SubnetTestInfo, + interfaces.SubnetTestInfo, +) { + subnets := network.GetSubnetsInfo() + Expect(len(subnets)).Should(BeNumerically(">=", 2)) + return subnets[0], subnets[1] +} + +type ChainConfigMap map[string]string + +// Sets the chain config in customChainConfigs for the specified subnet +func (m ChainConfigMap) Add(subnet interfaces.SubnetTestInfo, chainConfig string) { + if subnet.SubnetID == constants.PrimaryNetworkID { + m[CChainPathSpecifier] = chainConfig + } else { + m[subnet.BlockchainID.String()] = chainConfig + } +} + +func GetChainConfigWithOffChainMessages(offChainMessages []avalancheWarp.UnsignedMessage) string { + // Convert messages to hex + hexOffChainMessages := []string{} + for _, message := range offChainMessages { + hexOffChainMessages = append(hexOffChainMessages, hexutil.Encode(message.Bytes())) + } + + chainConfig := WarpEnabledChainConfig + chainConfig["warp-off-chain-messages"] = hexOffChainMessages + + // Marshal the map to JSON + offChainMessageJson, err := tmpnet.DefaultJSONMarshal(chainConfig) + Expect(err).Should(BeNil()) + + return string(offChainMessageJson) +} + +// read in the template file, make the substitutions declared at the beginning +// of the function, write out the instantiation to a temp file, and then return +// the path to that temp file. +func InstantiateGenesisTemplate( + templateFileName string, + chainID uint64, + teleporterContractAddress common.Address, + teleporterDeployedBytecode string, + teleporterDeployerAddress common.Address, +) string { + if teleporterContractAddress.Big().Cmp(big.NewInt(0)) == 0 { + teleporterContractAddress = common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff") + } + if teleporterDeployerAddress.Big().Cmp(big.NewInt(0)) == 0 { + teleporterDeployerAddress = common.HexToAddress("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + } + if teleporterDeployedBytecode == "" { + teleporterDeployedBytecode = "0x00" + } + + substitutions := []struct { + Target string + Value string + }{ + { + "", + strconv.FormatUint(chainID, 10), + }, + { + "", + teleporterContractAddress.Hex(), + }, + { + "", + teleporterDeployedBytecode, + }, + { + "", + teleporterDeployerAddress.Hex(), + }, + } + + templateFileBytes, err := os.ReadFile(templateFileName) + Expect(err).Should(BeNil()) + + subnetGenesisFile, err := os.CreateTemp(os.TempDir(), "") + Expect(err).Should(BeNil()) + + defer subnetGenesisFile.Close() + + var replaced string = string(templateFileBytes[:]) + for _, s := range substitutions { + replaced = strings.ReplaceAll(replaced, s.Target, s.Value) + } + + subnetGenesisFile.WriteString(replaced) + + return subnetGenesisFile.Name() +} + +// +// Aggregator utils +// + +func NewSignatureAggregator(apiUri string, subnets []ids.ID) *aggregator.SignatureAggregator { + cfg := sigAggConfig.Config{ + PChainAPI: &relayerConfig.APIConfig{ + BaseURL: apiUri, + }, + InfoAPI: &relayerConfig.APIConfig{ + BaseURL: apiUri, + }, + } + trackedSubnets := set.NewSet[ids.ID](len(subnets)) + trackedSubnets.Add(subnets...) + registry := prometheus.NewRegistry() + appRequestNetwork, err := peers.NewNetwork( + logging.Info, + registry, + trackedSubnets, + &cfg, + ) + Expect(err).Should(BeNil()) + + messageCreator, err := message.NewCreator( + logging.NoLog{}, + registry, + constants.DefaultNetworkCompressionType, + constants.DefaultNetworkMaximumInboundTimeout, + ) + Expect(err).Should(BeNil()) + agg, err := aggregator.NewSignatureAggregator( + appRequestNetwork, + logging.NoLog{}, + 1024, + metrics.NewSignatureAggregatorMetrics(prometheus.NewRegistry()), + messageCreator, + // Setting the etnaTime to a minute ago so that the post-etna code path is used in the test + time.Now().Add(-1*time.Minute), + ) + Expect(err).Should(BeNil()) + return agg +} + +// +// Native minter utils +// + +// Funded key must have admin access to set new admin. +func AddNativeMinterAdmin( + ctx context.Context, + subnet interfaces.SubnetTestInfo, + fundedKey *ecdsa.PrivateKey, + address common.Address, +) { + nativeMinterPrecompile, err := nativeMinter.NewINativeMinter(nativeminter.ContractAddress, subnet.RPCClient) + Expect(err).Should(BeNil()) + + opts, err := bind.NewKeyedTransactorWithChainID(fundedKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := nativeMinterPrecompile.SetAdmin(opts, address) + Expect(err).Should(BeNil()) + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +// Blocks until all validators specified in nodeURIs have reached the specified block height +func WaitForAllValidatorsToAcceptBlock(ctx context.Context, nodeURIs []string, blockchainID ids.ID, height uint64) { + cctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + for i, uri := range nodeURIs { + chainAWSURI := HttpToWebsocketURI(uri, blockchainID.String()) + log.Debug("Creating ethclient for blockchain", "blockchainID", blockchainID.String(), "wsURI", chainAWSURI) + client, err := ethclient.Dial(chainAWSURI) + Expect(err).Should(BeNil()) + defer client.Close() + + // Loop until each node has advanced to >= the height of the block that emitted the warp log + for { + block, err := client.BlockByNumber(cctx, nil) + Expect(err).Should(BeNil()) + if block.NumberU64() >= height { + log.Debug("Client accepted the block containing SendWarpMessage", "client", i, "height", block.NumberU64()) + break + } + } + } +} + +func ExtractWarpMessageFromLog( + ctx context.Context, + sourceReceipt *types.Receipt, + source interfaces.SubnetTestInfo, +) *avalancheWarp.UnsignedMessage { + log.Info("Fetching relevant warp logs from the newly produced block") + logs, err := source.RPCClient.FilterLogs(ctx, subnetEvmInterfaces.FilterQuery{ + BlockHash: &sourceReceipt.BlockHash, + Addresses: []common.Address{warp.Module.Address}, + }) + Expect(err).Should(BeNil()) + Expect(len(logs)).Should(Equal(1)) + + // Check for relevant warp log from subscription and ensure that it matches + // the log extracted from the last block. + txLog := logs[0] + log.Info("Parsing logData as unsigned warp message") + unsignedMsg, err := warp.UnpackSendWarpEventDataToMessage(txLog.Data) + Expect(err).Should(BeNil()) + return unsignedMsg +} + +func ConstructSignedWarpMessage( + ctx context.Context, + sourceReceipt *types.Receipt, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, +) *avalancheWarp.Message { + unsignedMsg := ExtractWarpMessageFromLog(ctx, sourceReceipt, source) + + // Set local variables for the duration of the test + unsignedWarpMessageID := unsignedMsg.ID() + log.Info( + "Parsed unsignedWarpMsg", + "unsignedWarpMessageID", unsignedWarpMessageID, + "unsignedWarpMessage", unsignedMsg, + ) + + // Loop over each client on source chain to ensure they all have time to accept the block. + // Note: if we did not confirm this here, the next stage could be racy since it assumes every node + // has accepted the block. + WaitForAllValidatorsToAcceptBlock(ctx, source.NodeURIs, source.BlockchainID, sourceReceipt.BlockNumber.Uint64()) + + // Get the aggregate signature for the Warp message + log.Info("Fetching aggregate signature from the source chain validators") + return GetSignedMessage(ctx, source, destination, unsignedWarpMessageID) +} + +func GetSignedMessage( + ctx context.Context, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, + unsignedWarpMessageID ids.ID, +) *avalancheWarp.Message { + Expect(len(source.NodeURIs)).Should(BeNumerically(">", 0)) + warpClient, err := warpBackend.NewClient(source.NodeURIs[0], source.BlockchainID.String()) + Expect(err).Should(BeNil()) + + signingSubnetID := source.SubnetID + if source.SubnetID == constants.PrimaryNetworkID { + signingSubnetID = destination.SubnetID + } + + // Get the aggregate signature for the Warp message + signedWarpMessageBytes, err := warpClient.GetMessageAggregateSignature( + ctx, + unsignedWarpMessageID, + warp.WarpDefaultQuorumNumerator, + signingSubnetID.String(), + ) + Expect(err).Should(BeNil()) + + signedWarpMsg, err := avalancheWarp.ParseMessage(signedWarpMessageBytes) + Expect(err).Should(BeNil()) + + return signedWarpMsg +} + +func SetupProposerVM(ctx context.Context, fundedKey *ecdsa.PrivateKey, network *tmpnet.Network, subnetID ids.ID) { + subnetDetails := network.Subnets[slices.IndexFunc( + network.Subnets, + func(s *tmpnet.Subnet) bool { return s.SubnetID == subnetID }, + )] + + chainID := subnetDetails.Chains[0].ChainID + + nodeURI, err := network.GetURIForNodeID(subnetDetails.ValidatorIDs[0]) + Expect(err).Should(BeNil()) + uri := HttpToWebsocketURI(nodeURI, chainID.String()) + + client, err := ethclient.Dial(uri) + Expect(err).Should(BeNil()) + chainIDInt, err := client.ChainID(ctx) + Expect(err).Should(BeNil()) + + err = subnetEvmUtils.IssueTxsToActivateProposerVMFork(ctx, chainIDInt, fundedKey, client) + Expect(err).Should(BeNil()) +} diff --git a/tests/utils/erc20.go b/tests/utils/erc20.go new file mode 100644 index 000000000..b235dbf6d --- /dev/null +++ b/tests/utils/erc20.go @@ -0,0 +1,61 @@ +package utils + +import ( + "context" + "crypto/ecdsa" + "math/big" + + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + exampleerc20 "github.com/ava-labs/teleporter/abi-bindings/go/mocks/ExampleERC20" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + . "github.com/onsi/gomega" +) + +var ( + ExpectedExampleERC20DeployerBalance = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e10)) +) + +func DeployExampleERC20( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + source interfaces.SubnetTestInfo, +) (common.Address, *exampleerc20.ExampleERC20) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) + Expect(err).Should(BeNil()) + + // Deploy Mock ERC20 contract + address, tx, token, err := exampleerc20.DeployExampleERC20(opts, source.RPCClient) + Expect(err).Should(BeNil()) + log.Info("Deployed Mock ERC20 contract", "address", address.Hex(), "txHash", tx.Hash().Hex()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, source, tx.Hash()) + + // Check that the deployer has the expected initial balance + senderAddress := crypto.PubkeyToAddress(senderKey.PublicKey) + balance, err := token.BalanceOf(&bind.CallOpts{}, senderAddress) + Expect(err).Should(BeNil()) + Expect(balance).Should(Equal(ExpectedExampleERC20DeployerBalance)) + + return address, token +} + +func ERC20Approve( + ctx context.Context, + token *exampleerc20.ExampleERC20, + spender common.Address, + amount *big.Int, + source interfaces.SubnetTestInfo, + senderKey *ecdsa.PrivateKey, +) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := token.Approve(opts, spender, amount) + Expect(err).Should(BeNil()) + log.Info("Approved ERC20", "spender", spender.Hex(), "txHash", tx.Hash().Hex()) + + WaitForTransactionSuccess(ctx, source, tx.Hash()) +} diff --git a/tests/utils/governance.go b/tests/utils/governance.go new file mode 100644 index 000000000..96d03555d --- /dev/null +++ b/tests/utils/governance.go @@ -0,0 +1,108 @@ +package utils + +import ( + "context" + "crypto/ecdsa" + + avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + validatorsetsig "github.com/ava-labs/teleporter/abi-bindings/go/governance/ValidatorSetSig" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + . "github.com/onsi/gomega" +) + +func DeployValidatorSetSig( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + contractSubnet interfaces.SubnetTestInfo, + validatorSubnet interfaces.SubnetTestInfo, +) (common.Address, *validatorsetsig.ValidatorSetSig) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, contractSubnet.EVMChainID) + Expect(err).Should(BeNil()) + address, tx, validatorSetSig, err := validatorsetsig.DeployValidatorSetSig( + opts, + contractSubnet.RPCClient, + validatorSubnet.BlockchainID, + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, contractSubnet, tx.Hash()) + + return address, validatorSetSig +} + +// Returns Receipt for the transaction unlike TeleporterRegistry version since this is a non-teleporter case +// and we don't want to add the ValidatorSetSig ABI to the subnetInfo +func ExecuteValidatorSetSigCallAndVerify( + ctx context.Context, + network interfaces.Network, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, + validatorSetSigAddress common.Address, + senderKey *ecdsa.PrivateKey, + unsignedMessage *avalancheWarp.UnsignedMessage, + expectSuccess bool, +) *types.Receipt { + signedWarpMsg := GetSignedMessage(ctx, source, destination, unsignedMessage.ID()) + log.Info("Got signed warp message", "messageID", signedWarpMsg.ID()) + + signedPredicateTx := CreateExecuteCallPredicateTransaction( + ctx, + signedWarpMsg, + validatorSetSigAddress, + senderKey, + destination, + ) + + // Wait for tx to be accepted and verify events emitted + if expectSuccess { + return SendTransactionAndWaitForSuccess(ctx, destination, signedPredicateTx) + } + return SendTransactionAndWaitForFailure(ctx, destination, signedPredicateTx) +} + +func InitOffChainMessageChainConfigValidatorSetSig( + networkID uint32, + subnet interfaces.SubnetTestInfo, + validatorSetSigAddress common.Address, + validatorSetSigMessages []validatorsetsig.ValidatorSetSigMessage, +) ([]avalancheWarp.UnsignedMessage, string) { + unsignedMessages := []avalancheWarp.UnsignedMessage{} + for _, message := range validatorSetSigMessages { + unsignedMessage := CreateOffChainValidatorSetSigMessage(networkID, subnet, message) + unsignedMessages = append(unsignedMessages, *unsignedMessage) + log.Info("Adding validatorSetSig off-chain message to Warp chain config", + "messageID", unsignedMessage.ID(), + "blockchainID", subnet.BlockchainID.String()) + } + return unsignedMessages, GetChainConfigWithOffChainMessages(unsignedMessages) +} + +// Creates an off-chain Warp message pointing to a function, contract and payload to be executed +// if the validator set signs this message +func CreateOffChainValidatorSetSigMessage( + networkID uint32, + subnet interfaces.SubnetTestInfo, + message validatorsetsig.ValidatorSetSigMessage, +) *avalancheWarp.UnsignedMessage { + sourceAddress := []byte{} + payloadBytes, err := message.Pack() + Expect(err).Should(BeNil()) + + addressedPayload, err := payload.NewAddressedCall(sourceAddress, payloadBytes) + Expect(err).Should(BeNil()) + + unsignedMessage, err := avalancheWarp.NewUnsignedMessage( + networkID, + subnet.BlockchainID, + addressedPayload.Bytes(), + ) + Expect(err).Should(BeNil()) + + return unsignedMessage +} diff --git a/tests/utils/proxy.go b/tests/utils/proxy.go new file mode 100644 index 000000000..36b6413d3 --- /dev/null +++ b/tests/utils/proxy.go @@ -0,0 +1,49 @@ +package utils + +import ( + "context" + "crypto/ecdsa" + + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + proxyadmin "github.com/ava-labs/teleporter/abi-bindings/go/ProxyAdmin" + transparentupgradeableproxy "github.com/ava-labs/teleporter/abi-bindings/go/TransparentUpgradeableProxy" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + . "github.com/onsi/gomega" +) + +func DeployTransparentUpgradeableProxy[T any]( + ctx context.Context, + subnet interfaces.SubnetTestInfo, + senderKey *ecdsa.PrivateKey, + implAddress common.Address, + newInstance func(address common.Address, backend bind.ContractBackend) (*T, error), +) (common.Address, *proxyadmin.ProxyAdmin, *T) { + opts, err := bind.NewKeyedTransactorWithChainID( + senderKey, + subnet.EVMChainID, + ) + Expect(err).Should((BeNil())) + + senderAddress := crypto.PubkeyToAddress(senderKey.PublicKey) + proxyAddress, tx, proxy, err := transparentupgradeableproxy.DeployTransparentUpgradeableProxy( + opts, + subnet.RPCClient, + implAddress, + senderAddress, + []byte{}, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + proxyAdminEvent, err := GetEventFromLogs(receipt.Logs, proxy.ParseAdminChanged) + Expect(err).Should(BeNil()) + + proxyAdmin, err := proxyadmin.NewProxyAdmin(proxyAdminEvent.NewAdmin, subnet.RPCClient) + Expect(err).Should(BeNil()) + + contract, err := newInstance(proxyAddress, subnet.RPCClient) + Expect(err).Should(BeNil()) + + return proxyAddress, proxyAdmin, contract +} diff --git a/tests/utils/teleporter.go b/tests/utils/teleporter.go new file mode 100644 index 000000000..3c92413b7 --- /dev/null +++ b/tests/utils/teleporter.go @@ -0,0 +1,825 @@ +package utils + +import ( + "bytes" + "context" + "crypto/ecdsa" + "math/big" + + "github.com/ava-labs/avalanchego/ids" + avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/precompile/contracts/warp" + predicateutils "github.com/ava-labs/subnet-evm/predicate" + "github.com/ava-labs/subnet-evm/rpc" + validatorsetsig "github.com/ava-labs/teleporter/abi-bindings/go/governance/ValidatorSetSig" + exampleerc20 "github.com/ava-labs/teleporter/abi-bindings/go/mocks/ExampleERC20" + teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/TeleporterMessenger" + teleporterregistry "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/registry/TeleporterRegistry" + testmessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/tests/TestMessenger" + "github.com/ava-labs/teleporter/tests/interfaces" + deploymentUtils "github.com/ava-labs/teleporter/utils/deployment-utils" + gasUtils "github.com/ava-labs/teleporter/utils/gas-utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + . "github.com/onsi/gomega" +) + +var ( + DefaultTeleporterTransactionGas uint64 = 300_000 + DefaultTeleporterTransactionValue = common.Big0 +) + +type ChainTeleporterInfo struct { + TeleporterRegistry *teleporterregistry.TeleporterRegistry + TeleporterRegistryAddress common.Address + + TeleporterMessenger *teleportermessenger.TeleporterMessenger + TeleporterMessengerAddress common.Address +} + +type TeleporterTestInfo map[ids.ID]*ChainTeleporterInfo + +func NewTeleporterTestInfo(subnets []interfaces.SubnetTestInfo) TeleporterTestInfo { + t := make(TeleporterTestInfo) + for _, subnet := range subnets { + t[subnet.BlockchainID] = &ChainTeleporterInfo{} + } + return t +} + +func (t TeleporterTestInfo) TeleporterMessenger( + subnet interfaces.SubnetTestInfo, +) *teleportermessenger.TeleporterMessenger { + return t[subnet.BlockchainID].TeleporterMessenger +} + +func (t TeleporterTestInfo) TeleporterMessengerAddress(subnet interfaces.SubnetTestInfo) common.Address { + return t[subnet.BlockchainID].TeleporterMessengerAddress +} + +func (t TeleporterTestInfo) TeleporterRegistry( + subnet interfaces.SubnetTestInfo, +) *teleporterregistry.TeleporterRegistry { + return t[subnet.BlockchainID].TeleporterRegistry +} + +func (t TeleporterTestInfo) TeleporterRegistryAddress(subnet interfaces.SubnetTestInfo) common.Address { + return t[subnet.BlockchainID].TeleporterRegistryAddress +} + +func (t TeleporterTestInfo) SetTeleporter(address common.Address, subnet interfaces.SubnetTestInfo) { + teleporterMessenger, err := teleportermessenger.NewTeleporterMessenger( + address, subnet.RPCClient, + ) + Expect(err).Should(BeNil()) + info := t[subnet.BlockchainID] + info.TeleporterMessengerAddress = address + info.TeleporterMessenger = teleporterMessenger +} + +func (t TeleporterTestInfo) InitializeBlockchainID(subnet interfaces.SubnetTestInfo, fundedKey *ecdsa.PrivateKey) { + opts, err := bind.NewKeyedTransactorWithChainID(fundedKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := t.TeleporterMessenger(subnet).InitializeBlockchainID(opts) + Expect(err).Should(BeNil()) + WaitForTransactionSuccess(context.Background(), subnet, tx.Hash()) +} + +func (t TeleporterTestInfo) DeployTeleporterRegistry(subnet interfaces.SubnetTestInfo, deployerKey *ecdsa.PrivateKey) { + ctx := context.Background() + entries := []teleporterregistry.ProtocolRegistryEntry{ + { + Version: big.NewInt(1), + ProtocolAddress: t.TeleporterMessengerAddress(subnet), + }, + } + opts, err := bind.NewKeyedTransactorWithChainID(deployerKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + teleporterRegistryAddress, tx, teleporterRegistry, err := teleporterregistry.DeployTeleporterRegistry( + opts, subnet.RPCClient, entries, + ) + Expect(err).Should(BeNil()) + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + info := t[subnet.BlockchainID] + info.TeleporterRegistryAddress = teleporterRegistryAddress + info.TeleporterRegistry = teleporterRegistry +} + +func (t TeleporterTestInfo) DeployTeleporterMessenger( + ctx context.Context, + subnet interfaces.SubnetTestInfo, + transactionBytes []byte, + deployerAddress common.Address, + contractAddress common.Address, + fundedKey *ecdsa.PrivateKey, +) { + // Fund the deployer address + fundAmount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(11)) // 11 AVAX + fundDeployerTx := CreateNativeTransferTransaction( + ctx, subnet, fundedKey, deployerAddress, fundAmount, + ) + SendTransactionAndWaitForSuccess(ctx, subnet, fundDeployerTx) + + log.Info("Finished funding Teleporter deployer", "blockchainID", subnet.BlockchainID.Hex()) + + // Deploy Teleporter contract + rpcClient, err := rpc.DialContext( + ctx, + HttpToRPCURI(subnet.NodeURIs[0], subnet.BlockchainID.String()), + ) + Expect(err).Should(BeNil()) + defer rpcClient.Close() + + txHash := common.Hash{} + err = rpcClient.CallContext(ctx, &txHash, "eth_sendRawTransaction", hexutil.Encode(transactionBytes)) + Expect(err).Should(BeNil()) + WaitForTransactionSuccess(ctx, subnet, txHash) + + teleporterCode, err := subnet.RPCClient.CodeAt(ctx, contractAddress, nil) + Expect(err).Should(BeNil()) + Expect(len(teleporterCode)).Should(BeNumerically(">", 2)) // 0x is an EOA, contract returns the bytecode +} + +func (t TeleporterTestInfo) RelayTeleporterMessage( + ctx context.Context, + sourceReceipt *types.Receipt, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, + expectSuccess bool, + fundedKey *ecdsa.PrivateKey, +) *types.Receipt { + // Fetch the Teleporter message from the logs + sendEvent, err := GetEventFromLogs(sourceReceipt.Logs, t.TeleporterMessenger(source).ParseSendCrossChainMessage) + Expect(err).Should(BeNil()) + + signedWarpMessage := ConstructSignedWarpMessage(ctx, sourceReceipt, source, destination) + + // Construct the transaction to send the Warp message to the destination chain + signedTx := CreateReceiveCrossChainMessageTransaction( + ctx, + signedWarpMessage, + sendEvent.Message.RequiredGasLimit, + t.TeleporterMessengerAddress(source), + fundedKey, + destination, + ) + + log.Info("Sending transaction to destination chain") + if !expectSuccess { + return SendTransactionAndWaitForFailure(ctx, destination, signedTx) + } + + receipt := SendTransactionAndWaitForSuccess(ctx, destination, signedTx) + + // Check the transaction logs for the ReceiveCrossChainMessage event emitted by the Teleporter contract + receiveEvent, err := GetEventFromLogs( + receipt.Logs, + t.TeleporterMessenger(destination).ParseReceiveCrossChainMessage, + ) + Expect(err).Should(BeNil()) + Expect(receiveEvent.SourceBlockchainID[:]).Should(Equal(source.BlockchainID[:])) + return receipt +} + +// +// Deployment utils +// + +// Deploys a new version of Teleporter and returns its address +// Does NOT modify the global Teleporter contract address to provide greater testing flexibility. +func DeployNewTeleporterVersion( + ctx context.Context, + teleporterInfo TeleporterTestInfo, + subnet interfaces.SubnetTestInfo, + fundedKey *ecdsa.PrivateKey, + teleporterByteCodeFile string, +) common.Address { + contractCreationGasPrice := (&big.Int{}).Add(deploymentUtils.GetDefaultContractCreationGasPrice(), big.NewInt(1)) + teleporterDeployerTransaction, + _, + teleporterDeployerAddress, + teleporterContractAddress, + err := deploymentUtils.ConstructKeylessTransaction( + teleporterByteCodeFile, + false, + contractCreationGasPrice, + ) + Expect(err).Should(BeNil()) + + teleporterInfo.DeployTeleporterMessenger( + ctx, + subnet, + teleporterDeployerTransaction, + teleporterDeployerAddress, + teleporterContractAddress, + fundedKey, + ) + + return teleporterContractAddress +} + +func DeployTestMessenger( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + teleporterManager common.Address, + registryAddress common.Address, + subnet interfaces.SubnetTestInfo, +) (common.Address, *testmessenger.TestMessenger) { + opts, err := bind.NewKeyedTransactorWithChainID( + senderKey, + subnet.EVMChainID, + ) + Expect(err).Should(BeNil()) + address, tx, exampleMessenger, err := testmessenger.DeployTestMessenger( + opts, + subnet.RPCClient, + registryAddress, + teleporterManager, + big.NewInt(1), + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return address, exampleMessenger +} + +// +// Parsing utils +// + +func ParseTeleporterMessage(unsignedMessage avalancheWarp.UnsignedMessage) *teleportermessenger.TeleporterMessage { + addressedPayload, err := payload.ParseAddressedCall(unsignedMessage.Payload) + Expect(err).Should(BeNil()) + + teleporterMessage := teleportermessenger.TeleporterMessage{} + err = teleporterMessage.Unpack(addressedPayload.Payload) + Expect(err).Should(BeNil()) + + return &teleporterMessage +} + +// +// Function call utils +// + +func SendAddFeeAmountAndWaitForAcceptance( + ctx context.Context, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, + messageID ids.ID, + amount *big.Int, + feeContractAddress common.Address, + senderKey *ecdsa.PrivateKey, + transactor *teleportermessenger.TeleporterMessenger, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID( + senderKey, + source.EVMChainID, + ) + Expect(err).Should(BeNil()) + + tx, err := transactor.AddFeeAmount(opts, messageID, feeContractAddress, amount) + Expect(err).Should(BeNil()) + + receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) + + addFeeAmountEvent, err := GetEventFromLogs(receipt.Logs, transactor.ParseAddFeeAmount) + Expect(err).Should(BeNil()) + Expect(addFeeAmountEvent.MessageID[:]).Should(Equal(messageID[:])) + + log.Info("Send AddFeeAmount transaction on source chain", + "messageID", messageID, + "sourceChainID", source.BlockchainID, + "destinationBlockchainID", destination.BlockchainID, + ) + + return receipt +} + +func RetryMessageExecutionAndWaitForAcceptance( + ctx context.Context, + sourceBlockchainID ids.ID, + destinationTeleporterMessenger *teleportermessenger.TeleporterMessenger, + destinationSubnet interfaces.SubnetTestInfo, + message teleportermessenger.TeleporterMessage, + senderKey *ecdsa.PrivateKey, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, destinationSubnet.EVMChainID) + Expect(err).Should(BeNil()) + + tx, err := destinationTeleporterMessenger.RetryMessageExecution(opts, sourceBlockchainID, message) + Expect(err).Should(BeNil()) + + return WaitForTransactionSuccess(ctx, destinationSubnet, tx.Hash()) +} + +func RedeemRelayerRewardsAndConfirm( + ctx context.Context, + teleporterMessenger *teleportermessenger.TeleporterMessenger, + subnet interfaces.SubnetTestInfo, + feeToken *exampleerc20.ExampleERC20, + feeTokenAddress common.Address, + redeemerKey *ecdsa.PrivateKey, + expectedAmount *big.Int, +) *types.Receipt { + redeemerAddress := crypto.PubkeyToAddress(redeemerKey.PublicKey) + + // Check the ERC20 balance before redemption + balanceBeforeRedemption, err := feeToken.BalanceOf( + &bind.CallOpts{}, redeemerAddress, + ) + Expect(err).Should(BeNil()) + + // Redeem the rewards + txOpts, err := bind.NewKeyedTransactorWithChainID( + redeemerKey, subnet.EVMChainID, + ) + Expect(err).Should(BeNil()) + tx, err := teleporterMessenger.RedeemRelayerRewards( + txOpts, feeTokenAddress, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + // Check that the ERC20 balance was incremented + balanceAfterRedemption, err := feeToken.BalanceOf( + &bind.CallOpts{}, redeemerAddress, + ) + Expect(err).Should(BeNil()) + Expect(balanceAfterRedemption).Should( + Equal( + big.NewInt(0).Add( + balanceBeforeRedemption, expectedAmount, + ), + ), + ) + + // Check that the redeemable rewards amount is now zero. + updatedRewardAmount, err := teleporterMessenger.CheckRelayerRewardAmount( + &bind.CallOpts{}, + redeemerAddress, + feeTokenAddress, + ) + Expect(err).Should(BeNil()) + Expect(updatedRewardAmount.Cmp(big.NewInt(0))).Should(Equal(0)) + + return receipt +} + +func SendSpecifiedReceiptsAndWaitForAcceptance( + ctx context.Context, + sourceTeleporterMessenger *teleportermessenger.TeleporterMessenger, + source interfaces.SubnetTestInfo, + destinationBlockchainID ids.ID, + messageIDs [][32]byte, + feeInfo teleportermessenger.TeleporterFeeInfo, + allowedRelayerAddresses []common.Address, + senderKey *ecdsa.PrivateKey, +) (*types.Receipt, ids.ID) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) + Expect(err).Should(BeNil()) + + tx, err := sourceTeleporterMessenger.SendSpecifiedReceipts( + opts, destinationBlockchainID, messageIDs, feeInfo, allowedRelayerAddresses) + Expect(err).Should(BeNil()) + + receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) + + // Check the transaction logs for the SendCrossChainMessage event emitted by the Teleporter contract + event, err := GetEventFromLogs(receipt.Logs, sourceTeleporterMessenger.ParseSendCrossChainMessage) + Expect(err).Should(BeNil()) + Expect(event.DestinationBlockchainID[:]).Should(Equal(destinationBlockchainID[:])) + + log.Info("Sending SendSpecifiedReceipts transaction", + "destinationBlockchainID", destinationBlockchainID, + "txHash", tx.Hash()) + + return receipt, event.MessageID +} + +func AddProtocolVersionAndWaitForAcceptance( + ctx context.Context, + sourceTeleporterInfo ChainTeleporterInfo, + subnet interfaces.SubnetTestInfo, + newTeleporterAddress common.Address, + senderKey *ecdsa.PrivateKey, + unsignedMessage *avalancheWarp.UnsignedMessage, +) { + signedWarpMsg := GetSignedMessage(ctx, subnet, subnet, unsignedMessage.ID()) + log.Info("Got signed warp message", "messageID", signedWarpMsg.ID()) + + // Construct tx to add protocol version and send to destination chain + signedTx := CreateAddProtocolVersionTransaction( + ctx, + signedWarpMsg, + sourceTeleporterInfo.TeleporterRegistryAddress, + senderKey, + subnet, + ) + + curLatestVersion, err := sourceTeleporterInfo.TeleporterRegistry.LatestVersion(&bind.CallOpts{}) + Expect(err).Should(BeNil()) + expectedLatestVersion := big.NewInt(curLatestVersion.Int64() + 1) + + // Wait for tx to be accepted, and verify events emitted + receipt := SendTransactionAndWaitForSuccess(ctx, subnet, signedTx) + addProtocolVersionEvent, err := GetEventFromLogs( + receipt.Logs, + sourceTeleporterInfo.TeleporterRegistry.ParseAddProtocolVersion, + ) + Expect(err).Should(BeNil()) + Expect(addProtocolVersionEvent.Version.Cmp(expectedLatestVersion)).Should(Equal(0)) + Expect(addProtocolVersionEvent.ProtocolAddress).Should(Equal(newTeleporterAddress)) + + versionUpdatedEvent, err := GetEventFromLogs( + receipt.Logs, + sourceTeleporterInfo.TeleporterRegistry.ParseLatestVersionUpdated, + ) + Expect(err).Should(BeNil()) + Expect(versionUpdatedEvent.OldVersion.Cmp(curLatestVersion)).Should(Equal(0)) + Expect(versionUpdatedEvent.NewVersion.Cmp(expectedLatestVersion)).Should(Equal(0)) +} + +func SendCrossChainMessageAndWaitForAcceptance( + ctx context.Context, + sourceTeleporterMessenger *teleportermessenger.TeleporterMessenger, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, + input teleportermessenger.TeleporterMessageInput, + senderKey *ecdsa.PrivateKey, +) (*types.Receipt, ids.ID) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) + Expect(err).Should(BeNil()) + + // Send a transaction to the Teleporter contract + tx, err := sourceTeleporterMessenger.SendCrossChainMessage(opts, input) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be accepted + receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) + + // Check the transaction logs for the SendCrossChainMessage event emitted by the Teleporter contract + event, err := GetEventFromLogs(receipt.Logs, sourceTeleporterMessenger.ParseSendCrossChainMessage) + Expect(err).Should(BeNil()) + + log.Info("Sending SendCrossChainMessage transaction on source chain", + "sourceChainID", source.BlockchainID, + "destinationBlockchainID", destination.BlockchainID, + "txHash", tx.Hash()) + + return receipt, event.MessageID +} + +// Returns true if the transaction receipt contains a ReceiptReceived log with the specified messageID +func CheckReceiptReceived( + receipt *types.Receipt, + messageID [32]byte, + transactor *teleportermessenger.TeleporterMessenger, +) bool { + for _, log := range receipt.Logs { + event, err := transactor.ParseReceiptReceived(*log) + if err == nil && bytes.Equal(event.MessageID[:], messageID[:]) { + return true + } + } + return false +} + +func ClearReceiptQueue( + ctx context.Context, + teleporterInfo TeleporterTestInfo, + source interfaces.SubnetTestInfo, + destination interfaces.SubnetTestInfo, + fundedKey *ecdsa.PrivateKey, +) { + outstandReceiptCount := GetOutstandingReceiptCount( + teleporterInfo.TeleporterMessenger(source), + destination.BlockchainID, + ) + for outstandReceiptCount.Cmp(big.NewInt(0)) != 0 { + log.Info("Emptying receipt queue", "remainingReceipts", outstandReceiptCount.String()) + // Send message from Subnet B to Subnet A to trigger the "regular" method of delivering receipts. + // The next message from B->A will contain the same receipts that were manually sent in the above steps, + // but they should not be processed again on Subnet A. + sendCrossChainMessageInput := teleportermessenger.TeleporterMessageInput{ + DestinationBlockchainID: destination.BlockchainID, + DestinationAddress: common.HexToAddress("0x1111111111111111111111111111111111111111"), + RequiredGasLimit: big.NewInt(1), + FeeInfo: teleportermessenger.TeleporterFeeInfo{ + FeeTokenAddress: common.Address{}, + Amount: big.NewInt(0), + }, + AllowedRelayerAddresses: []common.Address{}, + Message: []byte{1, 2, 3, 4}, + } + + // This message will also have the same receipts as the previous message + receipt, _ := SendCrossChainMessageAndWaitForAcceptance( + ctx, teleporterInfo.TeleporterMessenger(source), source, destination, sendCrossChainMessageInput, fundedKey) + + // Relay message + teleporterInfo.RelayTeleporterMessage(ctx, receipt, source, destination, true, fundedKey) + + outstandReceiptCount = GetOutstandingReceiptCount( + teleporterInfo.TeleporterMessenger(source), + destination.BlockchainID, + ) + } + log.Info("Receipt queue emptied") +} + +func GetOutstandingReceiptCount( + teleporterMessenger *teleportermessenger.TeleporterMessenger, + destinationBlockchainID ids.ID, +) *big.Int { + size, err := teleporterMessenger.GetReceiptQueueSize(&bind.CallOpts{}, destinationBlockchainID) + Expect(err).Should(BeNil()) + return size +} + +func SendExampleCrossChainMessageAndVerify( + ctx context.Context, + teleporterInfo TeleporterTestInfo, + source interfaces.SubnetTestInfo, + sourceExampleMessenger *testmessenger.TestMessenger, + destination interfaces.SubnetTestInfo, + destExampleMessengerAddress common.Address, + destExampleMessenger *testmessenger.TestMessenger, + senderKey *ecdsa.PrivateKey, + message string, + expectSuccess bool, +) { + // Call the example messenger contract on Subnet A + optsA, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := sourceExampleMessenger.SendMessage( + optsA, + destination.BlockchainID, + destExampleMessengerAddress, + common.BigToAddress(common.Big0), + big.NewInt(0), + testmessenger.SendMessageRequiredGas, + message, + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) + + event, err := GetEventFromLogs(receipt.Logs, teleporterInfo.TeleporterMessenger(source).ParseSendCrossChainMessage) + Expect(err).Should(BeNil()) + Expect(event.DestinationBlockchainID[:]).Should(Equal(destination.BlockchainID[:])) + + teleporterMessageID := event.MessageID + + // + // Relay the message to the destination + // + receipt = teleporterInfo.RelayTeleporterMessage(ctx, receipt, source, destination, true, senderKey) + + // + // Check Teleporter message received on the destination + // + delivered, err := teleporterInfo.TeleporterMessenger(destination).MessageReceived( + &bind.CallOpts{}, teleporterMessageID, + ) + Expect(err).Should(BeNil()) + Expect(delivered).Should(BeTrue()) + + if expectSuccess { + // Check that message execution was successful + messageExecutedEvent, err := GetEventFromLogs( + receipt.Logs, + teleporterInfo.TeleporterMessenger(destination).ParseMessageExecuted, + ) + Expect(err).Should(BeNil()) + Expect(messageExecutedEvent.MessageID[:]).Should(Equal(teleporterMessageID[:])) + } else { + // Check that message execution failed + messageExecutionFailedEvent, err := GetEventFromLogs( + receipt.Logs, + teleporterInfo.TeleporterMessenger(destination).ParseMessageExecutionFailed, + ) + Expect(err).Should(BeNil()) + Expect(messageExecutionFailedEvent.MessageID[:]).Should(Equal(teleporterMessageID[:])) + } + + // + // Verify we received the expected string + // + _, currMessage, err := destExampleMessenger.GetCurrentMessage(&bind.CallOpts{}, source.BlockchainID) + Expect(err).Should(BeNil()) + if expectSuccess { + Expect(currMessage).Should(Equal(message)) + } else { + Expect(currMessage).ShouldNot(Equal(message)) + } +} + +// +// Transaction utils +// + +// Constructs a transaction to call sendCrossChainMessage +// Returns the signed transaction. +func CreateSendCrossChainMessageTransaction( + ctx context.Context, + source interfaces.SubnetTestInfo, + input teleportermessenger.TeleporterMessageInput, + senderKey *ecdsa.PrivateKey, + teleporterContractAddress common.Address, +) *types.Transaction { + data, err := teleportermessenger.PackSendCrossChainMessage(input) + Expect(err).Should(BeNil()) + + gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, source, PrivateKeyToAddress(senderKey)) + + // Send a transaction to the Teleporter contract + tx := types.NewTx(&types.DynamicFeeTx{ + ChainID: source.EVMChainID, + Nonce: nonce, + To: &teleporterContractAddress, + Gas: DefaultTeleporterTransactionGas, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Value: DefaultTeleporterTransactionValue, + Data: data, + }) + + return SignTransaction(tx, senderKey, source.EVMChainID) +} + +// Constructs a transaction to call receiveCrossChainMessage +// Returns the signed transaction. +func CreateReceiveCrossChainMessageTransaction( + ctx context.Context, + signedMessage *avalancheWarp.Message, + requiredGasLimit *big.Int, + teleporterContractAddress common.Address, + senderKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, +) *types.Transaction { + // Construct the transaction to send the Warp message to the destination chain + log.Info("Constructing receiveCrossChainMessage transaction for the destination chain") + numSigners, err := signedMessage.Signature.NumSigners() + Expect(err).Should(BeNil()) + + teleporterMessage := ParseTeleporterMessage(signedMessage.UnsignedMessage) + gasLimit, err := gasUtils.CalculateReceiveMessageGasLimit( + numSigners, + requiredGasLimit, + len(signedMessage.Bytes()), + len(signedMessage.Payload), + len(teleporterMessage.Receipts), + ) + Expect(err).Should(BeNil()) + + callData, err := teleportermessenger.PackReceiveCrossChainMessage(0, PrivateKeyToAddress(senderKey)) + Expect(err).Should(BeNil()) + + gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, PrivateKeyToAddress(senderKey)) + + destinationTx := predicateutils.NewPredicateTx( + subnetInfo.EVMChainID, + nonce, + &teleporterContractAddress, + gasLimit, + gasFeeCap, + gasTipCap, + big.NewInt(0), + callData, + types.AccessList{}, + warp.ContractAddress, + signedMessage.Bytes(), + ) + + return SignTransaction(destinationTx, senderKey, subnetInfo.EVMChainID) +} + +// Constructs a transaction to call addProtocolVersion +// Returns the signed transaction. +func CreateAddProtocolVersionTransaction( + ctx context.Context, + signedMessage *avalancheWarp.Message, + teleporterRegistryAddress common.Address, + senderKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, +) *types.Transaction { + // Construct the transaction to send the Warp message to the destination chain + log.Info("Constructing addProtocolVersion transaction for the destination chain") + + callData, err := teleporterregistry.PackAddProtocolVersion(0) + Expect(err).Should(BeNil()) + + gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, PrivateKeyToAddress(senderKey)) + + destinationTx := predicateutils.NewPredicateTx( + subnetInfo.EVMChainID, + nonce, + &teleporterRegistryAddress, + 500_000, + gasFeeCap, + gasTipCap, + big.NewInt(0), + callData, + types.AccessList{}, + warp.ContractAddress, + signedMessage.Bytes(), + ) + + return SignTransaction(destinationTx, senderKey, subnetInfo.EVMChainID) +} + +func CreateExecuteCallPredicateTransaction( + ctx context.Context, + signedMessage *avalancheWarp.Message, + validatorSetSigAddress common.Address, + senderKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, +) *types.Transaction { + log.Info("Constructing executeCall transaction for the destination chain") + + callData, err := validatorsetsig.PackExecuteCall(0) + Expect(err).Should(BeNil()) + + gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, PrivateKeyToAddress(senderKey)) + + destinationTx := predicateutils.NewPredicateTx( + subnetInfo.EVMChainID, + nonce, + &validatorSetSigAddress, + 500_000, + gasFeeCap, + gasTipCap, + big.NewInt(0), + callData, + types.AccessList{}, + warp.ContractAddress, + signedMessage.Bytes(), + ) + return SignTransaction(destinationTx, senderKey, subnetInfo.EVMChainID) +} + +// +// Off-chain message utils +// + +// Creates an Warp message that registers a Teleporter protocol version with TeleporterRegistry. +// Returns the Warp message, as well as the chain config adding the message to the list of approved +// off-chain Warp messages +func InitOffChainMessageChainConfig( + networkID uint32, + subnet interfaces.SubnetTestInfo, + registryAddress common.Address, + teleporterAddress common.Address, + version uint64, +) (*avalancheWarp.UnsignedMessage, string) { + unsignedMessage := CreateOffChainRegistryMessage( + networkID, + subnet, + registryAddress, + teleporterregistry.ProtocolRegistryEntry{ + Version: big.NewInt(int64(version)), + ProtocolAddress: teleporterAddress, + }, + ) + log.Info("Adding off-chain message to Warp chain config", + "messageID", unsignedMessage.ID(), + "blockchainID", subnet.BlockchainID.String(), + ) + + return unsignedMessage, GetChainConfigWithOffChainMessages([]avalancheWarp.UnsignedMessage{*unsignedMessage}) +} + +// Creates an off-chain Warp message that registers a Teleporter protocol version with TeleporterRegistry +func CreateOffChainRegistryMessage( + networkID uint32, + subnet interfaces.SubnetTestInfo, + registryAddress common.Address, + entry teleporterregistry.ProtocolRegistryEntry, +) *avalancheWarp.UnsignedMessage { + sourceAddress := []byte{} + payloadBytes, err := teleporterregistry.PackTeleporterRegistryWarpPayload(entry, registryAddress) + Expect(err).Should(BeNil()) + + addressedPayload, err := payload.NewAddressedCall(sourceAddress, payloadBytes) + Expect(err).Should(BeNil()) + + unsignedMessage, err := avalancheWarp.NewUnsignedMessage( + networkID, + subnet.BlockchainID, + addressedPayload.Bytes(), + ) + Expect(err).Should(BeNil()) + + return unsignedMessage +} diff --git a/tests/utils/utils.go b/tests/utils/utils.go deleted file mode 100644 index a5ec2198a..000000000 --- a/tests/utils/utils.go +++ /dev/null @@ -1,1249 +0,0 @@ -// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package utils - -import ( - "bytes" - "context" - "crypto/ecdsa" - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - "strconv" - "strings" - "time" - - validatorsetsig "github.com/ava-labs/teleporter/abi-bindings/go/governance/ValidatorSetSig" - exampleerc20 "github.com/ava-labs/teleporter/abi-bindings/go/mocks/ExampleERC20" - teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/TeleporterMessenger" - teleporterregistry "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/registry/TeleporterRegistry" - testmessenger "github.com/ava-labs/teleporter/abi-bindings/go/teleporter/tests/TestMessenger" - deploymentUtils "github.com/ava-labs/teleporter/utils/deployment-utils" - gasUtils "github.com/ava-labs/teleporter/utils/gas-utils" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/eth/tracers" - "github.com/ava-labs/subnet-evm/ethclient" - subnetEvmInterfaces "github.com/ava-labs/subnet-evm/interfaces" - "github.com/ava-labs/subnet-evm/precompile/contracts/warp" - predicateutils "github.com/ava-labs/subnet-evm/predicate" - "github.com/ava-labs/teleporter/tests/interfaces" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - . "github.com/onsi/gomega" -) - -var ( - NativeTransferGas uint64 = 21_000 - DefaultTeleporterTransactionGas uint64 = 300_000 - DefaultTeleporterTransactionValue = common.Big0 - ExpectedExampleERC20DeployerBalance = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e10)) -) - -const ( - CChainPathSpecifier = "C" -) - -// -// Test utility functions -// - -func SendAddFeeAmountAndWaitForAcceptance( - ctx context.Context, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - messageID ids.ID, - amount *big.Int, - feeContractAddress common.Address, - senderKey *ecdsa.PrivateKey, - transactor *teleportermessenger.TeleporterMessenger, -) *types.Receipt { - opts, err := bind.NewKeyedTransactorWithChainID( - senderKey, - source.EVMChainID, - ) - Expect(err).Should(BeNil()) - - tx, err := transactor.AddFeeAmount(opts, messageID, feeContractAddress, amount) - Expect(err).Should(BeNil()) - - receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) - - addFeeAmountEvent, err := GetEventFromLogs(receipt.Logs, transactor.ParseAddFeeAmount) - Expect(err).Should(BeNil()) - Expect(addFeeAmountEvent.MessageID[:]).Should(Equal(messageID[:])) - - log.Info("Send AddFeeAmount transaction on source chain", - "messageID", messageID, - "sourceChainID", source.BlockchainID, - "destinationBlockchainID", destination.BlockchainID, - ) - - return receipt -} - -func RetryMessageExecutionAndWaitForAcceptance( - ctx context.Context, - sourceBlockchainID ids.ID, - subnet interfaces.SubnetTestInfo, - message teleportermessenger.TeleporterMessage, - senderKey *ecdsa.PrivateKey, -) *types.Receipt { - opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) - Expect(err).Should(BeNil()) - - tx, err := subnet.TeleporterMessenger.RetryMessageExecution(opts, sourceBlockchainID, message) - Expect(err).Should(BeNil()) - - return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) -} - -func RedeemRelayerRewardsAndConfirm( - ctx context.Context, - subnet interfaces.SubnetTestInfo, - feeToken *exampleerc20.ExampleERC20, - feeTokenAddress common.Address, - redeemerKey *ecdsa.PrivateKey, - expectedAmount *big.Int, -) *types.Receipt { - redeemerAddress := crypto.PubkeyToAddress(redeemerKey.PublicKey) - - // Check the ERC20 balance before redemption - balanceBeforeRedemption, err := feeToken.BalanceOf( - &bind.CallOpts{}, redeemerAddress, - ) - Expect(err).Should(BeNil()) - - // Redeem the rewards - txOpts, err := bind.NewKeyedTransactorWithChainID( - redeemerKey, subnet.EVMChainID, - ) - Expect(err).Should(BeNil()) - tx, err := subnet.TeleporterMessenger.RedeemRelayerRewards( - txOpts, feeTokenAddress, - ) - Expect(err).Should(BeNil()) - receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) - - // Check that the ERC20 balance was incremented - balanceAfterRedemption, err := feeToken.BalanceOf( - &bind.CallOpts{}, redeemerAddress, - ) - Expect(err).Should(BeNil()) - Expect(balanceAfterRedemption).Should( - Equal( - big.NewInt(0).Add( - balanceBeforeRedemption, expectedAmount, - ), - ), - ) - - // Check that the redeemable rewards amount is now zero. - updatedRewardAmount, err := subnet.TeleporterMessenger.CheckRelayerRewardAmount( - &bind.CallOpts{}, - redeemerAddress, - feeTokenAddress, - ) - Expect(err).Should(BeNil()) - Expect(updatedRewardAmount.Cmp(big.NewInt(0))).Should(Equal(0)) - - return receipt -} - -func SendSpecifiedReceiptsAndWaitForAcceptance( - ctx context.Context, - source interfaces.SubnetTestInfo, - destinationBlockchainID ids.ID, - messageIDs [][32]byte, - feeInfo teleportermessenger.TeleporterFeeInfo, - allowedRelayerAddresses []common.Address, - senderKey *ecdsa.PrivateKey, -) (*types.Receipt, ids.ID) { - opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) - Expect(err).Should(BeNil()) - - tx, err := source.TeleporterMessenger.SendSpecifiedReceipts( - opts, destinationBlockchainID, messageIDs, feeInfo, allowedRelayerAddresses) - Expect(err).Should(BeNil()) - - receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) - - // Check the transaction logs for the SendCrossChainMessage event emitted by the Teleporter contract - event, err := GetEventFromLogs(receipt.Logs, source.TeleporterMessenger.ParseSendCrossChainMessage) - Expect(err).Should(BeNil()) - Expect(event.DestinationBlockchainID[:]).Should(Equal(destinationBlockchainID[:])) - - log.Info("Sending SendSpecifiedReceipts transaction", - "destinationBlockchainID", destinationBlockchainID, - "txHash", tx.Hash()) - - return receipt, event.MessageID -} - -func HttpToWebsocketURI(uri string, blockchainID string) string { - return fmt.Sprintf("ws://%s/ext/bc/%s/ws", strings.TrimPrefix(uri, "http://"), blockchainID) -} - -func HttpToRPCURI(uri string, blockchainID string) string { - return fmt.Sprintf("http://%s/ext/bc/%s/rpc", strings.TrimPrefix(uri, "http://"), blockchainID) -} - -// Get the host and port from a URI. The URI should be in the format http://host:port or https://host:port -func GetURIHostAndPort(uri string) (string, uint32, error) { - // At a minimum uri should have http:// of 7 characters - Expect(len(uri)).Should(BeNumerically(">", 7)) - if uri[:7] == "http://" { - uri = uri[7:] - } else if uri[:8] == "https://" { - uri = uri[8:] - } else { - return "", 0, fmt.Errorf("invalid uri: %s", uri) - } - - // Split the uri into host and port - hostAndPort := strings.Split(uri, ":") - Expect(len(hostAndPort)).Should(Equal(2)) - - // Parse the port - port, err := strconv.ParseUint(hostAndPort[1], 10, 32) - if err != nil { - return "", 0, fmt.Errorf("failed to parse port: %w", err) - } - - return hostAndPort[0], uint32(port), nil -} - -// -// Transaction creation functions -// - -// Constructs a transaction to call sendCrossChainMessage -// Returns the signed transaction. -func CreateSendCrossChainMessageTransaction( - ctx context.Context, - source interfaces.SubnetTestInfo, - input teleportermessenger.TeleporterMessageInput, - senderKey *ecdsa.PrivateKey, - teleporterContractAddress common.Address, -) *types.Transaction { - data, err := teleportermessenger.PackSendCrossChainMessage(input) - Expect(err).Should(BeNil()) - - gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, source, PrivateKeyToAddress(senderKey)) - - // Send a transaction to the Teleporter contract - tx := types.NewTx(&types.DynamicFeeTx{ - ChainID: source.EVMChainID, - Nonce: nonce, - To: &teleporterContractAddress, - Gas: DefaultTeleporterTransactionGas, - GasFeeCap: gasFeeCap, - GasTipCap: gasTipCap, - Value: DefaultTeleporterTransactionValue, - Data: data, - }) - - return SignTransaction(tx, senderKey, source.EVMChainID) -} - -// Constructs a transaction to call receiveCrossChainMessage -// Returns the signed transaction. -func CreateReceiveCrossChainMessageTransaction( - ctx context.Context, - signedMessage *avalancheWarp.Message, - requiredGasLimit *big.Int, - teleporterContractAddress common.Address, - senderKey *ecdsa.PrivateKey, - subnetInfo interfaces.SubnetTestInfo, -) *types.Transaction { - // Construct the transaction to send the Warp message to the destination chain - log.Info("Constructing receiveCrossChainMessage transaction for the destination chain") - numSigners, err := signedMessage.Signature.NumSigners() - Expect(err).Should(BeNil()) - - teleporterMessage := ParseTeleporterMessage(signedMessage.UnsignedMessage) - gasLimit, err := gasUtils.CalculateReceiveMessageGasLimit( - numSigners, - requiredGasLimit, - len(signedMessage.Bytes()), - len(signedMessage.Payload), - len(teleporterMessage.Receipts), - ) - Expect(err).Should(BeNil()) - - callData, err := teleportermessenger.PackReceiveCrossChainMessage(0, PrivateKeyToAddress(senderKey)) - Expect(err).Should(BeNil()) - - gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, PrivateKeyToAddress(senderKey)) - - destinationTx := predicateutils.NewPredicateTx( - subnetInfo.EVMChainID, - nonce, - &teleporterContractAddress, - gasLimit, - gasFeeCap, - gasTipCap, - big.NewInt(0), - callData, - types.AccessList{}, - warp.ContractAddress, - signedMessage.Bytes(), - ) - - return SignTransaction(destinationTx, senderKey, subnetInfo.EVMChainID) -} - -// Constructs a transaction to call addProtocolVersion -// Returns the signed transaction. -func CreateAddProtocolVersionTransaction( - ctx context.Context, - signedMessage *avalancheWarp.Message, - teleporterRegistryAddress common.Address, - senderKey *ecdsa.PrivateKey, - subnetInfo interfaces.SubnetTestInfo, -) *types.Transaction { - // Construct the transaction to send the Warp message to the destination chain - log.Info("Constructing addProtocolVersion transaction for the destination chain") - - callData, err := teleporterregistry.PackAddProtocolVersion(0) - Expect(err).Should(BeNil()) - - gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, PrivateKeyToAddress(senderKey)) - - destinationTx := predicateutils.NewPredicateTx( - subnetInfo.EVMChainID, - nonce, - &teleporterRegistryAddress, - 500_000, - gasFeeCap, - gasTipCap, - big.NewInt(0), - callData, - types.AccessList{}, - warp.ContractAddress, - signedMessage.Bytes(), - ) - - return SignTransaction(destinationTx, senderKey, subnetInfo.EVMChainID) -} - -func CreateExecuteCallPredicateTransaction( - ctx context.Context, - signedMessage *avalancheWarp.Message, - validatorSetSigAddress common.Address, - senderKey *ecdsa.PrivateKey, - subnetInfo interfaces.SubnetTestInfo, -) *types.Transaction { - log.Info("Constructing executeCall transaction for the destination chain") - - callData, err := validatorsetsig.PackExecuteCall(0) - Expect(err).Should(BeNil()) - - gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, PrivateKeyToAddress(senderKey)) - - destinationTx := predicateutils.NewPredicateTx( - subnetInfo.EVMChainID, - nonce, - &validatorSetSigAddress, - 500_000, - gasFeeCap, - gasTipCap, - big.NewInt(0), - callData, - types.AccessList{}, - warp.ContractAddress, - signedMessage.Bytes(), - ) - return SignTransaction(destinationTx, senderKey, subnetInfo.EVMChainID) -} - -func AddProtocolVersionAndWaitForAcceptance( - ctx context.Context, - network interfaces.Network, - subnet interfaces.SubnetTestInfo, - newTeleporterAddress common.Address, - senderKey *ecdsa.PrivateKey, - unsignedMessage *avalancheWarp.UnsignedMessage, -) { - signedWarpMsg := network.GetSignedMessage(ctx, subnet, subnet, unsignedMessage.ID()) - log.Info("Got signed warp message", "messageID", signedWarpMsg.ID()) - - // Construct tx to add protocol version and send to destination chain - signedTx := CreateAddProtocolVersionTransaction( - ctx, - signedWarpMsg, - subnet.TeleporterRegistryAddress, - senderKey, - subnet, - ) - - curLatestVersion, err := subnet.TeleporterRegistry.LatestVersion(&bind.CallOpts{}) - Expect(err).Should(BeNil()) - expectedLatestVersion := big.NewInt(curLatestVersion.Int64() + 1) - - // Wait for tx to be accepted, and verify events emitted - receipt := SendTransactionAndWaitForSuccess(ctx, subnet, signedTx) - addProtocolVersionEvent, err := GetEventFromLogs(receipt.Logs, subnet.TeleporterRegistry.ParseAddProtocolVersion) - Expect(err).Should(BeNil()) - Expect(addProtocolVersionEvent.Version.Cmp(expectedLatestVersion)).Should(Equal(0)) - Expect(addProtocolVersionEvent.ProtocolAddress).Should(Equal(newTeleporterAddress)) - - versionUpdatedEvent, err := GetEventFromLogs(receipt.Logs, subnet.TeleporterRegistry.ParseLatestVersionUpdated) - Expect(err).Should(BeNil()) - Expect(versionUpdatedEvent.OldVersion.Cmp(curLatestVersion)).Should(Equal(0)) - Expect(versionUpdatedEvent.NewVersion.Cmp(expectedLatestVersion)).Should(Equal(0)) -} - -// Returns Receipt for the transaction unlike TeleporterRegistry version since this is a non-teleporter case -// and we don't want to add the ValidatorSetSig ABI to the subnetInfo -func ExecuteValidatorSetSigCallAndVerify( - ctx context.Context, - network interfaces.Network, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - validatorSetSigAddress common.Address, - senderKey *ecdsa.PrivateKey, - unsignedMessage *avalancheWarp.UnsignedMessage, - expectSuccess bool, -) *types.Receipt { - signedWarpMsg := network.GetSignedMessage(ctx, source, destination, unsignedMessage.ID()) - log.Info("Got signed warp message", "messageID", signedWarpMsg.ID()) - - signedPredicateTx := CreateExecuteCallPredicateTransaction( - ctx, - signedWarpMsg, - validatorSetSigAddress, - senderKey, - destination, - ) - - // Wait for tx to be accepted and verify events emitted - if expectSuccess { - return SendTransactionAndWaitForSuccess(ctx, destination, signedPredicateTx) - } - return SendTransactionAndWaitForFailure(ctx, destination, signedPredicateTx) -} - -func CreateNativeTransferTransaction( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - fromKey *ecdsa.PrivateKey, - recipient common.Address, - amount *big.Int, -) *types.Transaction { - fromAddress := crypto.PubkeyToAddress(fromKey.PublicKey) - gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnetInfo, fromAddress) - - tx := types.NewTx(&types.DynamicFeeTx{ - ChainID: subnetInfo.EVMChainID, - Nonce: nonce, - To: &recipient, - Gas: NativeTransferGas, - GasFeeCap: gasFeeCap, - GasTipCap: gasTipCap, - Value: amount, - }) - - return SignTransaction(tx, fromKey, subnetInfo.EVMChainID) -} - -func SendNativeTransfer( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - fromKey *ecdsa.PrivateKey, - recipient common.Address, - amount *big.Int, -) *types.Receipt { - tx := CreateNativeTransferTransaction(ctx, subnetInfo, fromKey, recipient, amount) - return SendTransactionAndWaitForSuccess(ctx, subnetInfo, tx) -} - -// Sends a tx, and waits for it to be mined. -// Asserts Receipt.status equals success. -func sendAndWaitForTransaction( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - tx *types.Transaction, - success bool, -) *types.Receipt { - err := subnetInfo.RPCClient.SendTransaction(ctx, tx) - Expect(err).Should(BeNil()) - - return waitForTransaction(ctx, subnetInfo, tx.Hash(), success) -} - -// Sends a tx, and waits for it to be mined. -// Asserts Receipt.status equals false. -func SendTransactionAndWaitForFailure( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - tx *types.Transaction, -) *types.Receipt { - return sendAndWaitForTransaction(ctx, subnetInfo, tx, false) -} - -// Sends a tx, and waits for it to be mined. -// Asserts Receipt.status equals true. -func SendTransactionAndWaitForSuccess( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - tx *types.Transaction, -) *types.Receipt { - return sendAndWaitForTransaction(ctx, subnetInfo, tx, true) -} - -func SendCrossChainMessageAndWaitForAcceptance( - ctx context.Context, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, - input teleportermessenger.TeleporterMessageInput, - senderKey *ecdsa.PrivateKey, -) (*types.Receipt, ids.ID) { - opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) - Expect(err).Should(BeNil()) - - // Send a transaction to the Teleporter contract - tx, err := source.TeleporterMessenger.SendCrossChainMessage(opts, input) - Expect(err).Should(BeNil()) - - // Wait for the transaction to be accepted - receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) - - // Check the transaction logs for the SendCrossChainMessage event emitted by the Teleporter contract - event, err := GetEventFromLogs(receipt.Logs, source.TeleporterMessenger.ParseSendCrossChainMessage) - Expect(err).Should(BeNil()) - - log.Info("Sending SendCrossChainMessage transaction on source chain", - "sourceChainID", source.BlockchainID, - "destinationBlockchainID", destination.BlockchainID, - "txHash", tx.Hash()) - - return receipt, event.MessageID -} - -// Waits for a transaction to be mined. -// Asserts Receipt.status equals true. -func WaitForTransactionSuccess( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - txHash common.Hash, -) *types.Receipt { - return waitForTransaction(ctx, subnetInfo, txHash, true) -} - -// Waits for a transaction to be mined. -// Asserts Receipt.status equals false. -func WaitForTransactionFailure( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - txHash common.Hash, -) *types.Receipt { - return waitForTransaction(ctx, subnetInfo, txHash, false) -} - -// Waits for a transaction to be mined. -// Asserts Receipt.status equals success. -func waitForTransaction( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - txHash common.Hash, - success bool, -) *types.Receipt { - cctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - - receipt, err := WaitMined(cctx, subnetInfo.RPCClient, txHash) - Expect(err).Should(BeNil()) - - if success { - if receipt.Status == types.ReceiptStatusFailed { - TraceTransactionAndExit(ctx, subnetInfo.RPCClient, receipt.TxHash) - } - } else { - Expect(receipt.Status).Should(Equal(types.ReceiptStatusFailed)) - } - return receipt -} - -// Polls for a transaction receipt of the given txHash on each queryTicker tick until -// either a transaction receipt returned, or the context is cancelled or expired. -func waitForTransactionReceipt( - cctx context.Context, - rpcClient ethclient.Client, - txHash common.Hash, -) (*types.Receipt, error) { - queryTicker := time.NewTicker(200 * time.Millisecond) - defer queryTicker.Stop() - for { - receipt, err := rpcClient.TransactionReceipt(cctx, txHash) - if err == nil { - return receipt, nil - } - - if errors.Is(err, subnetEvmInterfaces.NotFound) { - log.Debug("Transaction not yet mined") - } else { - log.Error("Receipt retrieval failed", "err", err) - return nil, err - } - - // Wait for the next round. - select { - case <-cctx.Done(): - return nil, cctx.Err() - case <-queryTicker.C: - } - } -} - -// Polls for the eth_blockNumber endpoint for the latest blockheight on each queryTicker tick until -// either the returned height is greater than or equal to the expectedBlockNumber, or the context -// is cancelled or expired. -func waitForBlockHeight( - cctx context.Context, - rpcClient ethclient.Client, - expectedBlockNumber uint64, -) error { - queryTicker := time.NewTicker(2 * time.Second) - defer queryTicker.Stop() - for { - currentBlockNumber, err := rpcClient.BlockNumber(cctx) - if err != nil { - return err - } - - if currentBlockNumber >= expectedBlockNumber { - return nil - } else { - log.Info("Waiting for block height where transaction was included", - "blockNumber", expectedBlockNumber) - } - - // Wait for the next round. - select { - case <-cctx.Done(): - return cctx.Err() - case <-queryTicker.C: - } - } -} - -// WaitMined waits for tx to be mined on the blockchain. -// It stops waiting when the context is canceled. -// Takes a tx hash instead of the full tx in the subnet-evm version of this function. -// Copied and modified from https://github.com/ava-labs/subnet-evm/blob/v0.6.0-fuji/accounts/abi/bind/util.go#L42 -func WaitMined(ctx context.Context, rpcClient ethclient.Client, txHash common.Hash) (*types.Receipt, error) { - cctx, cancel := context.WithTimeout(ctx, 20*time.Second) - defer cancel() - - receipt, err := waitForTransactionReceipt(cctx, rpcClient, txHash) - if err != nil { - return nil, err - } - - // Check that the block height endpoint returns a block height as high as the block number that the transaction was - // included in. This is to workaround the issue where multiple nodes behind a public RPC endpoint see - // transactions/blocks at different points in time. Ideally, all nodes in the network should have seen this block - // and transaction before returning from WaitMined. The block height endpoint of public RPC endpoints is - // configured to return the lowest value currently returned by any node behind the load balancer, so waiting for - // it to be at least as high as the block height specified in the receipt should provide a relatively strong - // indication that the transaction has been seen widely throughout the network. - err = waitForBlockHeight(cctx, rpcClient, receipt.BlockNumber.Uint64()) - if err != nil { - return nil, err - } - - return receipt, nil -} - -// Returns the first log in 'logs' that is successfully parsed by 'parser' -// Errors and prints a trace of the transaction if no log is found. -func GetEventFromLogsOrTrace[T any]( - ctx context.Context, - receipt *types.Receipt, - subnetInfo interfaces.SubnetTestInfo, - parser func(log types.Log) (T, error), -) T { - log, err := GetEventFromLogs(receipt.Logs, parser) - if err != nil { - TraceTransactionAndExit(ctx, subnetInfo.RPCClient, receipt.TxHash) - } - return log -} - -// Returns the first log in 'logs' that is successfully parsed by 'parser' -func GetEventFromLogs[T any](logs []*types.Log, parser func(log types.Log) (T, error)) (T, error) { - for _, log := range logs { - event, err := parser(*log) - if err == nil { - return event, nil - } - } - return *new(T), fmt.Errorf("failed to find %T event in receipt logs", *new(T)) -} - -// Returns true if the transaction receipt contains a ReceiptReceived log with the specified messageID -func CheckReceiptReceived( - receipt *types.Receipt, - messageID [32]byte, - transactor *teleportermessenger.TeleporterMessenger, -) bool { - for _, log := range receipt.Logs { - event, err := transactor.ParseReceiptReceived(*log) - if err == nil && bytes.Equal(event.MessageID[:], messageID[:]) { - return true - } - } - return false -} - -func ClearReceiptQueue( - ctx context.Context, - network interfaces.Network, - fundedKey *ecdsa.PrivateKey, - source interfaces.SubnetTestInfo, - destination interfaces.SubnetTestInfo, -) { - Expect(network.IsExternalNetwork()).Should(BeFalse()) - outstandReceiptCount := GetOutstandingReceiptCount(source, destination.BlockchainID) - for outstandReceiptCount.Cmp(big.NewInt(0)) != 0 { - log.Info("Emptying receipt queue", "remainingReceipts", outstandReceiptCount.String()) - // Send message from Subnet B to Subnet A to trigger the "regular" method of delivering receipts. - // The next message from B->A will contain the same receipts that were manually sent in the above steps, - // but they should not be processed again on Subnet A. - sendCrossChainMessageInput := teleportermessenger.TeleporterMessageInput{ - DestinationBlockchainID: destination.BlockchainID, - DestinationAddress: common.HexToAddress("0x1111111111111111111111111111111111111111"), - RequiredGasLimit: big.NewInt(1), - FeeInfo: teleportermessenger.TeleporterFeeInfo{ - FeeTokenAddress: common.Address{}, - Amount: big.NewInt(0), - }, - AllowedRelayerAddresses: []common.Address{}, - Message: []byte{1, 2, 3, 4}, - } - - // This message will also have the same receipts as the previous message - receipt, _ := SendCrossChainMessageAndWaitForAcceptance( - ctx, source, destination, sendCrossChainMessageInput, fundedKey) - - // Relay message - network.RelayMessage(ctx, receipt, source, destination, true) - - outstandReceiptCount = GetOutstandingReceiptCount(source, destination.BlockchainID) - } - log.Info("Receipt queue emptied") -} - -func GetOutstandingReceiptCount(source interfaces.SubnetTestInfo, destinationBlockchainID ids.ID) *big.Int { - size, err := source.TeleporterMessenger.GetReceiptQueueSize(&bind.CallOpts{}, destinationBlockchainID) - Expect(err).Should(BeNil()) - return size -} - -// Signs a transaction using the provided key for the specified chainID -func SignTransaction(tx *types.Transaction, key *ecdsa.PrivateKey, chainID *big.Int) *types.Transaction { - txSigner := types.LatestSignerForChainID(chainID) - signedTx, err := types.SignTx(tx, txSigner, key) - Expect(err).Should(BeNil()) - - return signedTx -} - -// Returns the gasFeeCap, gasTipCap, and nonce the be used when constructing a transaction from fundedAddress -func CalculateTxParams( - ctx context.Context, - subnetInfo interfaces.SubnetTestInfo, - fundedAddress common.Address, -) (*big.Int, *big.Int, uint64) { - baseFee, err := subnetInfo.RPCClient.EstimateBaseFee(ctx) - Expect(err).Should(BeNil()) - - gasTipCap, err := subnetInfo.RPCClient.SuggestGasTipCap(ctx) - Expect(err).Should(BeNil()) - - nonce, err := subnetInfo.RPCClient.NonceAt(ctx, fundedAddress, nil) - Expect(err).Should(BeNil()) - - gasFeeCap := baseFee.Mul(baseFee, big.NewInt(gasUtils.BaseFeeFactor)) - gasFeeCap.Add(gasFeeCap, big.NewInt(gasUtils.MaxPriorityFeePerGas)) - - return gasFeeCap, gasTipCap, nonce -} - -func PrivateKeyToAddress(k *ecdsa.PrivateKey) common.Address { - return crypto.PubkeyToAddress(k.PublicKey) -} - -// Throws a Gomega error if there is a mismatch -func CheckBalance(ctx context.Context, addr common.Address, expectedBalance *big.Int, rpcClient ethclient.Client) { - bal, err := rpcClient.BalanceAt(ctx, addr, nil) - Expect(err).Should(BeNil()) - ExpectBigEqual(bal, expectedBalance) -} - -// Gomega will print the transaction trace and exit -func TraceTransactionAndExit(ctx context.Context, rpcClient ethclient.Client, txHash common.Hash) { - Expect(TraceTransaction(ctx, rpcClient, txHash)).Should(Equal("")) -} - -func TraceTransaction(ctx context.Context, rpcClient ethclient.Client, txHash common.Hash) string { - var result interface{} - ct := "callTracer" - err := rpcClient.Client().Call(&result, "debug_traceTransaction", txHash.String(), tracers.TraceConfig{Tracer: &ct}) - Expect(err).Should(BeNil()) - - jsonStr, err := json.Marshal(result) - Expect(err).Should(BeNil()) - - return string(jsonStr) -} - -func ExpectBigEqual(v1 *big.Int, v2 *big.Int) { - // Compare strings, so gomega will print the numbers if they differ - Expect(v1.String()).Should(Equal(v2.String())) -} - -func BigIntSub(v1 *big.Int, v2 *big.Int) *big.Int { - return big.NewInt(0).Sub(v1, v2) -} - -func BigIntMul(v1 *big.Int, v2 *big.Int) *big.Int { - return big.NewInt(0).Mul(v1, v2) -} - -func ERC20Approve( - ctx context.Context, - token *exampleerc20.ExampleERC20, - spender common.Address, - amount *big.Int, - source interfaces.SubnetTestInfo, - senderKey *ecdsa.PrivateKey, -) { - opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) - Expect(err).Should(BeNil()) - tx, err := token.Approve(opts, spender, amount) - Expect(err).Should(BeNil()) - log.Info("Approved ERC20", "spender", spender.Hex(), "txHash", tx.Hash().Hex()) - - WaitForTransactionSuccess(ctx, source, tx.Hash()) -} - -func DeployExampleERC20( - ctx context.Context, - senderKey *ecdsa.PrivateKey, - source interfaces.SubnetTestInfo, -) (common.Address, *exampleerc20.ExampleERC20) { - opts, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) - Expect(err).Should(BeNil()) - - // Deploy Mock ERC20 contract - address, tx, token, err := exampleerc20.DeployExampleERC20(opts, source.RPCClient) - Expect(err).Should(BeNil()) - log.Info("Deployed Mock ERC20 contract", "address", address.Hex(), "txHash", tx.Hash().Hex()) - - // Wait for the transaction to be mined - WaitForTransactionSuccess(ctx, source, tx.Hash()) - - // Check that the deployer has the expected initial balance - senderAddress := crypto.PubkeyToAddress(senderKey.PublicKey) - balance, err := token.BalanceOf(&bind.CallOpts{}, senderAddress) - Expect(err).Should(BeNil()) - Expect(balance).Should(Equal(ExpectedExampleERC20DeployerBalance)) - - return address, token -} - -func DeployTestMessenger( - ctx context.Context, - senderKey *ecdsa.PrivateKey, - teleporterManager common.Address, - subnet interfaces.SubnetTestInfo, -) (common.Address, *testmessenger.TestMessenger) { - opts, err := bind.NewKeyedTransactorWithChainID( - senderKey, - subnet.EVMChainID, - ) - Expect(err).Should(BeNil()) - minTeleporterVersion, err := subnet.TeleporterRegistry.LatestVersion(&bind.CallOpts{}) - Expect(err).Should(BeNil()) - address, tx, exampleMessenger, err := testmessenger.DeployTestMessenger( - opts, - subnet.RPCClient, - subnet.TeleporterRegistryAddress, - teleporterManager, - minTeleporterVersion, - ) - Expect(err).Should(BeNil()) - - // Wait for the transaction to be mined - WaitForTransactionSuccess(ctx, subnet, tx.Hash()) - - return address, exampleMessenger -} - -func DeployValidatorSetSig( - ctx context.Context, - senderKey *ecdsa.PrivateKey, - contractSubnet interfaces.SubnetTestInfo, - validatorSubnet interfaces.SubnetTestInfo, -) (common.Address, *validatorsetsig.ValidatorSetSig) { - opts, err := bind.NewKeyedTransactorWithChainID(senderKey, contractSubnet.EVMChainID) - Expect(err).Should(BeNil()) - address, tx, validatorSetSig, err := validatorsetsig.DeployValidatorSetSig( - opts, - contractSubnet.RPCClient, - validatorSubnet.BlockchainID, - ) - Expect(err).Should(BeNil()) - - // Wait for the transaction to be mined - WaitForTransactionSuccess(ctx, contractSubnet, tx.Hash()) - - return address, validatorSetSig -} - -func GetTwoSubnets(network interfaces.Network) ( - interfaces.SubnetTestInfo, - interfaces.SubnetTestInfo, -) { - subnets := network.GetSubnetsInfo() - Expect(len(subnets)).Should(BeNumerically(">=", 2)) - return subnets[0], subnets[1] -} - -func SendExampleCrossChainMessageAndVerify( - ctx context.Context, - network interfaces.Network, - source interfaces.SubnetTestInfo, - sourceExampleMessenger *testmessenger.TestMessenger, - destination interfaces.SubnetTestInfo, - destExampleMessengerAddress common.Address, - destExampleMessenger *testmessenger.TestMessenger, - senderKey *ecdsa.PrivateKey, - message string, - expectSuccess bool, -) { - // Call the example messenger contract on Subnet A - optsA, err := bind.NewKeyedTransactorWithChainID(senderKey, source.EVMChainID) - Expect(err).Should(BeNil()) - tx, err := sourceExampleMessenger.SendMessage( - optsA, - destination.BlockchainID, - destExampleMessengerAddress, - common.BigToAddress(common.Big0), - big.NewInt(0), - testmessenger.SendMessageRequiredGas, - message, - ) - Expect(err).Should(BeNil()) - - // Wait for the transaction to be mined - receipt := WaitForTransactionSuccess(ctx, source, tx.Hash()) - - event, err := GetEventFromLogs(receipt.Logs, source.TeleporterMessenger.ParseSendCrossChainMessage) - Expect(err).Should(BeNil()) - Expect(event.DestinationBlockchainID[:]).Should(Equal(destination.BlockchainID[:])) - - teleporterMessageID := event.MessageID - - // - // Relay the message to the destination - // - receipt = network.RelayMessage(ctx, receipt, source, destination, true) - - // - // Check Teleporter message received on the destination - // - delivered, err := destination.TeleporterMessenger.MessageReceived( - &bind.CallOpts{}, teleporterMessageID, - ) - Expect(err).Should(BeNil()) - Expect(delivered).Should(BeTrue()) - - if expectSuccess { - // Check that message execution was successful - messageExecutedEvent, err := GetEventFromLogs(receipt.Logs, destination.TeleporterMessenger.ParseMessageExecuted) - Expect(err).Should(BeNil()) - Expect(messageExecutedEvent.MessageID[:]).Should(Equal(teleporterMessageID[:])) - } else { - // Check that message execution failed - messageExecutionFailedEvent, err := GetEventFromLogs( - receipt.Logs, - destination.TeleporterMessenger.ParseMessageExecutionFailed, - ) - Expect(err).Should(BeNil()) - Expect(messageExecutionFailedEvent.MessageID[:]).Should(Equal(teleporterMessageID[:])) - } - - // - // Verify we received the expected string - // - _, currMessage, err := destExampleMessenger.GetCurrentMessage(&bind.CallOpts{}, source.BlockchainID) - Expect(err).Should(BeNil()) - if expectSuccess { - Expect(currMessage).Should(Equal(message)) - } else { - Expect(currMessage).ShouldNot(Equal(message)) - } -} - -// Creates an Warp message that registers a Teleporter protocol version with TeleporterRegistry. -// Returns the Warp message, as well as the chain config adding the message to the list of approved -// off-chain Warp messages -func InitOffChainMessageChainConfig( - networkID uint32, - subnet interfaces.SubnetTestInfo, - teleporterAddress common.Address, - version uint64, -) (*avalancheWarp.UnsignedMessage, string) { - unsignedMessage := CreateOffChainRegistryMessage(networkID, subnet, teleporterregistry.ProtocolRegistryEntry{ - Version: big.NewInt(int64(version)), - ProtocolAddress: teleporterAddress, - }) - log.Info("Adding off-chain message to Warp chain config", - "messageID", unsignedMessage.ID(), - "blockchainID", subnet.BlockchainID.String(), - ) - - return unsignedMessage, GetChainConfigWithOffChainMessages([]avalancheWarp.UnsignedMessage{*unsignedMessage}) -} - -// Creates an off-chain Warp message that registers a Teleporter protocol version with TeleporterRegistry -func CreateOffChainRegistryMessage( - networkID uint32, - subnet interfaces.SubnetTestInfo, - entry teleporterregistry.ProtocolRegistryEntry, -) *avalancheWarp.UnsignedMessage { - sourceAddress := []byte{} - payloadBytes, err := teleporterregistry.PackTeleporterRegistryWarpPayload(entry, subnet.TeleporterRegistryAddress) - Expect(err).Should(BeNil()) - - addressedPayload, err := payload.NewAddressedCall(sourceAddress, payloadBytes) - Expect(err).Should(BeNil()) - - unsignedMessage, err := avalancheWarp.NewUnsignedMessage( - networkID, - subnet.BlockchainID, - addressedPayload.Bytes(), - ) - Expect(err).Should(BeNil()) - - return unsignedMessage -} - -func InitOffChainMessageChainConfigValidatorSetSig( - networkID uint32, - subnet interfaces.SubnetTestInfo, - validatorSetSigAddress common.Address, - validatorSetSigMessages []validatorsetsig.ValidatorSetSigMessage, -) ([]avalancheWarp.UnsignedMessage, string) { - unsignedMessages := []avalancheWarp.UnsignedMessage{} - for _, message := range validatorSetSigMessages { - unsignedMessage := CreateOffChainValidatorSetSigMessage(networkID, subnet, message) - unsignedMessages = append(unsignedMessages, *unsignedMessage) - log.Info("Adding validatorSetSig off-chain message to Warp chain config", - "messageID", unsignedMessage.ID(), - "blockchainID", subnet.BlockchainID.String()) - } - return unsignedMessages, GetChainConfigWithOffChainMessages(unsignedMessages) -} - -// Creates an off-chain Warp message pointing to a function, contract and payload to be executed -// if the validator set signs this message -func CreateOffChainValidatorSetSigMessage( - networkID uint32, - subnet interfaces.SubnetTestInfo, - message validatorsetsig.ValidatorSetSigMessage, -) *avalancheWarp.UnsignedMessage { - sourceAddress := []byte{} - payloadBytes, err := message.Pack() - Expect(err).Should(BeNil()) - - addressedPayload, err := payload.NewAddressedCall(sourceAddress, payloadBytes) - Expect(err).Should(BeNil()) - - unsignedMessage, err := avalancheWarp.NewUnsignedMessage( - networkID, - subnet.BlockchainID, - addressedPayload.Bytes(), - ) - Expect(err).Should(BeNil()) - - return unsignedMessage -} - -// Deploys a new version of Teleporter and returns its address -// Does NOT modify the global Teleporter contract address to provide greater testing flexibility. -func DeployNewTeleporterVersion( - ctx context.Context, - network interfaces.LocalNetwork, - fundedKey *ecdsa.PrivateKey, - teleporterByteCodeFile string, -) common.Address { - contractCreationGasPrice := (&big.Int{}).Add(deploymentUtils.GetDefaultContractCreationGasPrice(), big.NewInt(1)) - teleporterDeployerTransaction, - _, - teleporterDeployerAddress, - teleporterContractAddress, - err := deploymentUtils.ConstructKeylessTransaction( - teleporterByteCodeFile, - false, - contractCreationGasPrice, - ) - Expect(err).Should(BeNil()) - - network.DeployTeleporterContractToAllChains( - teleporterDeployerTransaction, - teleporterDeployerAddress, - teleporterContractAddress, - fundedKey, - ) - return teleporterContractAddress -} - -type ChainConfigMap map[string]string - -// Sets the chain config in customChainConfigs for the specified subnet -func (m ChainConfigMap) Add(subnet interfaces.SubnetTestInfo, chainConfig string) { - if subnet.SubnetID == constants.PrimaryNetworkID { - m[CChainPathSpecifier] = chainConfig - } else { - m[subnet.BlockchainID.String()] = chainConfig - } -} - -func ParseTeleporterMessage(unsignedMessage avalancheWarp.UnsignedMessage) *teleportermessenger.TeleporterMessage { - addressedPayload, err := payload.ParseAddressedCall(unsignedMessage.Payload) - Expect(err).Should(BeNil()) - - teleporterMessage := teleportermessenger.TeleporterMessage{} - err = teleporterMessage.Unpack(addressedPayload.Payload) - Expect(err).Should(BeNil()) - - return &teleporterMessage -} - -func GetChainConfigWithOffChainMessages(offChainMessages []avalancheWarp.UnsignedMessage) string { - // Convert messages to hex - hexOffChainMessages := []string{} - for _, message := range offChainMessages { - hexOffChainMessages = append(hexOffChainMessages, hexutil.Encode(message.Bytes())) - } - - // Create a map to represent the JSON structure - jsonMap := map[string]interface{}{ - "warp-api-enabled": true, - "warp-off-chain-messages": hexOffChainMessages, - "log-level": "debug", - "eth-apis": []string{ - "eth", "eth-filter", "net", "admin", "web3", - "internal-eth", "internal-blockchain", "internal-transaction", - "internal-debug", "internal-account", "internal-personal", - "debug", "debug-tracer", "debug-file-tracer", "debug-handler", - }, - } - - // Marshal the map to JSON - offChainMessageJson, err := json.Marshal(jsonMap) - Expect(err).Should(BeNil()) - - return string(offChainMessageJson) -} - -// read in the template file, make the substitutions declared at the beginning -// of the function, write out the instantiation to a temp file, and then return -// the path to that temp file. -func InstantiateGenesisTemplate( - templateFileName string, - chainID uint64, - teleporterContractAddress common.Address, - teleporterDeployedBytecode string, - teleporterDeployerAddress common.Address, -) string { - substitutions := []struct { - Target string - Value string - }{ - { - "", - strconv.FormatUint(chainID, 10), - }, - { - "", - teleporterContractAddress.Hex(), - }, - { - "", - teleporterDeployedBytecode, - }, - { - "", - teleporterDeployerAddress.Hex(), - }, - } - - templateFileBytes, err := os.ReadFile(templateFileName) - Expect(err).Should(BeNil()) - - subnetGenesisFile, err := os.CreateTemp(os.TempDir(), "") - Expect(err).Should(BeNil()) - - defer subnetGenesisFile.Close() - - var replaced string = string(templateFileBytes[:]) - for _, s := range substitutions { - replaced = strings.ReplaceAll(replaced, s.Target, s.Value) - } - - subnetGenesisFile.WriteString(replaced) - - return subnetGenesisFile.Name() -} - -// -// Teleporter message utils -// - -// Blocks until the given teleporter message is delivered to the specified TeleporterMessenger -// before the timeout, or if an error occurred. -func WaitTeleporterMessageDelivered( - ctx context.Context, - teleporterMessenger *teleportermessenger.TeleporterMessenger, - teleporterMessageID ids.ID, -) error { - cctx, cancel := context.WithTimeout(ctx, 20*time.Second) - defer cancel() - - queryTicker := time.NewTicker(200 * time.Millisecond) - defer queryTicker.Stop() - for { - delivered, err := teleporterMessenger.MessageReceived( - &bind.CallOpts{}, teleporterMessageID, - ) - if err != nil { - return err - } - - if delivered { - return nil - } - - // Wait for the next round. - select { - case <-cctx.Done(): - return cctx.Err() - case <-queryTicker.C: - } - } -} diff --git a/tests/utils/validator_manager.go b/tests/utils/validator_manager.go new file mode 100644 index 000000000..b3626bc14 --- /dev/null +++ b/tests/utils/validator_manager.go @@ -0,0 +1,2266 @@ +package utils + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "encoding/binary" + "fmt" + "log" + "math/big" + "reflect" + "sort" + "time" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/proto/pb/platformvm" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/formatting/address" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/stakeable" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + warpMessage "github.com/ava-labs/avalanchego/vms/platformvm/warp/message" + warpPayload "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/awm-relayer/signature-aggregator/aggregator" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/precompile/contracts/warp" + predicateutils "github.com/ava-labs/subnet-evm/predicate" + subnetEvmUtils "github.com/ava-labs/subnet-evm/tests/utils" + exampleerc20 "github.com/ava-labs/teleporter/abi-bindings/go/mocks/ExampleERC20" + erc20tokenstakingmanager "github.com/ava-labs/teleporter/abi-bindings/go/validator-manager/ERC20TokenStakingManager" + examplerewardcalculator "github.com/ava-labs/teleporter/abi-bindings/go/validator-manager/ExampleRewardCalculator" + nativetokenstakingmanager "github.com/ava-labs/teleporter/abi-bindings/go/validator-manager/NativeTokenStakingManager" + poavalidatormanager "github.com/ava-labs/teleporter/abi-bindings/go/validator-manager/PoAValidatorManager" + "github.com/ava-labs/teleporter/tests/interfaces" + "github.com/ethereum/go-ethereum/common" + "google.golang.org/protobuf/proto" + + . "github.com/onsi/gomega" +) + +const ( + DefaultMinDelegateFeeBips uint16 = 1 + DefaultMinStakeDurationSeconds uint64 = 1 + DefaultMinStakeAmount uint64 = 1e16 + DefaultMaxStakeAmount uint64 = 10e18 + DefaultMaxStakeMultiplier uint8 = 4 + DefaultMaxChurnPercentage uint8 = 20 + DefaultChurnPeriodSeconds uint64 = 1 + DefaultWeightToValueFactor uint64 = 1e12 + DefaultPChainAddress string = "P-local18jma8ppw3nhx5r4ap8clazz0dps7rv5u00z96u" +) + +// +// Deployment utils +// + +func DeployNativeTokenStakingManager( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, +) (common.Address, *nativetokenstakingmanager.NativeTokenStakingManager) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + address, tx, stakingManager, err := nativetokenstakingmanager.DeployNativeTokenStakingManager( + opts, + subnet.RPCClient, + 0, // ICMInitializable.Allowed + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return address, stakingManager +} + +func DeployAndInitializeNativeTokenStakingManager( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, +) (common.Address, *nativetokenstakingmanager.NativeTokenStakingManager) { + stakingManagerContractAddress, stakingManager := DeployNativeTokenStakingManager( + ctx, + senderKey, + subnet, + ) + rewardCalculatorAddress, _ := DeployExampleRewardCalculator( + ctx, + senderKey, + subnet, + uint64(10), + ) + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.Initialize( + opts, + nativetokenstakingmanager.PoSValidatorManagerSettings{ + BaseSettings: nativetokenstakingmanager.ValidatorManagerSettings{ + SubnetID: subnet.SubnetID, + ChurnPeriodSeconds: DefaultChurnPeriodSeconds, + MaximumChurnPercentage: DefaultMaxChurnPercentage, + }, + MinimumStakeAmount: big.NewInt(0).SetUint64(DefaultMinStakeAmount), + MaximumStakeAmount: big.NewInt(0).SetUint64(DefaultMaxStakeAmount), + MinimumStakeDuration: DefaultMinStakeDurationSeconds, + MinimumDelegationFeeBips: DefaultMinDelegateFeeBips, + MaximumStakeMultiplier: DefaultMaxStakeMultiplier, + WeightToValueFactor: big.NewInt(0).SetUint64(DefaultWeightToValueFactor), + RewardCalculator: rewardCalculatorAddress, + }, + ) + Expect(err).Should(BeNil()) + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return stakingManagerContractAddress, stakingManager +} + +func DeployERC20TokenStakingManager( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, +) (common.Address, *erc20tokenstakingmanager.ERC20TokenStakingManager) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + address, tx, stakingManager, err := erc20tokenstakingmanager.DeployERC20TokenStakingManager( + opts, + subnet.RPCClient, + 0, // ICMInitializable.Allowed + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return address, stakingManager +} + +func DeployAndInitializeERC20TokenStakingManager( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, +) ( + common.Address, + *erc20tokenstakingmanager.ERC20TokenStakingManager, + common.Address, + *exampleerc20.ExampleERC20, +) { + stakingManagerContractAddress, stakingManager := DeployERC20TokenStakingManager( + ctx, + senderKey, + subnet, + ) + + erc20Address, erc20 := DeployExampleERC20(ctx, senderKey, subnet) + rewardCalculatorAddress, _ := DeployExampleRewardCalculator( + ctx, + senderKey, + subnet, + uint64(10), + ) + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.Initialize( + opts, + erc20tokenstakingmanager.PoSValidatorManagerSettings{ + BaseSettings: erc20tokenstakingmanager.ValidatorManagerSettings{ + SubnetID: subnet.SubnetID, + ChurnPeriodSeconds: DefaultChurnPeriodSeconds, + MaximumChurnPercentage: DefaultMaxChurnPercentage, + }, + MinimumStakeAmount: big.NewInt(0).SetUint64(DefaultMinStakeAmount), + MaximumStakeAmount: big.NewInt(0).SetUint64(DefaultMaxStakeAmount), + MinimumStakeDuration: DefaultMinStakeDurationSeconds, + MinimumDelegationFeeBips: DefaultMinDelegateFeeBips, + MaximumStakeMultiplier: DefaultMaxStakeMultiplier, + WeightToValueFactor: big.NewInt(0).SetUint64(DefaultWeightToValueFactor), + RewardCalculator: rewardCalculatorAddress, + }, + erc20Address, + ) + Expect(err).Should(BeNil()) + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return stakingManagerContractAddress, stakingManager, erc20Address, erc20 +} + +func DeployPoAValidatorManager( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, +) (common.Address, *poavalidatormanager.PoAValidatorManager) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + address, tx, validatorManager, err := poavalidatormanager.DeployPoAValidatorManager( + opts, + subnet.RPCClient, + 0, // ICMInitializable.Allowed + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return address, validatorManager +} + +func DeployAndInitializePoAValidatorManager( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + ownerAddress common.Address, +) (common.Address, *poavalidatormanager.PoAValidatorManager) { + validatorManagerAddress, validatorManager := DeployPoAValidatorManager( + ctx, + senderKey, + subnet, + ) + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := validatorManager.Initialize( + opts, + poavalidatormanager.ValidatorManagerSettings{ + SubnetID: subnet.SubnetID, + ChurnPeriodSeconds: uint64(0), + MaximumChurnPercentage: uint8(20), + }, + ownerAddress, + ) + Expect(err).Should(BeNil()) + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return validatorManagerAddress, validatorManager +} + +func DeployExampleRewardCalculator( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + rewardBasisPoints uint64, +) (common.Address, *examplerewardcalculator.ExampleRewardCalculator) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + address, tx, calculator, err := examplerewardcalculator.DeployExampleRewardCalculator( + opts, + subnet.RPCClient, + rewardBasisPoints, + ) + Expect(err).Should(BeNil()) + + // Wait for the transaction to be mined + WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + + return address, calculator +} + +// +// Validator Set Initialization utils +// + +func InitializeNativeTokenValidatorSet( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + validatorManager *nativetokenstakingmanager.NativeTokenStakingManager, + validatorManagerAddress common.Address, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + nodes []Node, +) []ids.ID { + initialValidators := make([]warpMessage.SubnetConversionValidatorData, len(nodes)) + initialValidatorsABI := make([]nativetokenstakingmanager.InitialValidator, len(nodes)) + for i, node := range nodes { + initialValidators[i] = warpMessage.SubnetConversionValidatorData{ + NodeID: node.NodeID.Bytes(), + BLSPublicKey: node.NodePoP.PublicKey, + Weight: nodes[i].Weight, + } + initialValidatorsABI[i] = nativetokenstakingmanager.InitialValidator{ + NodeID: node.NodeID.Bytes(), + BlsPublicKey: node.NodePoP.PublicKey[:], + Weight: nodes[i].Weight, + } + } + + subnetConversionData := warpMessage.SubnetConversionData{ + SubnetID: subnetInfo.SubnetID, + ManagerChainID: subnetInfo.BlockchainID, + ManagerAddress: validatorManagerAddress[:], + Validators: initialValidators, + } + subnetConversionDataABI := nativetokenstakingmanager.SubnetConversionData{ + SubnetID: subnetInfo.SubnetID, + ValidatorManagerBlockchainID: subnetInfo.BlockchainID, + ValidatorManagerAddress: validatorManagerAddress, + InitialValidators: initialValidatorsABI, + } + subnetConversionID, err := warpMessage.SubnetConversionID(subnetConversionData) + Expect(err).Should(BeNil()) + subnetConversionSignedMessage := ConstructSubnetConversionMessage( + subnetConversionID, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + // Deliver the Warp message to the subnet + receipt := DeliverNativeTokenSubnetConversion( + ctx, + senderKey, + subnetInfo, + validatorManagerAddress, + subnetConversionSignedMessage, + subnetConversionDataABI, + ) + initialValidatorCreatedEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseInitialValidatorCreated, + ) + Expect(err).Should(BeNil()) + var validationIDs []ids.ID + for i := range nodes { + validationIDs = append(validationIDs, subnetInfo.SubnetID.Append(uint32(i))) + } + + Expect(initialValidatorCreatedEvent.Weight).Should(Equal(new(big.Int).SetUint64(nodes[0].Weight))) + + emittedValidationID := ids.ID(initialValidatorCreatedEvent.ValidationID) + Expect(emittedValidationID).Should(Equal(validationIDs[0])) + + return validationIDs +} + +func InitializeERC20TokenValidatorSet( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + validatorManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + validatorManagerAddress common.Address, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + nodes []Node, +) []ids.ID { + initialValidators := make([]warpMessage.SubnetConversionValidatorData, len(nodes)) + initialValidatorsABI := make([]erc20tokenstakingmanager.InitialValidator, len(nodes)) + for i, node := range nodes { + initialValidators[i] = warpMessage.SubnetConversionValidatorData{ + NodeID: node.NodeID.Bytes(), + BLSPublicKey: node.NodePoP.PublicKey, + Weight: nodes[i].Weight, + } + initialValidatorsABI[i] = erc20tokenstakingmanager.InitialValidator{ + NodeID: node.NodeID.Bytes(), + BlsPublicKey: node.NodePoP.PublicKey[:], + Weight: nodes[i].Weight, + } + } + + subnetConversionData := warpMessage.SubnetConversionData{ + SubnetID: subnetInfo.SubnetID, + ManagerChainID: subnetInfo.BlockchainID, + ManagerAddress: validatorManagerAddress[:], + Validators: initialValidators, + } + subnetConversionDataABI := erc20tokenstakingmanager.SubnetConversionData{ + SubnetID: subnetInfo.SubnetID, + ValidatorManagerBlockchainID: subnetInfo.BlockchainID, + ValidatorManagerAddress: validatorManagerAddress, + InitialValidators: initialValidatorsABI, + } + subnetConversionID, err := warpMessage.SubnetConversionID(subnetConversionData) + Expect(err).Should(BeNil()) + subnetConversionSignedMessage := ConstructSubnetConversionMessage( + subnetConversionID, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt := DeliverERC20TokenSubnetConversion( + ctx, + senderKey, + subnetInfo, + validatorManagerAddress, + subnetConversionSignedMessage, + subnetConversionDataABI, + ) + initialValidatorCreatedEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseInitialValidatorCreated, + ) + Expect(err).Should(BeNil()) + var validationIDs []ids.ID + for i := range nodes { + validationIDs = append(validationIDs, subnetInfo.SubnetID.Append(uint32(i))) + } + + Expect(initialValidatorCreatedEvent.Weight).Should(Equal(new(big.Int).SetUint64(nodes[0].Weight))) + + emittedValidationID := ids.ID(initialValidatorCreatedEvent.ValidationID) + Expect(emittedValidationID).Should(Equal(validationIDs[0])) + + return validationIDs +} + +func InitializePoAValidatorSet( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + validatorManager *poavalidatormanager.PoAValidatorManager, + validatorManagerAddress common.Address, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + nodes []Node, +) []ids.ID { + initialValidators := make([]warpMessage.SubnetConversionValidatorData, len(nodes)) + initialValidatorsABI := make([]poavalidatormanager.InitialValidator, len(nodes)) + for i, node := range nodes { + initialValidators[i] = warpMessage.SubnetConversionValidatorData{ + NodeID: node.NodeID.Bytes(), + BLSPublicKey: node.NodePoP.PublicKey, + Weight: nodes[i].Weight, + } + initialValidatorsABI[i] = poavalidatormanager.InitialValidator{ + NodeID: node.NodeID.Bytes(), + BlsPublicKey: node.NodePoP.PublicKey[:], + Weight: nodes[i].Weight, + } + } + + subnetConversionData := warpMessage.SubnetConversionData{ + SubnetID: subnetInfo.SubnetID, + ManagerChainID: subnetInfo.BlockchainID, + ManagerAddress: validatorManagerAddress[:], + Validators: initialValidators, + } + subnetConversionDataABI := poavalidatormanager.SubnetConversionData{ + SubnetID: subnetInfo.SubnetID, + ValidatorManagerBlockchainID: subnetInfo.BlockchainID, + ValidatorManagerAddress: validatorManagerAddress, + InitialValidators: initialValidatorsABI, + } + subnetConversionID, err := warpMessage.SubnetConversionID(subnetConversionData) + Expect(err).Should(BeNil()) + subnetConversionSignedMessage := ConstructSubnetConversionMessage( + subnetConversionID, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + // Deliver the Warp message to the subnet + receipt := DeliverPoASubnetConversion( + ctx, + senderKey, + subnetInfo, + validatorManagerAddress, + subnetConversionSignedMessage, + subnetConversionDataABI, + ) + initialValidatorCreatedEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseInitialValidatorCreated, + ) + Expect(err).Should(BeNil()) + var validationIDs []ids.ID + for i := range nodes { + validationIDs = append(validationIDs, subnetInfo.SubnetID.Append(uint32(i))) + } + + Expect(initialValidatorCreatedEvent.Weight).Should(Equal(new(big.Int).SetUint64(nodes[0].Weight))) + + emittedValidationID := ids.ID(initialValidatorCreatedEvent.ValidationID) + Expect(emittedValidationID).Should(Equal(validationIDs[0])) + + return validationIDs +} + +func DeliverNativeTokenSubnetConversion( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validatorManagerAddress common.Address, + subnetConversionSignedMessage *avalancheWarp.Message, + subnetConversionData nativetokenstakingmanager.SubnetConversionData, +) *types.Receipt { + abi, err := nativetokenstakingmanager.NativeTokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("initializeValidatorSet", subnetConversionData, uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + validatorManagerAddress, + subnetConversionSignedMessage, + ) +} + +func DeliverERC20TokenSubnetConversion( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validatorManagerAddress common.Address, + subnetConversionSignedMessage *avalancheWarp.Message, + subnetConversionData erc20tokenstakingmanager.SubnetConversionData, +) *types.Receipt { + abi, err := erc20tokenstakingmanager.ERC20TokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("initializeValidatorSet", subnetConversionData, uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + validatorManagerAddress, + subnetConversionSignedMessage, + ) +} + +func DeliverPoASubnetConversion( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validatorManagerAddress common.Address, + subnetConversionSignedMessage *avalancheWarp.Message, + subnetConversionData poavalidatormanager.SubnetConversionData, +) *types.Receipt { + abi, err := poavalidatormanager.PoAValidatorManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("initializeValidatorSet", subnetConversionData, uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + validatorManagerAddress, + subnetConversionSignedMessage, + ) +} + +// +// Function call utils +// + +func InitializeNativeValidatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakeAmount *big.Int, + node Node, + expiry uint64, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, +) (*types.Receipt, ids.ID) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + opts.Value = stakeAmount + + tx, err := stakingManager.InitializeValidatorRegistration( + opts, + nativetokenstakingmanager.ValidatorRegistrationInput{ + NodeID: node.NodeID[:], + RegistrationExpiry: expiry, + BlsPublicKey: node.NodePoP.PublicKey[:], + }, + DefaultMinDelegateFeeBips, + DefaultMinStakeDurationSeconds, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + registrationInitiatedEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodCreated, + ) + Expect(err).Should(BeNil()) + return receipt, ids.ID(registrationInitiatedEvent.ValidationID) +} + +func InitializeERC20ValidatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakeAmount *big.Int, + token *exampleerc20.ExampleERC20, + stakingManagerAddress common.Address, + node Node, + expiry uint64, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, +) (*types.Receipt, ids.ID) { + ERC20Approve( + ctx, + token, + stakingManagerAddress, + stakeAmount, + subnet, + senderKey, + ) + + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + + tx, err := stakingManager.InitializeValidatorRegistration( + opts, + erc20tokenstakingmanager.ValidatorRegistrationInput{ + NodeID: node.NodeID[:], + RegistrationExpiry: expiry, + BlsPublicKey: node.NodePoP.PublicKey[:], + }, + DefaultMinDelegateFeeBips, + DefaultMinStakeDurationSeconds, + stakeAmount, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + registrationInitiatedEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodCreated, + ) + Expect(err).Should(BeNil()) + return receipt, ids.ID(registrationInitiatedEvent.ValidationID) +} + +func InitializePoAValidatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + node Node, + expiry uint64, + validatorManager *poavalidatormanager.PoAValidatorManager, +) (*types.Receipt, ids.ID) { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + + tx, err := validatorManager.InitializeValidatorRegistration( + opts, + poavalidatormanager.ValidatorRegistrationInput{ + NodeID: node.NodeID[:], + RegistrationExpiry: expiry, + BlsPublicKey: node.NodePoP.PublicKey[:], + }, + node.Weight, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + registrationInitiatedEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseValidationPeriodCreated, + ) + Expect(err).Should(BeNil()) + return receipt, ids.ID(registrationInitiatedEvent.ValidationID) +} + +func CompleteNativeValidatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + registrationSignedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := nativetokenstakingmanager.NativeTokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeValidatorRegistration", uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + registrationSignedMessage, + ) +} + +func CompleteERC20ValidatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + registrationSignedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := erc20tokenstakingmanager.ERC20TokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeValidatorRegistration", uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + registrationSignedMessage, + ) +} + +func CompletePoAValidatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validatorManagerAddress common.Address, + registrationSignedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := poavalidatormanager.PoAValidatorManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeValidatorRegistration", uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + validatorManagerAddress, + registrationSignedMessage, + ) +} + +// Calls a method that retreived a signed Warp message from the transaction's access list +func CallWarpReceiver( + ctx context.Context, + callData []byte, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + contract common.Address, + signedMessage *avalancheWarp.Message, +) *types.Receipt { + gasFeeCap, gasTipCap, nonce := CalculateTxParams(ctx, subnet, PrivateKeyToAddress(senderKey)) + registrationTx := predicateutils.NewPredicateTx( + subnet.EVMChainID, + nonce, + &contract, + 2_000_000, + gasFeeCap, + gasTipCap, + big.NewInt(0), + callData, + types.AccessList{}, + warp.ContractAddress, + signedMessage.Bytes(), + ) + signedRegistrationTx := SignTransaction(registrationTx, senderKey, subnet.EVMChainID) + return SendTransactionAndWaitForSuccess(ctx, subnet, signedRegistrationTx) +} + +func InitializeAndCompleteNativeValidatorRegistration( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, + stakingManagerContractAddress common.Address, + expiry uint64, + node Node, +) ids.ID { + stakeAmount, err := stakingManager.WeightToValue( + &bind.CallOpts{}, + node.Weight, + ) + Expect(err).Should(BeNil()) + // Initiate validator registration + receipt, validationID := InitializeNativeValidatorRegistration( + ctx, + fundedKey, + subnetInfo, + stakeAmount, + node, + expiry, + stakingManager, + ) + + // Gather subnet-evm Warp signatures for the RegisterSubnetValidatorMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + signedWarpMessage := ConstructSignedWarpMessage(ctx, receipt, subnetInfo, pChainInfo) + + _, err = network.GetPChainWallet().IssueRegisterSubnetValidatorTx( + 100*units.Avax, + node.NodePoP.ProofOfPossession, + signedWarpMessage.Bytes(), + ) + Expect(err).Should(BeNil()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing validator registration") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessage( + validationID, + expiry, + node, + true, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteNativeValidatorRegistration( + ctx, + fundedKey, + subnetInfo, + stakingManagerContractAddress, + registrationSignedMessage, + ) + // Check that the validator is registered in the staking contract + registrationEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodRegistered, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + + return validationID +} + +func InitializeAndCompleteERC20ValidatorRegistration( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + stakingManagerAddress common.Address, + erc20 *exampleerc20.ExampleERC20, + expiry uint64, + node Node, +) ids.ID { + stakeAmount, err := stakingManager.WeightToValue( + &bind.CallOpts{}, + node.Weight, + ) + Expect(err).Should(BeNil()) + // Initiate validator registration + var receipt *types.Receipt + log.Println("Initializing validator registration") + receipt, validationID := InitializeERC20ValidatorRegistration( + ctx, + fundedKey, + subnetInfo, + stakeAmount, + erc20, + stakingManagerAddress, + node, + expiry, + stakingManager, + ) + + // Gather subnet-evm Warp signatures for the RegisterSubnetValidatorMessage & relay to the P-Chain + signedWarpMessage := ConstructSignedWarpMessage(ctx, receipt, subnetInfo, pChainInfo) + + _, err = network.GetPChainWallet().IssueRegisterSubnetValidatorTx( + 100*units.Avax, + node.NodePoP.ProofOfPossession, + signedWarpMessage.Bytes(), + ) + Expect(err).Should(BeNil()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing validator registration") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessage( + validationID, + expiry, + node, + true, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteERC20ValidatorRegistration( + ctx, + fundedKey, + subnetInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + // Check that the validator is registered in the staking contract + registrationEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodRegistered, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + + return validationID +} + +func InitializeAndCompletePoAValidatorRegistration( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + ownerKey *ecdsa.PrivateKey, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + validatorManager *poavalidatormanager.PoAValidatorManager, + validatorManagerAddress common.Address, + expiry uint64, + node Node, +) ids.ID { + // Initiate validator registration + receipt, validationID := InitializePoAValidatorRegistration( + ctx, + ownerKey, + subnetInfo, + node, + expiry, + validatorManager, + ) + + // Gather subnet-evm Warp signatures for the RegisterSubnetValidatorMessage & relay to the P-Chain + signedWarpMessage := ConstructSignedWarpMessage(ctx, receipt, subnetInfo, pChainInfo) + + _, err := network.GetPChainWallet().IssueRegisterSubnetValidatorTx( + 100*units.Avax, + node.NodePoP.ProofOfPossession, + signedWarpMessage.Bytes(), + ) + Expect(err).Should(BeNil()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing validator registration") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessage( + validationID, + expiry, + node, + true, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompletePoAValidatorRegistration( + ctx, + fundedKey, + subnetInfo, + validatorManagerAddress, + registrationSignedMessage, + ) + // Check that the validator is registered in the staking contract + registrationEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseValidationPeriodRegistered, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) + + return validationID +} + +func InitializeEndNativeValidation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, + validationID ids.ID, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.InitializeEndValidation( + opts, + validationID, + false, + 0, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func ForceInitializeEndNativeValidation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, + validationID ids.ID, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.ForceInitializeEndValidation( + opts, + validationID, + false, + 0, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func InitializeEndERC20Validation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + validationID ids.ID, + force bool, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.InitializeEndValidation( + opts, + validationID, + false, + 0, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func ForceInitializeEndERC20Validation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + validationID ids.ID, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.ForceInitializeEndValidation( + opts, + validationID, + false, + 0, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func InitializeEndPoAValidation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validatorManager *poavalidatormanager.PoAValidatorManager, + validationID ids.ID, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := validatorManager.InitializeEndValidation( + opts, + validationID, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func CompleteEndNativeValidation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + registrationSignedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := nativetokenstakingmanager.NativeTokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeEndValidation", uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + registrationSignedMessage, + ) +} + +func CompleteEndERC20Validation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + registrationSignedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := erc20tokenstakingmanager.ERC20TokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeEndValidation", uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + registrationSignedMessage, + ) +} + +func CompleteEndPoAValidation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validatorManagerAddress common.Address, + registrationSignedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := poavalidatormanager.PoAValidatorManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeEndValidation", uint32(0)) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + validatorManagerAddress, + registrationSignedMessage, + ) +} + +func InitializeERC20DelegatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validationID ids.ID, + delegationAmount *big.Int, + token *exampleerc20.ExampleERC20, + stakingManagerAddress common.Address, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, +) *types.Receipt { + ERC20Approve( + ctx, + token, + stakingManagerAddress, + delegationAmount, + subnet, + senderKey, + ) + + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + + tx, err := stakingManager.InitializeDelegatorRegistration( + opts, + validationID, + delegationAmount, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + _, err = GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorAdded, + ) + Expect(err).Should(BeNil()) + return receipt +} + +func CompleteERC20DelegatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + delegationID ids.ID, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + signedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := erc20tokenstakingmanager.ERC20TokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeDelegatorRegistration", uint32(0), delegationID) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + signedMessage, + ) +} + +func InitializeEndERC20Delegation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + delegationID ids.ID, +) *types.Receipt { + WaitMinStakeDuration(ctx, subnet, senderKey) + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.ForceInitializeEndDelegation( + opts, + delegationID, + false, + 0, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func CompleteEndERC20Delegation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + delegationID ids.ID, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + signedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := erc20tokenstakingmanager.ERC20TokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeEndDelegation", uint32(0), delegationID) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + signedMessage, + ) +} + +func InitializeNativeDelegatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + validationID ids.ID, + delegationAmount *big.Int, + stakingManagerAddress common.Address, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, +) *types.Receipt { + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + opts.Value = delegationAmount + + tx, err := stakingManager.InitializeDelegatorRegistration( + opts, + validationID, + ) + Expect(err).Should(BeNil()) + receipt := WaitForTransactionSuccess(ctx, subnet, tx.Hash()) + _, err = GetEventFromLogs( + receipt.Logs, + stakingManager.ParseDelegatorAdded, + ) + Expect(err).Should(BeNil()) + return receipt +} + +func CompleteNativeDelegatorRegistration( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + delegationID ids.ID, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + signedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := nativetokenstakingmanager.NativeTokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeDelegatorRegistration", uint32(0), delegationID) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + signedMessage, + ) +} + +func InitializeEndNativeDelegation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + subnet interfaces.SubnetTestInfo, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, + delegationID ids.ID, +) *types.Receipt { + WaitMinStakeDuration(ctx, subnet, senderKey) + opts, err := bind.NewKeyedTransactorWithChainID(senderKey, subnet.EVMChainID) + Expect(err).Should(BeNil()) + tx, err := stakingManager.ForceInitializeEndDelegation( + opts, + delegationID, + false, + 0, + ) + Expect(err).Should(BeNil()) + return WaitForTransactionSuccess(ctx, subnet, tx.Hash()) +} + +func CompleteEndNativeDelegation( + ctx context.Context, + senderKey *ecdsa.PrivateKey, + delegationID ids.ID, + subnet interfaces.SubnetTestInfo, + stakingManagerContractAddress common.Address, + signedMessage *avalancheWarp.Message, +) *types.Receipt { + abi, err := nativetokenstakingmanager.NativeTokenStakingManagerMetaData.GetAbi() + Expect(err).Should(BeNil()) + callData, err := abi.Pack("completeEndDelegation", uint32(0), delegationID) + Expect(err).Should(BeNil()) + return CallWarpReceiver( + ctx, + callData, + senderKey, + subnet, + stakingManagerContractAddress, + signedMessage, + ) +} + +func InitializeAndCompleteEndInitialNativeValidation( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, + stakingManagerAddress common.Address, + validationID ids.ID, + index uint32, + weight uint64, +) { + log.Println("Initializing initial validator removal") + WaitMinStakeDuration(ctx, subnetInfo, fundedKey) + receipt := ForceInitializeEndNativeValidation( + ctx, + fundedKey, + subnetInfo, + stakingManager, + validationID, + ) + validatorRemovalEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(validatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(validatorRemovalEvent.Weight.Uint64()).Should(Equal(weight)) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + unsignedMessage := ExtractWarpMessageFromLog(ctx, receipt, subnetInfo) + signedWarpMessage, err := signatureAggregator.CreateSignedMessage( + unsignedMessage, + nil, + subnetInfo.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + // Deliver the Warp message to the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing initial validator removal") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessageForInitialValidator( + validationID, + index, + false, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteEndNativeValidation( + ctx, + fundedKey, + subnetInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + + // Check that the validator is has been delisted from the staking contract + validationEndedEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodEnded, + ) + Expect(err).Should(BeNil()) + Expect(validationEndedEvent.ValidationID[:]).Should(Equal(validationID[:])) +} + +func InitializeAndCompleteEndNativeValidation( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *nativetokenstakingmanager.NativeTokenStakingManager, + stakingManagerAddress common.Address, + validationID ids.ID, + expiry uint64, + node Node, + nonce uint64, +) { + log.Println("Initializing validator removal") + WaitMinStakeDuration(ctx, subnetInfo, fundedKey) + receipt := ForceInitializeEndNativeValidation( + ctx, + fundedKey, + subnetInfo, + stakingManager, + validationID, + ) + validatorRemovalEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(validatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(validatorRemovalEvent.Weight.Uint64()).Should(Equal(node.Weight)) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + unsignedMessage := ExtractWarpMessageFromLog(ctx, receipt, subnetInfo) + signedWarpMessage, err := signatureAggregator.CreateSignedMessage( + unsignedMessage, + nil, + subnetInfo.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + // Deliver the Warp message to the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing validator removal") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessage( + validationID, + expiry, + node, + false, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteEndNativeValidation( + ctx, + fundedKey, + subnetInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + + // Check that the validator is has been delisted from the staking contract + registrationEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodEnded, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) +} + +func InitializeAndCompleteEndInitialERC20Validation( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + stakingManagerAddress common.Address, + validationID ids.ID, + index uint32, + weight uint64, +) { + log.Println("Initializing initial validator removal") + WaitMinStakeDuration(ctx, subnetInfo, fundedKey) + receipt := ForceInitializeEndERC20Validation( + ctx, + fundedKey, + subnetInfo, + stakingManager, + validationID, + ) + validatorRemovalEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(validatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(validatorRemovalEvent.Weight.Uint64()).Should(Equal(weight)) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + unsignedMessage := ExtractWarpMessageFromLog(ctx, receipt, subnetInfo) + signedWarpMessage, err := signatureAggregator.CreateSignedMessage( + unsignedMessage, + nil, + subnetInfo.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + // Deliver the Warp message to the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing initial validator removal") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessageForInitialValidator( + validationID, + index, + false, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteEndERC20Validation( + ctx, + fundedKey, + subnetInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + + // Check that the validator is has been delisted from the staking contract + validationEndedEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodEnded, + ) + Expect(err).Should(BeNil()) + Expect(validationEndedEvent.ValidationID[:]).Should(Equal(validationID[:])) +} + +func InitializeAndCompleteEndERC20Validation( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *erc20tokenstakingmanager.ERC20TokenStakingManager, + stakingManagerAddress common.Address, + validationID ids.ID, + expiry uint64, + node Node, + nonce uint64, +) { + log.Println("Initializing validator removal") + WaitMinStakeDuration(ctx, subnetInfo, fundedKey) + receipt := ForceInitializeEndERC20Validation( + ctx, + fundedKey, + subnetInfo, + stakingManager, + validationID, + ) + validatorRemovalEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(validatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(validatorRemovalEvent.Weight.Uint64()).Should(Equal(node.Weight)) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + unsignedMessage := ExtractWarpMessageFromLog(ctx, receipt, subnetInfo) + signedWarpMessage, err := signatureAggregator.CreateSignedMessage( + unsignedMessage, + nil, + subnetInfo.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + // Deliver the Warp message to the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing validator removal") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessage( + validationID, + expiry, + node, + false, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteEndERC20Validation( + ctx, + fundedKey, + subnetInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + + // Check that the validator is has been delisted from the staking contract + validationEndedEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodEnded, + ) + Expect(err).Should(BeNil()) + Expect(validationEndedEvent.ValidationID[:]).Should(Equal(validationID[:])) +} + +func InitializeAndCompleteEndInitialPoAValidation( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + ownerKey *ecdsa.PrivateKey, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + stakingManager *poavalidatormanager.PoAValidatorManager, + stakingManagerAddress common.Address, + validationID ids.ID, + index uint32, + weight uint64, +) { + log.Println("Initializing initial validator removal") + WaitMinStakeDuration(ctx, subnetInfo, fundedKey) + receipt := InitializeEndPoAValidation( + ctx, + ownerKey, + subnetInfo, + stakingManager, + validationID, + ) + validatorRemovalEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(validatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(validatorRemovalEvent.Weight.Uint64()).Should(Equal(weight)) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + unsignedMessage := ExtractWarpMessageFromLog(ctx, receipt, subnetInfo) + signedWarpMessage, err := signatureAggregator.CreateSignedMessage( + unsignedMessage, + nil, + subnetInfo.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + // Deliver the Warp message to the P-Chain + network.GetPChainWallet().IssueSetSubnetValidatorWeightTx(signedWarpMessage.Bytes()) + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + log.Println("Completing initial validator removal") + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessageForInitialValidator( + validationID, + index, + false, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteEndPoAValidation( + ctx, + fundedKey, + subnetInfo, + stakingManagerAddress, + registrationSignedMessage, + ) + + // Check that the validator is has been delisted from the staking contract + validationEndedEvent, err := GetEventFromLogs( + receipt.Logs, + stakingManager.ParseValidationPeriodEnded, + ) + Expect(err).Should(BeNil()) + Expect(validationEndedEvent.ValidationID[:]).Should(Equal(validationID[:])) +} + +func InitializeAndCompleteEndPoAValidation( + ctx context.Context, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, + ownerKey *ecdsa.PrivateKey, + fundedKey *ecdsa.PrivateKey, + subnetInfo interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + validatorManager *poavalidatormanager.PoAValidatorManager, + validatorManagerAddress common.Address, + validationID ids.ID, + weight uint64, + nonce uint64, +) { + receipt := InitializeEndPoAValidation( + ctx, + ownerKey, + subnetInfo, + validatorManager, + validationID, + ) + validatorRemovalEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseValidatorRemovalInitialized, + ) + Expect(err).Should(BeNil()) + Expect(validatorRemovalEvent.ValidationID[:]).Should(Equal(validationID[:])) + Expect(validatorRemovalEvent.Weight.Uint64()).Should(Equal(weight)) + + // Gather subnet-evm Warp signatures for the SetSubnetValidatorWeightMessage & relay to the P-Chain + // (Sending to the P-Chain will be skipped for now) + signedWarpMessage := ConstructSignedWarpMessage(ctx, receipt, subnetInfo, pChainInfo) + Expect(err).Should(BeNil()) + + // Validate the Warp message, (this will be done on the P-Chain in the future) + ValidateSubnetValidatorWeightMessage(signedWarpMessage, validationID, 0, nonce) + + // Construct a SubnetValidatorRegistrationMessage Warp message from the P-Chain + registrationSignedMessage := ConstructSubnetValidatorRegistrationMessage( + validationID, + 0, + Node{}, + false, + subnetInfo, + pChainInfo, + network, + signatureAggregator, + ) + + // Deliver the Warp message to the subnet + receipt = CompleteEndPoAValidation( + ctx, + ownerKey, + subnetInfo, + validatorManagerAddress, + registrationSignedMessage, + ) + + // Check that the validator is has been delisted from the staking contract + registrationEvent, err := GetEventFromLogs( + receipt.Logs, + validatorManager.ParseValidationPeriodEnded, + ) + Expect(err).Should(BeNil()) + Expect(registrationEvent.ValidationID[:]).Should(Equal(validationID[:])) +} + +// +// P-Chain utils +// + +func ConstructSubnetValidatorRegistrationMessageForInitialValidator( + validationID ids.ID, + index uint32, + valid bool, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, +) *avalancheWarp.Message { + justification := platformvm.SubnetValidatorRegistrationJustification{ + Preimage: &platformvm.SubnetValidatorRegistrationJustification_ConvertSubnetTxData{ + ConvertSubnetTxData: &platformvm.SubnetIDIndex{ + SubnetId: subnet.SubnetID[:], + Index: index, + }, + }, + } + justificationBytes, err := proto.Marshal(&justification) + Expect(err).Should(BeNil()) + + registrationPayload, err := warpMessage.NewSubnetValidatorRegistration(validationID, valid) + Expect(err).Should(BeNil()) + registrationAddressedCall, err := warpPayload.NewAddressedCall(nil, registrationPayload.Bytes()) + Expect(err).Should(BeNil()) + registrationUnsignedMessage, err := avalancheWarp.NewUnsignedMessage( + network.GetNetworkID(), + pChainInfo.BlockchainID, + registrationAddressedCall.Bytes(), + ) + Expect(err).Should(BeNil()) + + registrationSignedMessage, err := signatureAggregator.CreateSignedMessage( + registrationUnsignedMessage, + justificationBytes, + subnet.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + return registrationSignedMessage +} + +func ConstructSubnetValidatorRegistrationMessage( + validationID ids.ID, + expiry uint64, + node Node, + valid bool, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, +) *avalancheWarp.Message { + msg, err := warpMessage.NewRegisterSubnetValidator( + subnet.SubnetID, + node.NodeID, + node.NodePoP.PublicKey, + expiry, + warpMessage.PChainOwner{}, + warpMessage.PChainOwner{}, + node.Weight, + ) + Expect(err).Should(BeNil()) + justification := platformvm.SubnetValidatorRegistrationJustification{ + Preimage: &platformvm.SubnetValidatorRegistrationJustification_RegisterSubnetValidatorMessage{ + RegisterSubnetValidatorMessage: msg.Bytes(), + }, + } + justificationBytes, err := proto.Marshal(&justification) + Expect(err).Should(BeNil()) + + registrationPayload, err := warpMessage.NewSubnetValidatorRegistration(validationID, valid) + Expect(err).Should(BeNil()) + registrationAddressedCall, err := warpPayload.NewAddressedCall(nil, registrationPayload.Bytes()) + Expect(err).Should(BeNil()) + registrationUnsignedMessage, err := avalancheWarp.NewUnsignedMessage( + network.GetNetworkID(), + pChainInfo.BlockchainID, + registrationAddressedCall.Bytes(), + ) + Expect(err).Should(BeNil()) + + registrationSignedMessage, err := signatureAggregator.CreateSignedMessage( + registrationUnsignedMessage, + justificationBytes, + subnet.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + + return registrationSignedMessage +} + +func ConstructSubnetValidatorWeightUpdateMessage( + validationID ids.ID, + nonce uint64, + weight uint64, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, +) *avalancheWarp.Message { + payload, err := warpMessage.NewSubnetValidatorWeight(validationID, nonce, weight) + Expect(err).Should(BeNil()) + updateAddressedCall, err := warpPayload.NewAddressedCall(nil, payload.Bytes()) + Expect(err).Should(BeNil()) + updateUnsignedMessage, err := avalancheWarp.NewUnsignedMessage( + network.GetNetworkID(), + pChainInfo.BlockchainID, + updateAddressedCall.Bytes(), + ) + Expect(err).Should(BeNil()) + + updateSignedMessage, err := signatureAggregator.CreateSignedMessage( + updateUnsignedMessage, + nil, + subnet.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + return updateSignedMessage +} + +func ConstructSubnetConversionMessage( + subnetConversionID ids.ID, + subnet interfaces.SubnetTestInfo, + pChainInfo interfaces.SubnetTestInfo, + network interfaces.LocalNetwork, + signatureAggregator *aggregator.SignatureAggregator, +) *avalancheWarp.Message { + subnetConversionPayload, err := warpMessage.NewSubnetConversion(subnetConversionID) + Expect(err).Should(BeNil()) + subnetConversionAddressedCall, err := warpPayload.NewAddressedCall( + nil, + subnetConversionPayload.Bytes(), + ) + Expect(err).Should(BeNil()) + subnetConversionUnsignedMessage, err := avalancheWarp.NewUnsignedMessage( + network.GetNetworkID(), + pChainInfo.BlockchainID, + subnetConversionAddressedCall.Bytes(), + ) + Expect(err).Should(BeNil()) + + subnetConversionSignedMessage, err := signatureAggregator.CreateSignedMessage( + subnetConversionUnsignedMessage, + subnet.SubnetID[:], + subnet.SubnetID, + 67, + ) + Expect(err).Should(BeNil()) + return subnetConversionSignedMessage +} + +// +// Warp message validiation utils +// These will be replaced by the actual implementation on the P-Chain in the future +// + +func ValidateRegisterSubnetValidatorMessage( + signedWarpMessage *avalancheWarp.Message, + nodeID ids.ID, + weight uint64, + subnetID ids.ID, + blsPublicKey [bls.PublicKeyLen]byte, +) { + // Validate the Warp message, (this will be done on the P-Chain in the future) + msg, err := warpPayload.ParseAddressedCall(signedWarpMessage.UnsignedMessage.Payload) + Expect(err).Should(BeNil()) + // Check that the addressed call payload is a registered Warp message type + var payloadInterface warpMessage.Payload + ver, err := warpMessage.Codec.Unmarshal(msg.Payload, &payloadInterface) + Expect(err).Should(BeNil()) + payload, ok := payloadInterface.(*warpMessage.RegisterSubnetValidator) + Expect(ok).Should(BeTrue()) + + Expect(ver).Should(Equal(uint16(warpMessage.CodecVersion))) + Expect(payload.NodeID).Should(Equal(nodeID)) + Expect(payload.Weight).Should(Equal(weight)) + Expect(payload.SubnetID).Should(Equal(subnetID)) + Expect(payload.BLSPublicKey[:]).Should(Equal(blsPublicKey[:])) +} + +func ValidateSubnetValidatorWeightMessage( + signedWarpMessage *avalancheWarp.Message, + validationID ids.ID, + weight uint64, + nonce uint64, +) { + msg, err := warpPayload.ParseAddressedCall(signedWarpMessage.UnsignedMessage.Payload) + Expect(err).Should(BeNil()) + // Check that the addressed call payload is a registered Warp message type + var payloadInterface warpMessage.Payload + ver, err := warpMessage.Codec.Unmarshal(msg.Payload, &payloadInterface) + Expect(err).Should(BeNil()) + payload, ok := payloadInterface.(*warpMessage.SubnetValidatorWeight) + Expect(ok).Should(BeTrue()) + + Expect(ver).Should(Equal(uint16(warpMessage.CodecVersion))) + Expect(payload.ValidationID).Should(Equal(validationID)) + Expect(payload.Weight).Should(Equal(weight)) + Expect(payload.Nonce).Should(Equal(nonce)) +} + +func WaitMinStakeDuration( + ctx context.Context, + subnet interfaces.SubnetTestInfo, + fundedKey *ecdsa.PrivateKey, +) { + // Make sure minimum stake duration has passed + time.Sleep(time.Duration(DefaultMinStakeDurationSeconds) * time.Second) + + // Send a loopback transaction to self to force a block production + // before delisting the validator. + SendNativeTransfer( + ctx, + subnet, + fundedKey, + common.Address{}, + big.NewInt(10), + ) +} + +func CalculateSubnetConversionValidationId(subnetID ids.ID, validatorIdx uint32) ids.ID { + preImage := make([]byte, 36) + copy(preImage[0:32], subnetID[:]) + binary.BigEndian.PutUint32(preImage[32:36], validatorIdx) + return sha256.Sum256(preImage) +} + +// PackSubnetConversionData defines a packing function that works +// over any struct instance of SubnetConversionData since the abi-bindings +// process generates one for each of the different contracts. +func PackSubnetConversionData(data interface{}) ([]byte, error) { + v := reflect.ValueOf(data) + if v.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected struct, got %s", v.Kind()) + } + // Define required fields and their expected types + requiredFields := map[string]reflect.Type{ + "SubnetID": reflect.TypeOf([32]byte{}), + "ValidatorManagerBlockchainID": reflect.TypeOf([32]byte{}), + "ValidatorManagerAddress": reflect.TypeOf(common.Address{}), + // InitialValidators is a slice of structs and handled separately + "InitialValidators": reflect.TypeOf([]struct{}{}), + } + // Check for required fields and types + for fieldName, expectedType := range requiredFields { + field := v.FieldByName(fieldName) + + if !field.IsValid() { + return nil, fmt.Errorf("field %s is missing", fieldName) + } + // Allow flexible types for InitialValidators by checking it contains structs + if fieldName == "InitialValidators" { + if field.Kind() != reflect.Slice || field.Type().Elem().Kind() != reflect.Struct { + return nil, fmt.Errorf("field %s has incorrect type: expected a slice of structs", fieldName) + } + } else { + if field.Type() != expectedType { + return nil, fmt.Errorf("field %s has incorrect type: expected %s, got %s", fieldName, expectedType, field.Type()) + } + } + } + + subnetID := v.FieldByName("SubnetID").Interface().([32]byte) + validatorManagerBlockchainID := v.FieldByName("ValidatorManagerBlockchainID").Interface().([32]byte) + validatorManagerAddress := v.FieldByName("ValidatorManagerAddress").Interface().(common.Address) + initialValidators := v.FieldByName("InitialValidators") + + // Pack each InitialValidator struct + packedInitialValidators := make([][]byte, initialValidators.Len()) + var packedInitialValidatorsLen uint32 + for i := 0; i < initialValidators.Len(); i++ { + iv := initialValidators.Index(i).Interface() + ivPacked, err := PackInitialValidator(iv) + if err != nil { + return nil, fmt.Errorf("failed to pack InitialValidator: %w", err) + } + + packedInitialValidators[i] = ivPacked + packedInitialValidatorsLen += uint32(len(ivPacked)) + } + + b := make([]byte, 94+packedInitialValidatorsLen) + binary.BigEndian.PutUint16(b[0:2], uint16(warpMessage.CodecVersion)) + copy(b[2:34], subnetID[:]) + copy(b[34:66], validatorManagerBlockchainID[:]) + // These are evm addresses and have lengths of 20 so hardcoding here + binary.BigEndian.PutUint32(b[66:70], uint32(20)) + copy(b[70:90], validatorManagerAddress.Bytes()) + binary.BigEndian.PutUint32(b[90:94], uint32(initialValidators.Len())) + offset := 94 + for _, ivPacked := range packedInitialValidators { + copy(b[offset:offset+len(ivPacked)], ivPacked) + offset += len(ivPacked) + } + + return b, nil +} + +// PackInitialValidator defines a packing function that works +// over any struct instance of InitialValidator since the abi-bindings +// process generates one for each of the different contracts. +func PackInitialValidator(iv interface{}) ([]byte, error) { + v := reflect.ValueOf(iv) + + // Ensure the passed interface is a struct + if v.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected a struct, got %s", v.Kind()) + } + + // Define required fields and their expected types + requiredFields := map[string]reflect.Type{ + "NodeID": reflect.TypeOf([]byte{}), + "Weight": reflect.TypeOf(uint64(0)), + "BlsPublicKey": reflect.TypeOf([]byte{}), + } + + // Check for required fields and types + for fieldName, expectedType := range requiredFields { + field := v.FieldByName(fieldName) + + if !field.IsValid() { + return nil, fmt.Errorf("field %s is missing", fieldName) + } + + if field.Type() != expectedType { + return nil, fmt.Errorf("field %s has incorrect type: expected %s, got %s", fieldName, expectedType, field.Type()) + } + } + + // At this point, we know the struct has all required fields with correct types + // Use reflection to retrieve field values and perform canonical packing + nodeID := v.FieldByName("NodeID").Interface().([]byte) + weight := v.FieldByName("Weight").Interface().(uint64) + blsPublicKey := v.FieldByName("BlsPublicKey").Interface().([]byte) + + b := make([]byte, 60+len(nodeID)) + binary.BigEndian.PutUint32(b[0:4], uint32(len(nodeID))) + copy(b[4:4+len(nodeID)], nodeID[:]) + binary.BigEndian.PutUint64(b[4+len(nodeID):4+len(nodeID)+8], weight) + copy(b[4+len(nodeID)+8:4+len(nodeID)+8+48], blsPublicKey) + return b, nil +} + +func PChainProposerVMWorkaround( + network interfaces.LocalNetwork, +) { + // Workaround current block map rules + destAddr, err := address.ParseToID(DefaultPChainAddress) + Expect(err).Should(BeNil()) + log.Println("Waiting for P-Chain...") + time.Sleep(30 * time.Second) + + pBuilder := network.GetPChainWallet().Builder() + pContext := pBuilder.Context() + avaxAssetID := pContext.AVAXAssetID + locktime := uint64(time.Date(2030, 1, 1, 0, 0, 0, 0, time.UTC).Unix()) + amount := 500 * units.MilliAvax + _, err = network.GetPChainWallet().IssueBaseTx([]*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &stakeable.LockOut{ + Locktime: locktime, + TransferableOut: &secp256k1fx.TransferOutput{ + Amt: amount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + destAddr, + }, + }, + }, + }, + }, + }) + Expect(err).Should(BeNil()) + _, err = network.GetPChainWallet().IssueBaseTx([]*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &stakeable.LockOut{ + Locktime: locktime, + TransferableOut: &secp256k1fx.TransferOutput{ + Amt: amount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + destAddr, + }, + }, + }, + }, + }, + }) + Expect(err).Should(BeNil()) + // End workaround +} + +func AdvanceProposerVM( + ctx context.Context, + subnet interfaces.SubnetTestInfo, + fundedKey *ecdsa.PrivateKey, + blocks int, +) { + for i := 0; i < blocks; i++ { + err := subnetEvmUtils.IssueTxsToActivateProposerVMFork( + ctx, subnet.EVMChainID, fundedKey, subnet.WSClient, + ) + Expect(err).Should(BeNil()) + } +} + +func ConvertSubnet( + ctx context.Context, + subnetInfo interfaces.SubnetTestInfo, + network interfaces.LocalNetwork, + stakingManagerAddress common.Address, + fundedKey *ecdsa.PrivateKey, +) []Node { + // Remove the current validators before converting the subnet + var nodes []Node + for _, uri := range subnetInfo.NodeURIs { + infoClient := info.NewClient(uri) + nodeID, nodePoP, err := infoClient.GetNodeID(ctx) + Expect(err).Should(BeNil()) + nodes = append(nodes, Node{ + NodeID: nodeID, + NodePoP: nodePoP, + }) + + _, err = network.GetPChainWallet().IssueRemoveSubnetValidatorTx( + nodeID, + subnetInfo.SubnetID, + ) + Expect(err).Should(BeNil()) + } + + // Sort the nodeIDs so that the subnet conversion ID matches the P-Chain + sort.Slice(nodes, func(i, j int) bool { + return string(nodes[i].NodeID.Bytes()) < string(nodes[j].NodeID.Bytes()) + }) + + totalWeight := uint64(len(nodes)-1) * units.Schmeckle + for i := 0; i < len(nodes)-1; i++ { + nodes[i].Weight = units.Schmeckle + totalWeight += units.Schmeckle + } + // Set the last node's weight such that removing any other node will not violate the churn limit + nodes[len(nodes)-1].Weight = 4 * totalWeight + + // Construct the convert subnet info + destAddr, err := address.ParseToID(DefaultPChainAddress) + Expect(err).Should(BeNil()) + vdrs := make([]*txs.ConvertSubnetValidator, len(nodes)) + for i, node := range nodes { + vdrs[i] = &txs.ConvertSubnetValidator{ + NodeID: node.NodeID.Bytes(), + Weight: nodes[i].Weight, + Balance: units.Avax * 100, + Signer: *node.NodePoP, + RemainingBalanceOwner: warpMessage.PChainOwner{ + Threshold: 1, + Addresses: []ids.ShortID{destAddr}, + }, + DeactivationOwner: warpMessage.PChainOwner{ + Threshold: 1, + Addresses: []ids.ShortID{destAddr}, + }, + } + } + + log.Println("Issuing ConvertSubnetTx") + _, err = network.GetPChainWallet().IssueConvertSubnetTx( + subnetInfo.SubnetID, + subnetInfo.BlockchainID, + stakingManagerAddress[:], + vdrs, + ) + Expect(err).Should(BeNil()) + + PChainProposerVMWorkaround(network) + AdvanceProposerVM(ctx, subnetInfo, fundedKey, 5) + + return nodes +} diff --git a/tests/utils/warp-genesis-template.json b/tests/utils/warp-genesis-template.json index 9d221136e..5dab415be 100644 --- a/tests/utils/warp-genesis-template.json +++ b/tests/utils/warp-genesis-template.json @@ -28,7 +28,8 @@ "blockTimestamp": 0, "adminAddresses": [ "0xAcB633F5B00099c7ec187eB00156c5cd9D854b5B", - "0x3405506b3711859c5070949ed9b700c7ba7bf750" + "0x3405506b3711859c5070949ed9b700c7ba7bf750", + "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC" ] } }, diff --git a/utils/deployment-utils/deployment_utils.go b/utils/deployment-utils/deployment_utils.go index a12dbaf12..3f0ba81ca 100644 --- a/utils/deployment-utils/deployment_utils.go +++ b/utils/deployment-utils/deployment_utils.go @@ -126,8 +126,6 @@ func ConstructKeylessTransaction( contractAddress := crypto.CreateAddress(senderAddress, 0) contractAddressString := contractAddress.Hex() // "0x" prepended by Hex() already. - log.Println("Raw Teleporter Contract Creation Transaction:") - log.Println(contractCreationTxString) log.Println("Teleporter Contract Keyless Deployer Address: ", senderAddressString) log.Println("Teleporter Messenger Universal Contract Address: ", contractAddressString)