From 9389ba6f79e754f94ed943395453c0b61938ea57 Mon Sep 17 00:00:00 2001 From: trajan0x <83933037+trajan0x@users.noreply.github.com> Date: Sat, 30 Jul 2022 15:13:51 +0100 Subject: [PATCH] Add Attesation Contract (#69) Co-authored-by: Trajan0x --- core/agents/updater/producer.go | 13 + .../attestationcollector.abigen.go | 3443 +++++++++++++++++ .../attestationcollector.contractinfo.json | 1 + .../attestationcollector.metadata.go | 24 + .../attestationcollector/generate.go | 3 + .../contracts/attestationcollector/helpers.go | 34 + .../attestationharness.abigen.go | 848 ++++ .../attestationharness.contractinfo.json | 1 + .../attestationharness.metadata.go | 24 + .../test/attestationharness/generate.go | 4 + .../test/attestationharness/helpers.go | 35 + core/db/datastore/pebble/sdb.go | 6 +- core/db/db_test.go | 6 +- core/db/message.go | 4 +- core/domains/domain.go | 7 +- core/domains/evm/collector.go | 62 + core/domains/evm/collector_test.go | 35 + core/domains/evm/suite_test.go | 26 +- core/testutil/contracttype.go | 10 + core/testutil/contracttypeimpl_string.go | 8 +- core/testutil/deployers.go | 52 + core/testutil/manager.go | 2 +- core/testutil/typecast.go | 31 +- core/testutil/typecast_test.go | 14 + core/types/attestation.go | 75 + core/types/encoder.go | 84 + core/types/encoder_test.go | 47 + .../types/{message_test.go => parity_test.go} | 53 + 28 files changed, 4931 insertions(+), 21 deletions(-) create mode 100644 core/contracts/attestationcollector/attestationcollector.abigen.go create mode 100644 core/contracts/attestationcollector/attestationcollector.contractinfo.json create mode 100644 core/contracts/attestationcollector/attestationcollector.metadata.go create mode 100644 core/contracts/attestationcollector/generate.go create mode 100644 core/contracts/attestationcollector/helpers.go create mode 100644 core/contracts/test/attestationharness/attestationharness.abigen.go create mode 100644 core/contracts/test/attestationharness/attestationharness.contractinfo.json create mode 100644 core/contracts/test/attestationharness/attestationharness.metadata.go create mode 100644 core/contracts/test/attestationharness/generate.go create mode 100644 core/contracts/test/attestationharness/helpers.go create mode 100644 core/domains/evm/collector.go create mode 100644 core/domains/evm/collector_test.go create mode 100644 core/types/attestation.go rename core/types/{message_test.go => parity_test.go} (68%) diff --git a/core/agents/updater/producer.go b/core/agents/updater/producer.go index 033778e640..c315ada919 100644 --- a/core/agents/updater/producer.go +++ b/core/agents/updater/producer.go @@ -168,3 +168,16 @@ func HashUpdate(update types.Update) ([32]byte, error) { signedHash := crypto.Keccak256Hash([]byte("\x19Ethereum Signed Message:\n32"), hashedDigest.Bytes()) return signedHash, nil } + +// HashAttestation hashes an attestation. +func HashAttestation(attestation types.Attestation) ([32]byte, error) { + encodedAttestation, err := types.EncodeAttestation(attestation) + if err != nil { + return [32]byte{}, fmt.Errorf("could not encode attestation: %w", err) + } + + hashedDigest := crypto.Keccak256Hash(encodedAttestation) + + signedHash := crypto.Keccak256Hash([]byte("\x19Ethereum Signed Message:\n32"), hashedDigest.Bytes()) + return signedHash, nil +} diff --git a/core/contracts/attestationcollector/attestationcollector.abigen.go b/core/contracts/attestationcollector/attestationcollector.abigen.go new file mode 100644 index 0000000000..2c4ac83623 --- /dev/null +++ b/core/contracts/attestationcollector/attestationcollector.abigen.go @@ -0,0 +1,3443 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package attestationcollector + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// AddressUpgradeableMetaData contains all meta data concerning the AddressUpgradeable contract. +var AddressUpgradeableMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220727ce1433873ec66526437ba322468859e5e44f570d4021a0275f8035716a14664736f6c634300080d0033", +} + +// AddressUpgradeableABI is the input ABI used to generate the binding from. +// Deprecated: Use AddressUpgradeableMetaData.ABI instead. +var AddressUpgradeableABI = AddressUpgradeableMetaData.ABI + +// AddressUpgradeableBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AddressUpgradeableMetaData.Bin instead. +var AddressUpgradeableBin = AddressUpgradeableMetaData.Bin + +// DeployAddressUpgradeable deploys a new Ethereum contract, binding an instance of AddressUpgradeable to it. +func DeployAddressUpgradeable(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *AddressUpgradeable, error) { + parsed, err := AddressUpgradeableMetaData.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(AddressUpgradeableBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &AddressUpgradeable{AddressUpgradeableCaller: AddressUpgradeableCaller{contract: contract}, AddressUpgradeableTransactor: AddressUpgradeableTransactor{contract: contract}, AddressUpgradeableFilterer: AddressUpgradeableFilterer{contract: contract}}, nil +} + +// AddressUpgradeable is an auto generated Go binding around an Ethereum contract. +type AddressUpgradeable struct { + AddressUpgradeableCaller // Read-only binding to the contract + AddressUpgradeableTransactor // Write-only binding to the contract + AddressUpgradeableFilterer // Log filterer for contract events +} + +// AddressUpgradeableCaller is an auto generated read-only Go binding around an Ethereum contract. +type AddressUpgradeableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AddressUpgradeableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AddressUpgradeableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AddressUpgradeableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AddressUpgradeableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AddressUpgradeableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AddressUpgradeableSession struct { + Contract *AddressUpgradeable // 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 +} + +// AddressUpgradeableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AddressUpgradeableCallerSession struct { + Contract *AddressUpgradeableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AddressUpgradeableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AddressUpgradeableTransactorSession struct { + Contract *AddressUpgradeableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressUpgradeableRaw is an auto generated low-level Go binding around an Ethereum contract. +type AddressUpgradeableRaw struct { + Contract *AddressUpgradeable // Generic contract binding to access the raw methods on +} + +// AddressUpgradeableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AddressUpgradeableCallerRaw struct { + Contract *AddressUpgradeableCaller // Generic read-only contract binding to access the raw methods on +} + +// AddressUpgradeableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AddressUpgradeableTransactorRaw struct { + Contract *AddressUpgradeableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAddressUpgradeable creates a new instance of AddressUpgradeable, bound to a specific deployed contract. +func NewAddressUpgradeable(address common.Address, backend bind.ContractBackend) (*AddressUpgradeable, error) { + contract, err := bindAddressUpgradeable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AddressUpgradeable{AddressUpgradeableCaller: AddressUpgradeableCaller{contract: contract}, AddressUpgradeableTransactor: AddressUpgradeableTransactor{contract: contract}, AddressUpgradeableFilterer: AddressUpgradeableFilterer{contract: contract}}, nil +} + +// NewAddressUpgradeableCaller creates a new read-only instance of AddressUpgradeable, bound to a specific deployed contract. +func NewAddressUpgradeableCaller(address common.Address, caller bind.ContractCaller) (*AddressUpgradeableCaller, error) { + contract, err := bindAddressUpgradeable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AddressUpgradeableCaller{contract: contract}, nil +} + +// NewAddressUpgradeableTransactor creates a new write-only instance of AddressUpgradeable, bound to a specific deployed contract. +func NewAddressUpgradeableTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressUpgradeableTransactor, error) { + contract, err := bindAddressUpgradeable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AddressUpgradeableTransactor{contract: contract}, nil +} + +// NewAddressUpgradeableFilterer creates a new log filterer instance of AddressUpgradeable, bound to a specific deployed contract. +func NewAddressUpgradeableFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressUpgradeableFilterer, error) { + contract, err := bindAddressUpgradeable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AddressUpgradeableFilterer{contract: contract}, nil +} + +// bindAddressUpgradeable binds a generic wrapper to an already deployed contract. +func bindAddressUpgradeable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AddressUpgradeableABI)) + 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 (_AddressUpgradeable *AddressUpgradeableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AddressUpgradeable.Contract.AddressUpgradeableCaller.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 (_AddressUpgradeable *AddressUpgradeableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AddressUpgradeable.Contract.AddressUpgradeableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AddressUpgradeable *AddressUpgradeableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AddressUpgradeable.Contract.AddressUpgradeableTransactor.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 (_AddressUpgradeable *AddressUpgradeableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AddressUpgradeable.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 (_AddressUpgradeable *AddressUpgradeableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AddressUpgradeable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AddressUpgradeable *AddressUpgradeableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AddressUpgradeable.Contract.contract.Transact(opts, method, params...) +} + +// AttestationMetaData contains all meta data concerning the Attestation contract. +var AttestationMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207ee88204e5693e1a9483df6e58ee243c872e2fdc769dad2c6329deea804a72fe64736f6c634300080d0033", +} + +// AttestationABI is the input ABI used to generate the binding from. +// Deprecated: Use AttestationMetaData.ABI instead. +var AttestationABI = AttestationMetaData.ABI + +// AttestationBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AttestationMetaData.Bin instead. +var AttestationBin = AttestationMetaData.Bin + +// DeployAttestation deploys a new Ethereum contract, binding an instance of Attestation to it. +func DeployAttestation(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Attestation, error) { + parsed, err := AttestationMetaData.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(AttestationBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Attestation{AttestationCaller: AttestationCaller{contract: contract}, AttestationTransactor: AttestationTransactor{contract: contract}, AttestationFilterer: AttestationFilterer{contract: contract}}, nil +} + +// Attestation is an auto generated Go binding around an Ethereum contract. +type Attestation struct { + AttestationCaller // Read-only binding to the contract + AttestationTransactor // Write-only binding to the contract + AttestationFilterer // Log filterer for contract events +} + +// AttestationCaller is an auto generated read-only Go binding around an Ethereum contract. +type AttestationCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AttestationTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AttestationFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AttestationSession struct { + Contract *Attestation // 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 +} + +// AttestationCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AttestationCallerSession struct { + Contract *AttestationCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AttestationTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AttestationTransactorSession struct { + Contract *AttestationTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AttestationRaw is an auto generated low-level Go binding around an Ethereum contract. +type AttestationRaw struct { + Contract *Attestation // Generic contract binding to access the raw methods on +} + +// AttestationCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AttestationCallerRaw struct { + Contract *AttestationCaller // Generic read-only contract binding to access the raw methods on +} + +// AttestationTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AttestationTransactorRaw struct { + Contract *AttestationTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAttestation creates a new instance of Attestation, bound to a specific deployed contract. +func NewAttestation(address common.Address, backend bind.ContractBackend) (*Attestation, error) { + contract, err := bindAttestation(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Attestation{AttestationCaller: AttestationCaller{contract: contract}, AttestationTransactor: AttestationTransactor{contract: contract}, AttestationFilterer: AttestationFilterer{contract: contract}}, nil +} + +// NewAttestationCaller creates a new read-only instance of Attestation, bound to a specific deployed contract. +func NewAttestationCaller(address common.Address, caller bind.ContractCaller) (*AttestationCaller, error) { + contract, err := bindAttestation(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AttestationCaller{contract: contract}, nil +} + +// NewAttestationTransactor creates a new write-only instance of Attestation, bound to a specific deployed contract. +func NewAttestationTransactor(address common.Address, transactor bind.ContractTransactor) (*AttestationTransactor, error) { + contract, err := bindAttestation(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AttestationTransactor{contract: contract}, nil +} + +// NewAttestationFilterer creates a new log filterer instance of Attestation, bound to a specific deployed contract. +func NewAttestationFilterer(address common.Address, filterer bind.ContractFilterer) (*AttestationFilterer, error) { + contract, err := bindAttestation(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AttestationFilterer{contract: contract}, nil +} + +// bindAttestation binds a generic wrapper to an already deployed contract. +func bindAttestation(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AttestationABI)) + 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 (_Attestation *AttestationRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Attestation.Contract.AttestationCaller.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 (_Attestation *AttestationRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Attestation.Contract.AttestationTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Attestation *AttestationRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Attestation.Contract.AttestationTransactor.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 (_Attestation *AttestationCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Attestation.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 (_Attestation *AttestationTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Attestation.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Attestation *AttestationTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Attestation.Contract.contract.Transact(opts, method, params...) +} + +// AttestationCollectorMetaData contains all meta data concerning the AttestationCollector contract. +var AttestationCollectorMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attestation\",\"type\":\"bytes\"}],\"name\":\"AttestationSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"}],\"name\":\"UpdaterAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"}],\"name\":\"UpdaterRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"addUpdater\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isUpdater\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"removeUpdater\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"submitAttestation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "58fb6b36": "addUpdater(uint32,address)", + "8129fc1c": "initialize()", + "021780f1": "isUpdater(uint32,address)", + "8da5cb5b": "owner()", + "cefdf149": "removeUpdater(uint32,address)", + "715018a6": "renounceOwnership()", + "ea3dd1db": "submitAttestation(address,bytes)", + "f2fde38b": "transferOwnership(address)", + }, + Bin: "0x608060405234801561001057600080fd5b50611c19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100f5578063cefdf1491461011d578063ea3dd1db14610130578063f2fde38b1461014357600080fd5b8063021780f11461008d57806358fb6b36146100d0578063715018a6146100e55780638129fc1c146100ed575b600080fd5b6100bb61009b3660046117e7565b609760209081526000928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b6100e36100de3660046117e7565b610156565b005b6100e36101d0565b6100e3610243565b60655460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c7565b6100e361012b3660046117e7565b6102f2565b6100e361013e366004611854565b610363565b6100e3610151366004611934565b6103c4565b60655473ffffffffffffffffffffffffffffffffffffffff1633146101c25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6101cc82826104bd565b5050565b60655473ffffffffffffffffffffffffffffffffffffffff1633146102375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b6102416000610591565b565b600061024f6001610608565b9050801561028457603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61028c610761565b80156102ef57603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60655473ffffffffffffffffffffffffffffffffffffffff1633146103595760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b6101cc82826107e7565b600061036f83836108b1565b90508273ffffffffffffffffffffffffffffffffffffffff167f786431104fc3c4b19da7bae78f422f46b9c07528276a2ee430e8569cb8705f14836040516103b791906119ba565b60405180910390a2505050565b60655473ffffffffffffffffffffffffffffffffffffffff16331461042b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b73ffffffffffffffffffffffffffffffffffffffff81166104b45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101b9565b6102ef81610591565b63ffffffff8216600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166101cc5763ffffffff8216600081815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055519182527f7a3a28cc7dcc3a542ba3484ee58c7789cf2aa2c18993c7979e129e400719acf291015b60405180910390a25050565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b603254600090610100900460ff16156106a7578160ff16600114801561062d5750303b155b61069f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101b9565b506000919050565b60325460ff8084169116106107245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101b9565b50603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b603254610100900460ff166107de5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101b9565b61024133610591565b63ffffffff8216600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156101cc5763ffffffff8216600081815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055519182527f68013ab89ba87f3a94d66c35bd0ff2578e0417b8df4cb289a9132d90febae91f9101610585565b60006108bd82826109f6565b905060286bffffffffffffffffffffffff601883901c16116109215760405162461bcd60e51b815260206004820152601260248201527f4e6f7420616e206174746573746174696f6e000000000000000000000000000060448201526064016101b9565b6109568361093462ffffff198416610a1a565b61095161094662ffffff198616610a2f565b62ffffff1916610a62565b610ab5565b6109a461096862ffffff198316610bab565b63ffffffff16600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816845290915290205460ff1690565b6109f05760405162461bcd60e51b815260206004820152601860248201527f5369676e6572206973206e6f7420616e2075706461746572000000000000000060448201526064016101b9565b92915050565b815160009060208401610a1164ffffffffff85168284610bbf565b95945050505050565b60006109f062ffffff19831682602881610c09565b60006109f06028610a5281601886901c6bffffffffffffffffffffffff166119fc565b62ffffff19851691906000610c09565b6060600080610a7f8460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506040519150819250610aa48483602001610c8f565b508181016020016040529052919050565b6000610ac662ffffff198416610e34565b9050610b1f816040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90508373ffffffffffffffffffffffffffffffffffffffff16610b428284610e91565b73ffffffffffffffffffffffffffffffffffffffff1614610ba55760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e617475726500000000000000000000000000000060448201526064016101b9565b50505050565b60006109f062ffffff198316826004610eb5565b600080610bcc8385611a13565b9050604051811115610bdc575060005b80600003610bf15762ffffff19915050610c02565b5050606083811b8317901b811760181b5b9392505050565b600080610c248660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050610c3d86610ee5565b84610c488784611a13565b610c529190611a13565b1115610c655762ffffff19915050610c87565b610c6f8582611a13565b9050610c838364ffffffffff168286610bbf565b9150505b949350505050565b600062ffffff1980841603610d0c5760405162461bcd60e51b815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201527f657220646572656600000000000000000000000000000000000000000000000060648201526084016101b9565b610d1583610f2d565b610d875760405162461bcd60e51b815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201527f696e74657220646572656600000000000000000000000000000000000000000060648201526084016101b9565b6000610da18460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000610dcb8560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000604051905084811115610df05760206060fd5b8285848460045afa50610e2a610e068760d81c90565b70ffffffffff000000000000000000000000606091821b168717901b841760181b90565b9695505050505050565b600080610e4f8360781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000610e798460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169091209392505050565b6000806000610ea08585610f6a565b91509150610ead81610fd8565b509392505050565b6000610ec2826020611a2b565b610ecd906008611a4e565b60ff16610edb8585856111c4565b901c949350505050565b6000610eff8260181c6bffffffffffffffffffffffff1690565b610f178360781c6bffffffffffffffffffffffff1690565b016bffffffffffffffffffffffff169050919050565b6000610f398260d81c90565b64ffffffffff1664ffffffffff03610f5357506000919050565b6000610f5e83610ee5565b60405110199392505050565b6000808251604103610fa05760208301516040840151606085015160001a610f9487828585611382565b94509450505050610fd1565b8251604003610fc95760208301516040840151610fbe86838361149a565b935093505050610fd1565b506000905060025b9250929050565b6000816004811115610fec57610fec611a77565b03610ff45750565b600181600481111561100857611008611a77565b036110555760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016101b9565b600281600481111561106957611069611a77565b036110b65760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016101b9565b60038160048111156110ca576110ca611a77565b0361113d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016101b9565b600481600481111561115157611151611a77565b036102ef5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016101b9565b60008160ff166000036111d957506000610c02565b6111f18460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1661120c60ff841685611a13565b11156112845761126b61122d8560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166112538660181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16858560ff166114ec565b60405162461bcd60e51b81526004016101b991906119ba565b60208260ff1611156112fe5760405162461bcd60e51b815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e20333220627974657300000000000060648201526084016101b9565b60088202600061131c8660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060007f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84011d91909501511695945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156113b95750600090506003611491565b8460ff16601b141580156113d157508460ff16601c14155b156113e25750600090506004611491565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611436573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661148a57600060019250925050611491565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316816114d060ff86901c601b611a13565b90506114de87828885611382565b935093505050935093915050565b606060006114f98661155a565b91505060006115078661155a565b91505060006115158661155a565b91505060006115238661155a565b9150508383838360405160200161153d9493929190611aa6565b604051602081830303815290604052945050505050949350505050565b600080601f5b600f8160ff1611156115cd576000611579826008611a4e565b60ff1685901c905061158a81611644565b61ffff16841793508160ff166010146115a557601084901b93505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611560565b50600f5b60ff8160ff16101561163e5760006115ea826008611a4e565b60ff1685901c90506115fb81611644565b61ffff16831792508160ff1660001461161657601083901b92505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016115d1565b50915091565b600061165660048360ff16901c611676565b60ff1661ffff919091161760081b61166d82611676565b60ff1617919050565b600060f08083179060ff821690036116915750603092915050565b8060ff1660f1036116a55750603192915050565b8060ff1660f2036116b95750603292915050565b8060ff1660f3036116cd5750603392915050565b8060ff1660f4036116e15750603492915050565b8060ff1660f5036116f55750603592915050565b8060ff1660f6036117095750603692915050565b8060ff1660f70361171d5750603792915050565b8060ff1660f8036117315750603892915050565b8060ff1660f9036117455750603992915050565b8060ff1660fa036117595750606192915050565b8060ff1660fb0361176d5750606292915050565b8060ff1660fc036117815750606392915050565b8060ff1660fd036117955750606492915050565b8060ff1660fe036117a95750606592915050565b8060ff1660ff036117bd5750606692915050565b50919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461075c57600080fd5b600080604083850312156117fa57600080fd5b823563ffffffff8116811461180e57600080fd5b915061181c602084016117c3565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561186757600080fd5b611870836117c3565b9150602083013567ffffffffffffffff8082111561188d57600080fd5b818501915085601f8301126118a157600080fd5b8135818111156118b3576118b3611825565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156118f9576118f9611825565b8160405282815288602084870101111561191257600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60006020828403121561194657600080fd5b610c02826117c3565b6000815180845260005b8181101561197557602081850181015186830182015201611959565b81811115611987576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610c02602083018461194f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a0e57611a0e6119cd565b500390565b60008219821115611a2657611a266119cd565b500190565b600060ff821660ff841680821015611a4557611a456119cd565b90039392505050565b600060ff821660ff84168160ff0481118215151615611a6f57611a6f6119cd565b029392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f54797065644d656d566965772f696e646578202d204f76657272616e2074686581527f20766965772e20536c696365206973206174203078000000000000000000000060208201527fffffffffffff000000000000000000000000000000000000000000000000000060d086811b821660358401527f2077697468206c656e6774682030780000000000000000000000000000000000603b840181905286821b8316604a8501527f2e20417474656d7074656420746f20696e646578206174206f6666736574203060508501527f7800000000000000000000000000000000000000000000000000000000000000607085015285821b83166071850152607784015283901b1660868201527f2e00000000000000000000000000000000000000000000000000000000000000608c8201526000608d8201610e2a56fea2646970667358221220520cdd88203931370e5cb8bbcf5094413443157a6e50223ddc347706587db5c164736f6c634300080d0033", +} + +// AttestationCollectorABI is the input ABI used to generate the binding from. +// Deprecated: Use AttestationCollectorMetaData.ABI instead. +var AttestationCollectorABI = AttestationCollectorMetaData.ABI + +// Deprecated: Use AttestationCollectorMetaData.Sigs instead. +// AttestationCollectorFuncSigs maps the 4-byte function signature to its string representation. +var AttestationCollectorFuncSigs = AttestationCollectorMetaData.Sigs + +// AttestationCollectorBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AttestationCollectorMetaData.Bin instead. +var AttestationCollectorBin = AttestationCollectorMetaData.Bin + +// DeployAttestationCollector deploys a new Ethereum contract, binding an instance of AttestationCollector to it. +func DeployAttestationCollector(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *AttestationCollector, error) { + parsed, err := AttestationCollectorMetaData.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(AttestationCollectorBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &AttestationCollector{AttestationCollectorCaller: AttestationCollectorCaller{contract: contract}, AttestationCollectorTransactor: AttestationCollectorTransactor{contract: contract}, AttestationCollectorFilterer: AttestationCollectorFilterer{contract: contract}}, nil +} + +// AttestationCollector is an auto generated Go binding around an Ethereum contract. +type AttestationCollector struct { + AttestationCollectorCaller // Read-only binding to the contract + AttestationCollectorTransactor // Write-only binding to the contract + AttestationCollectorFilterer // Log filterer for contract events +} + +// AttestationCollectorCaller is an auto generated read-only Go binding around an Ethereum contract. +type AttestationCollectorCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationCollectorTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AttestationCollectorTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationCollectorFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AttestationCollectorFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationCollectorSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AttestationCollectorSession struct { + Contract *AttestationCollector // 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 +} + +// AttestationCollectorCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AttestationCollectorCallerSession struct { + Contract *AttestationCollectorCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AttestationCollectorTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AttestationCollectorTransactorSession struct { + Contract *AttestationCollectorTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AttestationCollectorRaw is an auto generated low-level Go binding around an Ethereum contract. +type AttestationCollectorRaw struct { + Contract *AttestationCollector // Generic contract binding to access the raw methods on +} + +// AttestationCollectorCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AttestationCollectorCallerRaw struct { + Contract *AttestationCollectorCaller // Generic read-only contract binding to access the raw methods on +} + +// AttestationCollectorTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AttestationCollectorTransactorRaw struct { + Contract *AttestationCollectorTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAttestationCollector creates a new instance of AttestationCollector, bound to a specific deployed contract. +func NewAttestationCollector(address common.Address, backend bind.ContractBackend) (*AttestationCollector, error) { + contract, err := bindAttestationCollector(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AttestationCollector{AttestationCollectorCaller: AttestationCollectorCaller{contract: contract}, AttestationCollectorTransactor: AttestationCollectorTransactor{contract: contract}, AttestationCollectorFilterer: AttestationCollectorFilterer{contract: contract}}, nil +} + +// NewAttestationCollectorCaller creates a new read-only instance of AttestationCollector, bound to a specific deployed contract. +func NewAttestationCollectorCaller(address common.Address, caller bind.ContractCaller) (*AttestationCollectorCaller, error) { + contract, err := bindAttestationCollector(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AttestationCollectorCaller{contract: contract}, nil +} + +// NewAttestationCollectorTransactor creates a new write-only instance of AttestationCollector, bound to a specific deployed contract. +func NewAttestationCollectorTransactor(address common.Address, transactor bind.ContractTransactor) (*AttestationCollectorTransactor, error) { + contract, err := bindAttestationCollector(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AttestationCollectorTransactor{contract: contract}, nil +} + +// NewAttestationCollectorFilterer creates a new log filterer instance of AttestationCollector, bound to a specific deployed contract. +func NewAttestationCollectorFilterer(address common.Address, filterer bind.ContractFilterer) (*AttestationCollectorFilterer, error) { + contract, err := bindAttestationCollector(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AttestationCollectorFilterer{contract: contract}, nil +} + +// bindAttestationCollector binds a generic wrapper to an already deployed contract. +func bindAttestationCollector(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AttestationCollectorABI)) + 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 (_AttestationCollector *AttestationCollectorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AttestationCollector.Contract.AttestationCollectorCaller.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 (_AttestationCollector *AttestationCollectorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AttestationCollector.Contract.AttestationCollectorTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AttestationCollector *AttestationCollectorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AttestationCollector.Contract.AttestationCollectorTransactor.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 (_AttestationCollector *AttestationCollectorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AttestationCollector.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 (_AttestationCollector *AttestationCollectorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AttestationCollector.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AttestationCollector *AttestationCollectorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AttestationCollector.Contract.contract.Transact(opts, method, params...) +} + +// IsUpdater is a free data retrieval call binding the contract method 0x021780f1. +// +// Solidity: function isUpdater(uint32 , address ) view returns(bool) +func (_AttestationCollector *AttestationCollectorCaller) IsUpdater(opts *bind.CallOpts, arg0 uint32, arg1 common.Address) (bool, error) { + var out []interface{} + err := _AttestationCollector.contract.Call(opts, &out, "isUpdater", arg0, arg1) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsUpdater is a free data retrieval call binding the contract method 0x021780f1. +// +// Solidity: function isUpdater(uint32 , address ) view returns(bool) +func (_AttestationCollector *AttestationCollectorSession) IsUpdater(arg0 uint32, arg1 common.Address) (bool, error) { + return _AttestationCollector.Contract.IsUpdater(&_AttestationCollector.CallOpts, arg0, arg1) +} + +// IsUpdater is a free data retrieval call binding the contract method 0x021780f1. +// +// Solidity: function isUpdater(uint32 , address ) view returns(bool) +func (_AttestationCollector *AttestationCollectorCallerSession) IsUpdater(arg0 uint32, arg1 common.Address) (bool, error) { + return _AttestationCollector.Contract.IsUpdater(&_AttestationCollector.CallOpts, arg0, arg1) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_AttestationCollector *AttestationCollectorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AttestationCollector.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 (_AttestationCollector *AttestationCollectorSession) Owner() (common.Address, error) { + return _AttestationCollector.Contract.Owner(&_AttestationCollector.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_AttestationCollector *AttestationCollectorCallerSession) Owner() (common.Address, error) { + return _AttestationCollector.Contract.Owner(&_AttestationCollector.CallOpts) +} + +// AddUpdater is a paid mutator transaction binding the contract method 0x58fb6b36. +// +// Solidity: function addUpdater(uint32 _domain, address _updater) returns() +func (_AttestationCollector *AttestationCollectorTransactor) AddUpdater(opts *bind.TransactOpts, _domain uint32, _updater common.Address) (*types.Transaction, error) { + return _AttestationCollector.contract.Transact(opts, "addUpdater", _domain, _updater) +} + +// AddUpdater is a paid mutator transaction binding the contract method 0x58fb6b36. +// +// Solidity: function addUpdater(uint32 _domain, address _updater) returns() +func (_AttestationCollector *AttestationCollectorSession) AddUpdater(_domain uint32, _updater common.Address) (*types.Transaction, error) { + return _AttestationCollector.Contract.AddUpdater(&_AttestationCollector.TransactOpts, _domain, _updater) +} + +// AddUpdater is a paid mutator transaction binding the contract method 0x58fb6b36. +// +// Solidity: function addUpdater(uint32 _domain, address _updater) returns() +func (_AttestationCollector *AttestationCollectorTransactorSession) AddUpdater(_domain uint32, _updater common.Address) (*types.Transaction, error) { + return _AttestationCollector.Contract.AddUpdater(&_AttestationCollector.TransactOpts, _domain, _updater) +} + +// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. +// +// Solidity: function initialize() returns() +func (_AttestationCollector *AttestationCollectorTransactor) Initialize(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AttestationCollector.contract.Transact(opts, "initialize") +} + +// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. +// +// Solidity: function initialize() returns() +func (_AttestationCollector *AttestationCollectorSession) Initialize() (*types.Transaction, error) { + return _AttestationCollector.Contract.Initialize(&_AttestationCollector.TransactOpts) +} + +// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. +// +// Solidity: function initialize() returns() +func (_AttestationCollector *AttestationCollectorTransactorSession) Initialize() (*types.Transaction, error) { + return _AttestationCollector.Contract.Initialize(&_AttestationCollector.TransactOpts) +} + +// RemoveUpdater is a paid mutator transaction binding the contract method 0xcefdf149. +// +// Solidity: function removeUpdater(uint32 _domain, address _updater) returns() +func (_AttestationCollector *AttestationCollectorTransactor) RemoveUpdater(opts *bind.TransactOpts, _domain uint32, _updater common.Address) (*types.Transaction, error) { + return _AttestationCollector.contract.Transact(opts, "removeUpdater", _domain, _updater) +} + +// RemoveUpdater is a paid mutator transaction binding the contract method 0xcefdf149. +// +// Solidity: function removeUpdater(uint32 _domain, address _updater) returns() +func (_AttestationCollector *AttestationCollectorSession) RemoveUpdater(_domain uint32, _updater common.Address) (*types.Transaction, error) { + return _AttestationCollector.Contract.RemoveUpdater(&_AttestationCollector.TransactOpts, _domain, _updater) +} + +// RemoveUpdater is a paid mutator transaction binding the contract method 0xcefdf149. +// +// Solidity: function removeUpdater(uint32 _domain, address _updater) returns() +func (_AttestationCollector *AttestationCollectorTransactorSession) RemoveUpdater(_domain uint32, _updater common.Address) (*types.Transaction, error) { + return _AttestationCollector.Contract.RemoveUpdater(&_AttestationCollector.TransactOpts, _domain, _updater) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_AttestationCollector *AttestationCollectorTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AttestationCollector.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_AttestationCollector *AttestationCollectorSession) RenounceOwnership() (*types.Transaction, error) { + return _AttestationCollector.Contract.RenounceOwnership(&_AttestationCollector.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_AttestationCollector *AttestationCollectorTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _AttestationCollector.Contract.RenounceOwnership(&_AttestationCollector.TransactOpts) +} + +// SubmitAttestation is a paid mutator transaction binding the contract method 0xea3dd1db. +// +// Solidity: function submitAttestation(address _updater, bytes _attestation) returns() +func (_AttestationCollector *AttestationCollectorTransactor) SubmitAttestation(opts *bind.TransactOpts, _updater common.Address, _attestation []byte) (*types.Transaction, error) { + return _AttestationCollector.contract.Transact(opts, "submitAttestation", _updater, _attestation) +} + +// SubmitAttestation is a paid mutator transaction binding the contract method 0xea3dd1db. +// +// Solidity: function submitAttestation(address _updater, bytes _attestation) returns() +func (_AttestationCollector *AttestationCollectorSession) SubmitAttestation(_updater common.Address, _attestation []byte) (*types.Transaction, error) { + return _AttestationCollector.Contract.SubmitAttestation(&_AttestationCollector.TransactOpts, _updater, _attestation) +} + +// SubmitAttestation is a paid mutator transaction binding the contract method 0xea3dd1db. +// +// Solidity: function submitAttestation(address _updater, bytes _attestation) returns() +func (_AttestationCollector *AttestationCollectorTransactorSession) SubmitAttestation(_updater common.Address, _attestation []byte) (*types.Transaction, error) { + return _AttestationCollector.Contract.SubmitAttestation(&_AttestationCollector.TransactOpts, _updater, _attestation) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_AttestationCollector *AttestationCollectorTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _AttestationCollector.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_AttestationCollector *AttestationCollectorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _AttestationCollector.Contract.TransferOwnership(&_AttestationCollector.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_AttestationCollector *AttestationCollectorTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _AttestationCollector.Contract.TransferOwnership(&_AttestationCollector.TransactOpts, newOwner) +} + +// AttestationCollectorAttestationSubmittedIterator is returned from FilterAttestationSubmitted and is used to iterate over the raw logs and unpacked data for AttestationSubmitted events raised by the AttestationCollector contract. +type AttestationCollectorAttestationSubmittedIterator struct { + Event *AttestationCollectorAttestationSubmitted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AttestationCollectorAttestationSubmittedIterator) 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(AttestationCollectorAttestationSubmitted) + 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(AttestationCollectorAttestationSubmitted) + 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 *AttestationCollectorAttestationSubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AttestationCollectorAttestationSubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// AttestationCollectorAttestationSubmitted represents a AttestationSubmitted event raised by the AttestationCollector contract. +type AttestationCollectorAttestationSubmitted struct { + Updater common.Address + Attestation []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAttestationSubmitted is a free log retrieval operation binding the contract event 0x786431104fc3c4b19da7bae78f422f46b9c07528276a2ee430e8569cb8705f14. +// +// Solidity: event AttestationSubmitted(address indexed updater, bytes attestation) +func (_AttestationCollector *AttestationCollectorFilterer) FilterAttestationSubmitted(opts *bind.FilterOpts, updater []common.Address) (*AttestationCollectorAttestationSubmittedIterator, error) { + + var updaterRule []interface{} + for _, updaterItem := range updater { + updaterRule = append(updaterRule, updaterItem) + } + + logs, sub, err := _AttestationCollector.contract.FilterLogs(opts, "AttestationSubmitted", updaterRule) + if err != nil { + return nil, err + } + return &AttestationCollectorAttestationSubmittedIterator{contract: _AttestationCollector.contract, event: "AttestationSubmitted", logs: logs, sub: sub}, nil +} + +// WatchAttestationSubmitted is a free log subscription operation binding the contract event 0x786431104fc3c4b19da7bae78f422f46b9c07528276a2ee430e8569cb8705f14. +// +// Solidity: event AttestationSubmitted(address indexed updater, bytes attestation) +func (_AttestationCollector *AttestationCollectorFilterer) WatchAttestationSubmitted(opts *bind.WatchOpts, sink chan<- *AttestationCollectorAttestationSubmitted, updater []common.Address) (event.Subscription, error) { + + var updaterRule []interface{} + for _, updaterItem := range updater { + updaterRule = append(updaterRule, updaterItem) + } + + logs, sub, err := _AttestationCollector.contract.WatchLogs(opts, "AttestationSubmitted", updaterRule) + 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(AttestationCollectorAttestationSubmitted) + if err := _AttestationCollector.contract.UnpackLog(event, "AttestationSubmitted", 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 +} + +// ParseAttestationSubmitted is a log parse operation binding the contract event 0x786431104fc3c4b19da7bae78f422f46b9c07528276a2ee430e8569cb8705f14. +// +// Solidity: event AttestationSubmitted(address indexed updater, bytes attestation) +func (_AttestationCollector *AttestationCollectorFilterer) ParseAttestationSubmitted(log types.Log) (*AttestationCollectorAttestationSubmitted, error) { + event := new(AttestationCollectorAttestationSubmitted) + if err := _AttestationCollector.contract.UnpackLog(event, "AttestationSubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// AttestationCollectorInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the AttestationCollector contract. +type AttestationCollectorInitializedIterator struct { + Event *AttestationCollectorInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AttestationCollectorInitializedIterator) 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(AttestationCollectorInitialized) + 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(AttestationCollectorInitialized) + 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 *AttestationCollectorInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AttestationCollectorInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// AttestationCollectorInitialized represents a Initialized event raised by the AttestationCollector contract. +type AttestationCollectorInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_AttestationCollector *AttestationCollectorFilterer) FilterInitialized(opts *bind.FilterOpts) (*AttestationCollectorInitializedIterator, error) { + + logs, sub, err := _AttestationCollector.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &AttestationCollectorInitializedIterator{contract: _AttestationCollector.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_AttestationCollector *AttestationCollectorFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *AttestationCollectorInitialized) (event.Subscription, error) { + + logs, sub, err := _AttestationCollector.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(AttestationCollectorInitialized) + if err := _AttestationCollector.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 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_AttestationCollector *AttestationCollectorFilterer) ParseInitialized(log types.Log) (*AttestationCollectorInitialized, error) { + event := new(AttestationCollectorInitialized) + if err := _AttestationCollector.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// AttestationCollectorOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the AttestationCollector contract. +type AttestationCollectorOwnershipTransferredIterator struct { + Event *AttestationCollectorOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AttestationCollectorOwnershipTransferredIterator) 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(AttestationCollectorOwnershipTransferred) + 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(AttestationCollectorOwnershipTransferred) + 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 *AttestationCollectorOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AttestationCollectorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// AttestationCollectorOwnershipTransferred represents a OwnershipTransferred event raised by the AttestationCollector contract. +type AttestationCollectorOwnershipTransferred 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 (_AttestationCollector *AttestationCollectorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*AttestationCollectorOwnershipTransferredIterator, 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 := _AttestationCollector.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &AttestationCollectorOwnershipTransferredIterator{contract: _AttestationCollector.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 (_AttestationCollector *AttestationCollectorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AttestationCollectorOwnershipTransferred, 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 := _AttestationCollector.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(AttestationCollectorOwnershipTransferred) + if err := _AttestationCollector.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 (_AttestationCollector *AttestationCollectorFilterer) ParseOwnershipTransferred(log types.Log) (*AttestationCollectorOwnershipTransferred, error) { + event := new(AttestationCollectorOwnershipTransferred) + if err := _AttestationCollector.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// AttestationCollectorUpdaterAddedIterator is returned from FilterUpdaterAdded and is used to iterate over the raw logs and unpacked data for UpdaterAdded events raised by the AttestationCollector contract. +type AttestationCollectorUpdaterAddedIterator struct { + Event *AttestationCollectorUpdaterAdded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AttestationCollectorUpdaterAddedIterator) 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(AttestationCollectorUpdaterAdded) + 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(AttestationCollectorUpdaterAdded) + 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 *AttestationCollectorUpdaterAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AttestationCollectorUpdaterAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// AttestationCollectorUpdaterAdded represents a UpdaterAdded event raised by the AttestationCollector contract. +type AttestationCollectorUpdaterAdded struct { + Domain uint32 + Updater common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdaterAdded is a free log retrieval operation binding the contract event 0x7a3a28cc7dcc3a542ba3484ee58c7789cf2aa2c18993c7979e129e400719acf2. +// +// Solidity: event UpdaterAdded(uint32 indexed domain, address updater) +func (_AttestationCollector *AttestationCollectorFilterer) FilterUpdaterAdded(opts *bind.FilterOpts, domain []uint32) (*AttestationCollectorUpdaterAddedIterator, error) { + + var domainRule []interface{} + for _, domainItem := range domain { + domainRule = append(domainRule, domainItem) + } + + logs, sub, err := _AttestationCollector.contract.FilterLogs(opts, "UpdaterAdded", domainRule) + if err != nil { + return nil, err + } + return &AttestationCollectorUpdaterAddedIterator{contract: _AttestationCollector.contract, event: "UpdaterAdded", logs: logs, sub: sub}, nil +} + +// WatchUpdaterAdded is a free log subscription operation binding the contract event 0x7a3a28cc7dcc3a542ba3484ee58c7789cf2aa2c18993c7979e129e400719acf2. +// +// Solidity: event UpdaterAdded(uint32 indexed domain, address updater) +func (_AttestationCollector *AttestationCollectorFilterer) WatchUpdaterAdded(opts *bind.WatchOpts, sink chan<- *AttestationCollectorUpdaterAdded, domain []uint32) (event.Subscription, error) { + + var domainRule []interface{} + for _, domainItem := range domain { + domainRule = append(domainRule, domainItem) + } + + logs, sub, err := _AttestationCollector.contract.WatchLogs(opts, "UpdaterAdded", domainRule) + 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(AttestationCollectorUpdaterAdded) + if err := _AttestationCollector.contract.UnpackLog(event, "UpdaterAdded", 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 +} + +// ParseUpdaterAdded is a log parse operation binding the contract event 0x7a3a28cc7dcc3a542ba3484ee58c7789cf2aa2c18993c7979e129e400719acf2. +// +// Solidity: event UpdaterAdded(uint32 indexed domain, address updater) +func (_AttestationCollector *AttestationCollectorFilterer) ParseUpdaterAdded(log types.Log) (*AttestationCollectorUpdaterAdded, error) { + event := new(AttestationCollectorUpdaterAdded) + if err := _AttestationCollector.contract.UnpackLog(event, "UpdaterAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// AttestationCollectorUpdaterRemovedIterator is returned from FilterUpdaterRemoved and is used to iterate over the raw logs and unpacked data for UpdaterRemoved events raised by the AttestationCollector contract. +type AttestationCollectorUpdaterRemovedIterator struct { + Event *AttestationCollectorUpdaterRemoved // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AttestationCollectorUpdaterRemovedIterator) 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(AttestationCollectorUpdaterRemoved) + 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(AttestationCollectorUpdaterRemoved) + 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 *AttestationCollectorUpdaterRemovedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AttestationCollectorUpdaterRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// AttestationCollectorUpdaterRemoved represents a UpdaterRemoved event raised by the AttestationCollector contract. +type AttestationCollectorUpdaterRemoved struct { + Domain uint32 + Updater common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdaterRemoved is a free log retrieval operation binding the contract event 0x68013ab89ba87f3a94d66c35bd0ff2578e0417b8df4cb289a9132d90febae91f. +// +// Solidity: event UpdaterRemoved(uint32 indexed domain, address updater) +func (_AttestationCollector *AttestationCollectorFilterer) FilterUpdaterRemoved(opts *bind.FilterOpts, domain []uint32) (*AttestationCollectorUpdaterRemovedIterator, error) { + + var domainRule []interface{} + for _, domainItem := range domain { + domainRule = append(domainRule, domainItem) + } + + logs, sub, err := _AttestationCollector.contract.FilterLogs(opts, "UpdaterRemoved", domainRule) + if err != nil { + return nil, err + } + return &AttestationCollectorUpdaterRemovedIterator{contract: _AttestationCollector.contract, event: "UpdaterRemoved", logs: logs, sub: sub}, nil +} + +// WatchUpdaterRemoved is a free log subscription operation binding the contract event 0x68013ab89ba87f3a94d66c35bd0ff2578e0417b8df4cb289a9132d90febae91f. +// +// Solidity: event UpdaterRemoved(uint32 indexed domain, address updater) +func (_AttestationCollector *AttestationCollectorFilterer) WatchUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *AttestationCollectorUpdaterRemoved, domain []uint32) (event.Subscription, error) { + + var domainRule []interface{} + for _, domainItem := range domain { + domainRule = append(domainRule, domainItem) + } + + logs, sub, err := _AttestationCollector.contract.WatchLogs(opts, "UpdaterRemoved", domainRule) + 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(AttestationCollectorUpdaterRemoved) + if err := _AttestationCollector.contract.UnpackLog(event, "UpdaterRemoved", 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 +} + +// ParseUpdaterRemoved is a log parse operation binding the contract event 0x68013ab89ba87f3a94d66c35bd0ff2578e0417b8df4cb289a9132d90febae91f. +// +// Solidity: event UpdaterRemoved(uint32 indexed domain, address updater) +func (_AttestationCollector *AttestationCollectorFilterer) ParseUpdaterRemoved(log types.Log) (*AttestationCollectorUpdaterRemoved, error) { + event := new(AttestationCollectorUpdaterRemoved) + if err := _AttestationCollector.contract.UnpackLog(event, "UpdaterRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// AuthMetaData contains all meta data concerning the Auth contract. +var AuthMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220166547638e80f3d27e55b19cbeec8aa8a2aea82406f1d001b9a37b1dd6ab571a64736f6c634300080d0033", +} + +// AuthABI is the input ABI used to generate the binding from. +// Deprecated: Use AuthMetaData.ABI instead. +var AuthABI = AuthMetaData.ABI + +// AuthBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AuthMetaData.Bin instead. +var AuthBin = AuthMetaData.Bin + +// DeployAuth deploys a new Ethereum contract, binding an instance of Auth to it. +func DeployAuth(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Auth, error) { + parsed, err := AuthMetaData.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(AuthBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Auth{AuthCaller: AuthCaller{contract: contract}, AuthTransactor: AuthTransactor{contract: contract}, AuthFilterer: AuthFilterer{contract: contract}}, nil +} + +// Auth is an auto generated Go binding around an Ethereum contract. +type Auth struct { + AuthCaller // Read-only binding to the contract + AuthTransactor // Write-only binding to the contract + AuthFilterer // Log filterer for contract events +} + +// AuthCaller is an auto generated read-only Go binding around an Ethereum contract. +type AuthCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AuthTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AuthTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AuthFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AuthFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AuthSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AuthSession struct { + Contract *Auth // 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 +} + +// AuthCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AuthCallerSession struct { + Contract *AuthCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AuthTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AuthTransactorSession struct { + Contract *AuthTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AuthRaw is an auto generated low-level Go binding around an Ethereum contract. +type AuthRaw struct { + Contract *Auth // Generic contract binding to access the raw methods on +} + +// AuthCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AuthCallerRaw struct { + Contract *AuthCaller // Generic read-only contract binding to access the raw methods on +} + +// AuthTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AuthTransactorRaw struct { + Contract *AuthTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAuth creates a new instance of Auth, bound to a specific deployed contract. +func NewAuth(address common.Address, backend bind.ContractBackend) (*Auth, error) { + contract, err := bindAuth(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Auth{AuthCaller: AuthCaller{contract: contract}, AuthTransactor: AuthTransactor{contract: contract}, AuthFilterer: AuthFilterer{contract: contract}}, nil +} + +// NewAuthCaller creates a new read-only instance of Auth, bound to a specific deployed contract. +func NewAuthCaller(address common.Address, caller bind.ContractCaller) (*AuthCaller, error) { + contract, err := bindAuth(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AuthCaller{contract: contract}, nil +} + +// NewAuthTransactor creates a new write-only instance of Auth, bound to a specific deployed contract. +func NewAuthTransactor(address common.Address, transactor bind.ContractTransactor) (*AuthTransactor, error) { + contract, err := bindAuth(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AuthTransactor{contract: contract}, nil +} + +// NewAuthFilterer creates a new log filterer instance of Auth, bound to a specific deployed contract. +func NewAuthFilterer(address common.Address, filterer bind.ContractFilterer) (*AuthFilterer, error) { + contract, err := bindAuth(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AuthFilterer{contract: contract}, nil +} + +// bindAuth binds a generic wrapper to an already deployed contract. +func bindAuth(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AuthABI)) + 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 (_Auth *AuthRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Auth.Contract.AuthCaller.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 (_Auth *AuthRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Auth.Contract.AuthTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Auth *AuthRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Auth.Contract.AuthTransactor.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 (_Auth *AuthCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Auth.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 (_Auth *AuthTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Auth.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Auth *AuthTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Auth.Contract.contract.Transact(opts, method, params...) +} + +// AuthManagerMetaData contains all meta data concerning the AuthManager contract. +var AuthManagerMetaData = &bind.MetaData{ + ABI: "[]", +} + +// AuthManagerABI is the input ABI used to generate the binding from. +// Deprecated: Use AuthManagerMetaData.ABI instead. +var AuthManagerABI = AuthManagerMetaData.ABI + +// AuthManager is an auto generated Go binding around an Ethereum contract. +type AuthManager struct { + AuthManagerCaller // Read-only binding to the contract + AuthManagerTransactor // Write-only binding to the contract + AuthManagerFilterer // Log filterer for contract events +} + +// AuthManagerCaller is an auto generated read-only Go binding around an Ethereum contract. +type AuthManagerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AuthManagerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AuthManagerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AuthManagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AuthManagerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AuthManagerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AuthManagerSession struct { + Contract *AuthManager // 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 +} + +// AuthManagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AuthManagerCallerSession struct { + Contract *AuthManagerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AuthManagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AuthManagerTransactorSession struct { + Contract *AuthManagerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AuthManagerRaw is an auto generated low-level Go binding around an Ethereum contract. +type AuthManagerRaw struct { + Contract *AuthManager // Generic contract binding to access the raw methods on +} + +// AuthManagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AuthManagerCallerRaw struct { + Contract *AuthManagerCaller // Generic read-only contract binding to access the raw methods on +} + +// AuthManagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AuthManagerTransactorRaw struct { + Contract *AuthManagerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAuthManager creates a new instance of AuthManager, bound to a specific deployed contract. +func NewAuthManager(address common.Address, backend bind.ContractBackend) (*AuthManager, error) { + contract, err := bindAuthManager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AuthManager{AuthManagerCaller: AuthManagerCaller{contract: contract}, AuthManagerTransactor: AuthManagerTransactor{contract: contract}, AuthManagerFilterer: AuthManagerFilterer{contract: contract}}, nil +} + +// NewAuthManagerCaller creates a new read-only instance of AuthManager, bound to a specific deployed contract. +func NewAuthManagerCaller(address common.Address, caller bind.ContractCaller) (*AuthManagerCaller, error) { + contract, err := bindAuthManager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AuthManagerCaller{contract: contract}, nil +} + +// NewAuthManagerTransactor creates a new write-only instance of AuthManager, bound to a specific deployed contract. +func NewAuthManagerTransactor(address common.Address, transactor bind.ContractTransactor) (*AuthManagerTransactor, error) { + contract, err := bindAuthManager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AuthManagerTransactor{contract: contract}, nil +} + +// NewAuthManagerFilterer creates a new log filterer instance of AuthManager, bound to a specific deployed contract. +func NewAuthManagerFilterer(address common.Address, filterer bind.ContractFilterer) (*AuthManagerFilterer, error) { + contract, err := bindAuthManager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AuthManagerFilterer{contract: contract}, nil +} + +// bindAuthManager binds a generic wrapper to an already deployed contract. +func bindAuthManager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AuthManagerABI)) + 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 (_AuthManager *AuthManagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthManager.Contract.AuthManagerCaller.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 (_AuthManager *AuthManagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthManager.Contract.AuthManagerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AuthManager *AuthManagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthManager.Contract.AuthManagerTransactor.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 (_AuthManager *AuthManagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthManager.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 (_AuthManager *AuthManagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthManager.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AuthManager *AuthManagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthManager.Contract.contract.Transact(opts, method, params...) +} + +// ContextUpgradeableMetaData contains all meta data concerning the ContextUpgradeable contract. +var ContextUpgradeableMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}]", +} + +// ContextUpgradeableABI is the input ABI used to generate the binding from. +// Deprecated: Use ContextUpgradeableMetaData.ABI instead. +var ContextUpgradeableABI = ContextUpgradeableMetaData.ABI + +// ContextUpgradeable is an auto generated Go binding around an Ethereum contract. +type ContextUpgradeable struct { + ContextUpgradeableCaller // Read-only binding to the contract + ContextUpgradeableTransactor // Write-only binding to the contract + ContextUpgradeableFilterer // Log filterer for contract events +} + +// ContextUpgradeableCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContextUpgradeableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContextUpgradeableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContextUpgradeableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContextUpgradeableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContextUpgradeableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContextUpgradeableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContextUpgradeableSession struct { + Contract *ContextUpgradeable // 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 +} + +// ContextUpgradeableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContextUpgradeableCallerSession struct { + Contract *ContextUpgradeableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ContextUpgradeableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContextUpgradeableTransactorSession struct { + Contract *ContextUpgradeableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContextUpgradeableRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContextUpgradeableRaw struct { + Contract *ContextUpgradeable // Generic contract binding to access the raw methods on +} + +// ContextUpgradeableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContextUpgradeableCallerRaw struct { + Contract *ContextUpgradeableCaller // Generic read-only contract binding to access the raw methods on +} + +// ContextUpgradeableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContextUpgradeableTransactorRaw struct { + Contract *ContextUpgradeableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewContextUpgradeable creates a new instance of ContextUpgradeable, bound to a specific deployed contract. +func NewContextUpgradeable(address common.Address, backend bind.ContractBackend) (*ContextUpgradeable, error) { + contract, err := bindContextUpgradeable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ContextUpgradeable{ContextUpgradeableCaller: ContextUpgradeableCaller{contract: contract}, ContextUpgradeableTransactor: ContextUpgradeableTransactor{contract: contract}, ContextUpgradeableFilterer: ContextUpgradeableFilterer{contract: contract}}, nil +} + +// NewContextUpgradeableCaller creates a new read-only instance of ContextUpgradeable, bound to a specific deployed contract. +func NewContextUpgradeableCaller(address common.Address, caller bind.ContractCaller) (*ContextUpgradeableCaller, error) { + contract, err := bindContextUpgradeable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContextUpgradeableCaller{contract: contract}, nil +} + +// NewContextUpgradeableTransactor creates a new write-only instance of ContextUpgradeable, bound to a specific deployed contract. +func NewContextUpgradeableTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextUpgradeableTransactor, error) { + contract, err := bindContextUpgradeable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContextUpgradeableTransactor{contract: contract}, nil +} + +// NewContextUpgradeableFilterer creates a new log filterer instance of ContextUpgradeable, bound to a specific deployed contract. +func NewContextUpgradeableFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextUpgradeableFilterer, error) { + contract, err := bindContextUpgradeable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContextUpgradeableFilterer{contract: contract}, nil +} + +// bindContextUpgradeable binds a generic wrapper to an already deployed contract. +func bindContextUpgradeable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ContextUpgradeableABI)) + 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 (_ContextUpgradeable *ContextUpgradeableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ContextUpgradeable.Contract.ContextUpgradeableCaller.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 (_ContextUpgradeable *ContextUpgradeableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ContextUpgradeable.Contract.ContextUpgradeableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ContextUpgradeable *ContextUpgradeableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ContextUpgradeable.Contract.ContextUpgradeableTransactor.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 (_ContextUpgradeable *ContextUpgradeableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ContextUpgradeable.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 (_ContextUpgradeable *ContextUpgradeableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ContextUpgradeable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ContextUpgradeable *ContextUpgradeableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ContextUpgradeable.Contract.contract.Transact(opts, method, params...) +} + +// ContextUpgradeableInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the ContextUpgradeable contract. +type ContextUpgradeableInitializedIterator struct { + Event *ContextUpgradeableInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ContextUpgradeableInitializedIterator) 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(ContextUpgradeableInitialized) + 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(ContextUpgradeableInitialized) + 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 *ContextUpgradeableInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContextUpgradeableInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContextUpgradeableInitialized represents a Initialized event raised by the ContextUpgradeable contract. +type ContextUpgradeableInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_ContextUpgradeable *ContextUpgradeableFilterer) FilterInitialized(opts *bind.FilterOpts) (*ContextUpgradeableInitializedIterator, error) { + + logs, sub, err := _ContextUpgradeable.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &ContextUpgradeableInitializedIterator{contract: _ContextUpgradeable.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_ContextUpgradeable *ContextUpgradeableFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *ContextUpgradeableInitialized) (event.Subscription, error) { + + logs, sub, err := _ContextUpgradeable.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(ContextUpgradeableInitialized) + if err := _ContextUpgradeable.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 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_ContextUpgradeable *ContextUpgradeableFilterer) ParseInitialized(log types.Log) (*ContextUpgradeableInitialized, error) { + event := new(ContextUpgradeableInitialized) + if err := _ContextUpgradeable.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ECDSAMetaData contains all meta data concerning the ECDSA contract. +var ECDSAMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220099461ae85d64d015a240ca7028310fd9987755ed92fb2497c3529fa2dbb711864736f6c634300080d0033", +} + +// ECDSAABI is the input ABI used to generate the binding from. +// Deprecated: Use ECDSAMetaData.ABI instead. +var ECDSAABI = ECDSAMetaData.ABI + +// ECDSABin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ECDSAMetaData.Bin instead. +var ECDSABin = ECDSAMetaData.Bin + +// DeployECDSA deploys a new Ethereum contract, binding an instance of ECDSA to it. +func DeployECDSA(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ECDSA, error) { + parsed, err := ECDSAMetaData.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(ECDSABin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ECDSA{ECDSACaller: ECDSACaller{contract: contract}, ECDSATransactor: ECDSATransactor{contract: contract}, ECDSAFilterer: ECDSAFilterer{contract: contract}}, nil +} + +// ECDSA is an auto generated Go binding around an Ethereum contract. +type ECDSA struct { + ECDSACaller // Read-only binding to the contract + ECDSATransactor // Write-only binding to the contract + ECDSAFilterer // Log filterer for contract events +} + +// ECDSACaller is an auto generated read-only Go binding around an Ethereum contract. +type ECDSACaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ECDSATransactor is an auto generated write-only Go binding around an Ethereum contract. +type ECDSATransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ECDSAFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ECDSAFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ECDSASession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ECDSASession struct { + Contract *ECDSA // 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 +} + +// ECDSACallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ECDSACallerSession struct { + Contract *ECDSACaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ECDSATransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ECDSATransactorSession struct { + Contract *ECDSATransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ECDSARaw is an auto generated low-level Go binding around an Ethereum contract. +type ECDSARaw struct { + Contract *ECDSA // Generic contract binding to access the raw methods on +} + +// ECDSACallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ECDSACallerRaw struct { + Contract *ECDSACaller // Generic read-only contract binding to access the raw methods on +} + +// ECDSATransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ECDSATransactorRaw struct { + Contract *ECDSATransactor // Generic write-only contract binding to access the raw methods on +} + +// NewECDSA creates a new instance of ECDSA, bound to a specific deployed contract. +func NewECDSA(address common.Address, backend bind.ContractBackend) (*ECDSA, error) { + contract, err := bindECDSA(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ECDSA{ECDSACaller: ECDSACaller{contract: contract}, ECDSATransactor: ECDSATransactor{contract: contract}, ECDSAFilterer: ECDSAFilterer{contract: contract}}, nil +} + +// NewECDSACaller creates a new read-only instance of ECDSA, bound to a specific deployed contract. +func NewECDSACaller(address common.Address, caller bind.ContractCaller) (*ECDSACaller, error) { + contract, err := bindECDSA(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ECDSACaller{contract: contract}, nil +} + +// NewECDSATransactor creates a new write-only instance of ECDSA, bound to a specific deployed contract. +func NewECDSATransactor(address common.Address, transactor bind.ContractTransactor) (*ECDSATransactor, error) { + contract, err := bindECDSA(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ECDSATransactor{contract: contract}, nil +} + +// NewECDSAFilterer creates a new log filterer instance of ECDSA, bound to a specific deployed contract. +func NewECDSAFilterer(address common.Address, filterer bind.ContractFilterer) (*ECDSAFilterer, error) { + contract, err := bindECDSA(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ECDSAFilterer{contract: contract}, nil +} + +// bindECDSA binds a generic wrapper to an already deployed contract. +func bindECDSA(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ECDSAABI)) + 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 (_ECDSA *ECDSARaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ECDSA.Contract.ECDSACaller.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 (_ECDSA *ECDSARaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ECDSA.Contract.ECDSATransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ECDSA *ECDSARaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ECDSA.Contract.ECDSATransactor.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 (_ECDSA *ECDSACallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ECDSA.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 (_ECDSA *ECDSATransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ECDSA.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ECDSA *ECDSATransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ECDSA.Contract.contract.Transact(opts, method, params...) +} + +// InitializableMetaData contains all meta data concerning the Initializable contract. +var InitializableMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}]", +} + +// InitializableABI is the input ABI used to generate the binding from. +// Deprecated: Use InitializableMetaData.ABI instead. +var InitializableABI = InitializableMetaData.ABI + +// Initializable is an auto generated Go binding around an Ethereum contract. +type Initializable struct { + InitializableCaller // Read-only binding to the contract + InitializableTransactor // Write-only binding to the contract + InitializableFilterer // Log filterer for contract events +} + +// InitializableCaller is an auto generated read-only Go binding around an Ethereum contract. +type InitializableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InitializableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type InitializableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InitializableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type InitializableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InitializableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type InitializableSession struct { + Contract *Initializable // 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 +} + +// InitializableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type InitializableCallerSession struct { + Contract *InitializableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// InitializableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type InitializableTransactorSession struct { + Contract *InitializableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// InitializableRaw is an auto generated low-level Go binding around an Ethereum contract. +type InitializableRaw struct { + Contract *Initializable // Generic contract binding to access the raw methods on +} + +// InitializableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type InitializableCallerRaw struct { + Contract *InitializableCaller // Generic read-only contract binding to access the raw methods on +} + +// InitializableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type InitializableTransactorRaw struct { + Contract *InitializableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewInitializable creates a new instance of Initializable, bound to a specific deployed contract. +func NewInitializable(address common.Address, backend bind.ContractBackend) (*Initializable, error) { + contract, err := bindInitializable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Initializable{InitializableCaller: InitializableCaller{contract: contract}, InitializableTransactor: InitializableTransactor{contract: contract}, InitializableFilterer: InitializableFilterer{contract: contract}}, nil +} + +// NewInitializableCaller creates a new read-only instance of Initializable, bound to a specific deployed contract. +func NewInitializableCaller(address common.Address, caller bind.ContractCaller) (*InitializableCaller, error) { + contract, err := bindInitializable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &InitializableCaller{contract: contract}, nil +} + +// NewInitializableTransactor creates a new write-only instance of Initializable, bound to a specific deployed contract. +func NewInitializableTransactor(address common.Address, transactor bind.ContractTransactor) (*InitializableTransactor, error) { + contract, err := bindInitializable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &InitializableTransactor{contract: contract}, nil +} + +// NewInitializableFilterer creates a new log filterer instance of Initializable, bound to a specific deployed contract. +func NewInitializableFilterer(address common.Address, filterer bind.ContractFilterer) (*InitializableFilterer, error) { + contract, err := bindInitializable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &InitializableFilterer{contract: contract}, nil +} + +// bindInitializable binds a generic wrapper to an already deployed contract. +func bindInitializable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(InitializableABI)) + 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 (_Initializable *InitializableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Initializable.Contract.InitializableCaller.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 (_Initializable *InitializableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Initializable.Contract.InitializableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Initializable *InitializableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Initializable.Contract.InitializableTransactor.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 (_Initializable *InitializableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Initializable.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 (_Initializable *InitializableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Initializable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Initializable *InitializableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Initializable.Contract.contract.Transact(opts, method, params...) +} + +// InitializableInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Initializable contract. +type InitializableInitializedIterator struct { + Event *InitializableInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InitializableInitializedIterator) 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(InitializableInitialized) + 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(InitializableInitialized) + 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 *InitializableInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InitializableInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InitializableInitialized represents a Initialized event raised by the Initializable contract. +type InitializableInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Initializable *InitializableFilterer) FilterInitialized(opts *bind.FilterOpts) (*InitializableInitializedIterator, error) { + + logs, sub, err := _Initializable.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &InitializableInitializedIterator{contract: _Initializable.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Initializable *InitializableFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *InitializableInitialized) (event.Subscription, error) { + + logs, sub, err := _Initializable.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(InitializableInitialized) + if err := _Initializable.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 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Initializable *InitializableFilterer) ParseInitialized(log types.Log) (*InitializableInitialized, error) { + event := new(InitializableInitialized) + if err := _Initializable.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OwnableUpgradeableMetaData contains all meta data concerning the OwnableUpgradeable contract. +var OwnableUpgradeableMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "8da5cb5b": "owner()", + "715018a6": "renounceOwnership()", + "f2fde38b": "transferOwnership(address)", + }, +} + +// OwnableUpgradeableABI is the input ABI used to generate the binding from. +// Deprecated: Use OwnableUpgradeableMetaData.ABI instead. +var OwnableUpgradeableABI = OwnableUpgradeableMetaData.ABI + +// Deprecated: Use OwnableUpgradeableMetaData.Sigs instead. +// OwnableUpgradeableFuncSigs maps the 4-byte function signature to its string representation. +var OwnableUpgradeableFuncSigs = OwnableUpgradeableMetaData.Sigs + +// OwnableUpgradeable is an auto generated Go binding around an Ethereum contract. +type OwnableUpgradeable struct { + OwnableUpgradeableCaller // Read-only binding to the contract + OwnableUpgradeableTransactor // Write-only binding to the contract + OwnableUpgradeableFilterer // Log filterer for contract events +} + +// OwnableUpgradeableCaller is an auto generated read-only Go binding around an Ethereum contract. +type OwnableUpgradeableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableUpgradeableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OwnableUpgradeableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableUpgradeableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OwnableUpgradeableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableUpgradeableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OwnableUpgradeableSession struct { + Contract *OwnableUpgradeable // 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 +} + +// OwnableUpgradeableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OwnableUpgradeableCallerSession struct { + Contract *OwnableUpgradeableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OwnableUpgradeableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OwnableUpgradeableTransactorSession struct { + Contract *OwnableUpgradeableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OwnableUpgradeableRaw is an auto generated low-level Go binding around an Ethereum contract. +type OwnableUpgradeableRaw struct { + Contract *OwnableUpgradeable // Generic contract binding to access the raw methods on +} + +// OwnableUpgradeableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OwnableUpgradeableCallerRaw struct { + Contract *OwnableUpgradeableCaller // Generic read-only contract binding to access the raw methods on +} + +// OwnableUpgradeableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OwnableUpgradeableTransactorRaw struct { + Contract *OwnableUpgradeableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewOwnableUpgradeable creates a new instance of OwnableUpgradeable, bound to a specific deployed contract. +func NewOwnableUpgradeable(address common.Address, backend bind.ContractBackend) (*OwnableUpgradeable, error) { + contract, err := bindOwnableUpgradeable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OwnableUpgradeable{OwnableUpgradeableCaller: OwnableUpgradeableCaller{contract: contract}, OwnableUpgradeableTransactor: OwnableUpgradeableTransactor{contract: contract}, OwnableUpgradeableFilterer: OwnableUpgradeableFilterer{contract: contract}}, nil +} + +// NewOwnableUpgradeableCaller creates a new read-only instance of OwnableUpgradeable, bound to a specific deployed contract. +func NewOwnableUpgradeableCaller(address common.Address, caller bind.ContractCaller) (*OwnableUpgradeableCaller, error) { + contract, err := bindOwnableUpgradeable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OwnableUpgradeableCaller{contract: contract}, nil +} + +// NewOwnableUpgradeableTransactor creates a new write-only instance of OwnableUpgradeable, bound to a specific deployed contract. +func NewOwnableUpgradeableTransactor(address common.Address, transactor bind.ContractTransactor) (*OwnableUpgradeableTransactor, error) { + contract, err := bindOwnableUpgradeable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OwnableUpgradeableTransactor{contract: contract}, nil +} + +// NewOwnableUpgradeableFilterer creates a new log filterer instance of OwnableUpgradeable, bound to a specific deployed contract. +func NewOwnableUpgradeableFilterer(address common.Address, filterer bind.ContractFilterer) (*OwnableUpgradeableFilterer, error) { + contract, err := bindOwnableUpgradeable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OwnableUpgradeableFilterer{contract: contract}, nil +} + +// bindOwnableUpgradeable binds a generic wrapper to an already deployed contract. +func bindOwnableUpgradeable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(OwnableUpgradeableABI)) + 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 (_OwnableUpgradeable *OwnableUpgradeableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OwnableUpgradeable.Contract.OwnableUpgradeableCaller.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 (_OwnableUpgradeable *OwnableUpgradeableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.OwnableUpgradeableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OwnableUpgradeable *OwnableUpgradeableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.OwnableUpgradeableTransactor.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 (_OwnableUpgradeable *OwnableUpgradeableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OwnableUpgradeable.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 (_OwnableUpgradeable *OwnableUpgradeableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OwnableUpgradeable *OwnableUpgradeableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.contract.Transact(opts, method, params...) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_OwnableUpgradeable *OwnableUpgradeableCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OwnableUpgradeable.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 (_OwnableUpgradeable *OwnableUpgradeableSession) Owner() (common.Address, error) { + return _OwnableUpgradeable.Contract.Owner(&_OwnableUpgradeable.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_OwnableUpgradeable *OwnableUpgradeableCallerSession) Owner() (common.Address, error) { + return _OwnableUpgradeable.Contract.Owner(&_OwnableUpgradeable.CallOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_OwnableUpgradeable *OwnableUpgradeableTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OwnableUpgradeable.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_OwnableUpgradeable *OwnableUpgradeableSession) RenounceOwnership() (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.RenounceOwnership(&_OwnableUpgradeable.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_OwnableUpgradeable *OwnableUpgradeableTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.RenounceOwnership(&_OwnableUpgradeable.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_OwnableUpgradeable *OwnableUpgradeableTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _OwnableUpgradeable.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_OwnableUpgradeable *OwnableUpgradeableSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.TransferOwnership(&_OwnableUpgradeable.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_OwnableUpgradeable *OwnableUpgradeableTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _OwnableUpgradeable.Contract.TransferOwnership(&_OwnableUpgradeable.TransactOpts, newOwner) +} + +// OwnableUpgradeableInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the OwnableUpgradeable contract. +type OwnableUpgradeableInitializedIterator struct { + Event *OwnableUpgradeableInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *OwnableUpgradeableInitializedIterator) 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(OwnableUpgradeableInitialized) + 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(OwnableUpgradeableInitialized) + 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 *OwnableUpgradeableInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OwnableUpgradeableInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OwnableUpgradeableInitialized represents a Initialized event raised by the OwnableUpgradeable contract. +type OwnableUpgradeableInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_OwnableUpgradeable *OwnableUpgradeableFilterer) FilterInitialized(opts *bind.FilterOpts) (*OwnableUpgradeableInitializedIterator, error) { + + logs, sub, err := _OwnableUpgradeable.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &OwnableUpgradeableInitializedIterator{contract: _OwnableUpgradeable.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_OwnableUpgradeable *OwnableUpgradeableFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *OwnableUpgradeableInitialized) (event.Subscription, error) { + + logs, sub, err := _OwnableUpgradeable.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(OwnableUpgradeableInitialized) + if err := _OwnableUpgradeable.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 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_OwnableUpgradeable *OwnableUpgradeableFilterer) ParseInitialized(log types.Log) (*OwnableUpgradeableInitialized, error) { + event := new(OwnableUpgradeableInitialized) + if err := _OwnableUpgradeable.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OwnableUpgradeableOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the OwnableUpgradeable contract. +type OwnableUpgradeableOwnershipTransferredIterator struct { + Event *OwnableUpgradeableOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *OwnableUpgradeableOwnershipTransferredIterator) 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(OwnableUpgradeableOwnershipTransferred) + 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(OwnableUpgradeableOwnershipTransferred) + 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 *OwnableUpgradeableOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OwnableUpgradeableOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OwnableUpgradeableOwnershipTransferred represents a OwnershipTransferred event raised by the OwnableUpgradeable contract. +type OwnableUpgradeableOwnershipTransferred 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 (_OwnableUpgradeable *OwnableUpgradeableFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*OwnableUpgradeableOwnershipTransferredIterator, 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 := _OwnableUpgradeable.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &OwnableUpgradeableOwnershipTransferredIterator{contract: _OwnableUpgradeable.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 (_OwnableUpgradeable *OwnableUpgradeableFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OwnableUpgradeableOwnershipTransferred, 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 := _OwnableUpgradeable.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(OwnableUpgradeableOwnershipTransferred) + if err := _OwnableUpgradeable.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 (_OwnableUpgradeable *OwnableUpgradeableFilterer) ParseOwnershipTransferred(log types.Log) (*OwnableUpgradeableOwnershipTransferred, error) { + event := new(OwnableUpgradeableOwnershipTransferred) + if err := _OwnableUpgradeable.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StringsMetaData contains all meta data concerning the Strings contract. +var StringsMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e257bed11037ec4fc2768d269bb17cb67558a254ec5b3812a3321b30c6e6e1a964736f6c634300080d0033", +} + +// StringsABI is the input ABI used to generate the binding from. +// Deprecated: Use StringsMetaData.ABI instead. +var StringsABI = StringsMetaData.ABI + +// StringsBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use StringsMetaData.Bin instead. +var StringsBin = StringsMetaData.Bin + +// DeployStrings deploys a new Ethereum contract, binding an instance of Strings to it. +func DeployStrings(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Strings, error) { + parsed, err := StringsMetaData.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(StringsBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Strings{StringsCaller: StringsCaller{contract: contract}, StringsTransactor: StringsTransactor{contract: contract}, StringsFilterer: StringsFilterer{contract: contract}}, nil +} + +// Strings is an auto generated Go binding around an Ethereum contract. +type Strings struct { + StringsCaller // Read-only binding to the contract + StringsTransactor // Write-only binding to the contract + StringsFilterer // Log filterer for contract events +} + +// StringsCaller is an auto generated read-only Go binding around an Ethereum contract. +type StringsCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StringsTransactor is an auto generated write-only Go binding around an Ethereum contract. +type StringsTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StringsFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type StringsFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StringsSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type StringsSession struct { + Contract *Strings // 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 +} + +// StringsCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type StringsCallerSession struct { + Contract *StringsCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// StringsTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type StringsTransactorSession struct { + Contract *StringsTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StringsRaw is an auto generated low-level Go binding around an Ethereum contract. +type StringsRaw struct { + Contract *Strings // Generic contract binding to access the raw methods on +} + +// StringsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type StringsCallerRaw struct { + Contract *StringsCaller // Generic read-only contract binding to access the raw methods on +} + +// StringsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type StringsTransactorRaw struct { + Contract *StringsTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewStrings creates a new instance of Strings, bound to a specific deployed contract. +func NewStrings(address common.Address, backend bind.ContractBackend) (*Strings, error) { + contract, err := bindStrings(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Strings{StringsCaller: StringsCaller{contract: contract}, StringsTransactor: StringsTransactor{contract: contract}, StringsFilterer: StringsFilterer{contract: contract}}, nil +} + +// NewStringsCaller creates a new read-only instance of Strings, bound to a specific deployed contract. +func NewStringsCaller(address common.Address, caller bind.ContractCaller) (*StringsCaller, error) { + contract, err := bindStrings(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &StringsCaller{contract: contract}, nil +} + +// NewStringsTransactor creates a new write-only instance of Strings, bound to a specific deployed contract. +func NewStringsTransactor(address common.Address, transactor bind.ContractTransactor) (*StringsTransactor, error) { + contract, err := bindStrings(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &StringsTransactor{contract: contract}, nil +} + +// NewStringsFilterer creates a new log filterer instance of Strings, bound to a specific deployed contract. +func NewStringsFilterer(address common.Address, filterer bind.ContractFilterer) (*StringsFilterer, error) { + contract, err := bindStrings(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &StringsFilterer{contract: contract}, nil +} + +// bindStrings binds a generic wrapper to an already deployed contract. +func bindStrings(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(StringsABI)) + 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 (_Strings *StringsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Strings.Contract.StringsCaller.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 (_Strings *StringsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Strings.Contract.StringsTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Strings *StringsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Strings.Contract.StringsTransactor.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 (_Strings *StringsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Strings.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 (_Strings *StringsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Strings.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Strings *StringsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Strings.Contract.contract.Transact(opts, method, params...) +} + +// TypedMemViewMetaData contains all meta data concerning the TypedMemView contract. +var TypedMemViewMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"NULL\",\"outputs\":[{\"internalType\":\"bytes29\",\"name\":\"\",\"type\":\"bytes29\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "f26be3fc": "NULL()", + }, + Bin: "0x60c9610038600b82828239805160001a607314602b57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b605e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000081565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000909116815260200160405180910390f3fea2646970667358221220ea6ef7ba43f5f066ef723e6a4a974ffc8341d84389459e3ed021a6c5892aa6d364736f6c634300080d0033", +} + +// TypedMemViewABI is the input ABI used to generate the binding from. +// Deprecated: Use TypedMemViewMetaData.ABI instead. +var TypedMemViewABI = TypedMemViewMetaData.ABI + +// Deprecated: Use TypedMemViewMetaData.Sigs instead. +// TypedMemViewFuncSigs maps the 4-byte function signature to its string representation. +var TypedMemViewFuncSigs = TypedMemViewMetaData.Sigs + +// TypedMemViewBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use TypedMemViewMetaData.Bin instead. +var TypedMemViewBin = TypedMemViewMetaData.Bin + +// DeployTypedMemView deploys a new Ethereum contract, binding an instance of TypedMemView to it. +func DeployTypedMemView(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *TypedMemView, error) { + parsed, err := TypedMemViewMetaData.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(TypedMemViewBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &TypedMemView{TypedMemViewCaller: TypedMemViewCaller{contract: contract}, TypedMemViewTransactor: TypedMemViewTransactor{contract: contract}, TypedMemViewFilterer: TypedMemViewFilterer{contract: contract}}, nil +} + +// TypedMemView is an auto generated Go binding around an Ethereum contract. +type TypedMemView struct { + TypedMemViewCaller // Read-only binding to the contract + TypedMemViewTransactor // Write-only binding to the contract + TypedMemViewFilterer // Log filterer for contract events +} + +// TypedMemViewCaller is an auto generated read-only Go binding around an Ethereum contract. +type TypedMemViewCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TypedMemViewTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TypedMemViewTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TypedMemViewFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TypedMemViewFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TypedMemViewSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TypedMemViewSession struct { + Contract *TypedMemView // 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 +} + +// TypedMemViewCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TypedMemViewCallerSession struct { + Contract *TypedMemViewCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TypedMemViewTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TypedMemViewTransactorSession struct { + Contract *TypedMemViewTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TypedMemViewRaw is an auto generated low-level Go binding around an Ethereum contract. +type TypedMemViewRaw struct { + Contract *TypedMemView // Generic contract binding to access the raw methods on +} + +// TypedMemViewCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TypedMemViewCallerRaw struct { + Contract *TypedMemViewCaller // Generic read-only contract binding to access the raw methods on +} + +// TypedMemViewTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TypedMemViewTransactorRaw struct { + Contract *TypedMemViewTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTypedMemView creates a new instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemView(address common.Address, backend bind.ContractBackend) (*TypedMemView, error) { + contract, err := bindTypedMemView(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &TypedMemView{TypedMemViewCaller: TypedMemViewCaller{contract: contract}, TypedMemViewTransactor: TypedMemViewTransactor{contract: contract}, TypedMemViewFilterer: TypedMemViewFilterer{contract: contract}}, nil +} + +// NewTypedMemViewCaller creates a new read-only instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemViewCaller(address common.Address, caller bind.ContractCaller) (*TypedMemViewCaller, error) { + contract, err := bindTypedMemView(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TypedMemViewCaller{contract: contract}, nil +} + +// NewTypedMemViewTransactor creates a new write-only instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemViewTransactor(address common.Address, transactor bind.ContractTransactor) (*TypedMemViewTransactor, error) { + contract, err := bindTypedMemView(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TypedMemViewTransactor{contract: contract}, nil +} + +// NewTypedMemViewFilterer creates a new log filterer instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemViewFilterer(address common.Address, filterer bind.ContractFilterer) (*TypedMemViewFilterer, error) { + contract, err := bindTypedMemView(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TypedMemViewFilterer{contract: contract}, nil +} + +// bindTypedMemView binds a generic wrapper to an already deployed contract. +func bindTypedMemView(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(TypedMemViewABI)) + 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 (_TypedMemView *TypedMemViewRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TypedMemView.Contract.TypedMemViewCaller.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 (_TypedMemView *TypedMemViewRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TypedMemView.Contract.TypedMemViewTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TypedMemView *TypedMemViewRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TypedMemView.Contract.TypedMemViewTransactor.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 (_TypedMemView *TypedMemViewCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TypedMemView.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 (_TypedMemView *TypedMemViewTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TypedMemView.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TypedMemView *TypedMemViewTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TypedMemView.Contract.contract.Transact(opts, method, params...) +} + +// NULL is a free data retrieval call binding the contract method 0xf26be3fc. +// +// Solidity: function NULL() view returns(bytes29) +func (_TypedMemView *TypedMemViewCaller) NULL(opts *bind.CallOpts) ([29]byte, error) { + var out []interface{} + err := _TypedMemView.contract.Call(opts, &out, "NULL") + + if err != nil { + return *new([29]byte), err + } + + out0 := *abi.ConvertType(out[0], new([29]byte)).(*[29]byte) + + return out0, err + +} + +// NULL is a free data retrieval call binding the contract method 0xf26be3fc. +// +// Solidity: function NULL() view returns(bytes29) +func (_TypedMemView *TypedMemViewSession) NULL() ([29]byte, error) { + return _TypedMemView.Contract.NULL(&_TypedMemView.CallOpts) +} + +// NULL is a free data retrieval call binding the contract method 0xf26be3fc. +// +// Solidity: function NULL() view returns(bytes29) +func (_TypedMemView *TypedMemViewCallerSession) NULL() ([29]byte, error) { + return _TypedMemView.Contract.NULL(&_TypedMemView.CallOpts) +} diff --git a/core/contracts/attestationcollector/attestationcollector.contractinfo.json b/core/contracts/attestationcollector/attestationcollector.contractinfo.json new file mode 100644 index 0000000000..7cf6d8794a --- /dev/null +++ b/core/contracts/attestationcollector/attestationcollector.contractinfo.json @@ -0,0 +1 @@ +{"solidity/AttestationCollector.sol:AddressUpgradeable":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220727ce1433873ec66526437ba322468859e5e44f570d4021a0275f8035716a14664736f6c634300080d0033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220727ce1433873ec66526437ba322468859e5e44f570d4021a0275f8035716a14664736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"50953:7122:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;50953:7122:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"50953:7122:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Collection of functions related to the address type","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Collection of functions related to the address type\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"AddressUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:Attestation":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207ee88204e5693e1a9483df6e58ee243c872e2fdc769dad2c6329deea804a72fe64736f6c634300080d0033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207ee88204e5693e1a9483df6e58ee243c872e2fdc769dad2c6329deea804a72fe64736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"32270:3216:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;32270:3216:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"32270:3216:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"OFFSET_HOME_DOMAIN":{"details":"AttestationData memory layout [000 .. 004): homeDomain uint32 4 bytes [004 .. 008): nonce uint32 4 bytes [008 .. 040): root bytes32 32 bytes Attestation memory layout [000 .. 040): data bytes 40 bytes (see above) [040 .. END): signature bytes ?? bytes (64/65 bytes)"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_HOME_DOMAIN\":{\"details\":\"AttestationData memory layout [000 .. 004): homeDomain uint32 4 bytes [004 .. 008): nonce uint32 4 bytes [008 .. 040): root bytes32 32 bytes Attestation memory layout [000 .. 040): data bytes 40 bytes (see above) [040 .. END): signature bytes ?? bytes (64/65 bytes)\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"Attestation\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:AttestationCollector":{"code":"0x608060405234801561001057600080fd5b50611c19806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100f5578063cefdf1491461011d578063ea3dd1db14610130578063f2fde38b1461014357600080fd5b8063021780f11461008d57806358fb6b36146100d0578063715018a6146100e55780638129fc1c146100ed575b600080fd5b6100bb61009b3660046117e7565b609760209081526000928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b6100e36100de3660046117e7565b610156565b005b6100e36101d0565b6100e3610243565b60655460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c7565b6100e361012b3660046117e7565b6102f2565b6100e361013e366004611854565b610363565b6100e3610151366004611934565b6103c4565b60655473ffffffffffffffffffffffffffffffffffffffff1633146101c25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6101cc82826104bd565b5050565b60655473ffffffffffffffffffffffffffffffffffffffff1633146102375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b6102416000610591565b565b600061024f6001610608565b9050801561028457603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61028c610761565b80156102ef57603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60655473ffffffffffffffffffffffffffffffffffffffff1633146103595760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b6101cc82826107e7565b600061036f83836108b1565b90508273ffffffffffffffffffffffffffffffffffffffff167f786431104fc3c4b19da7bae78f422f46b9c07528276a2ee430e8569cb8705f14836040516103b791906119ba565b60405180910390a2505050565b60655473ffffffffffffffffffffffffffffffffffffffff16331461042b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b73ffffffffffffffffffffffffffffffffffffffff81166104b45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101b9565b6102ef81610591565b63ffffffff8216600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166101cc5763ffffffff8216600081815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055519182527f7a3a28cc7dcc3a542ba3484ee58c7789cf2aa2c18993c7979e129e400719acf291015b60405180910390a25050565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b603254600090610100900460ff16156106a7578160ff16600114801561062d5750303b155b61069f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101b9565b506000919050565b60325460ff8084169116106107245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101b9565b50603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b603254610100900460ff166107de5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101b9565b61024133610591565b63ffffffff8216600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156101cc5763ffffffff8216600081815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055519182527f68013ab89ba87f3a94d66c35bd0ff2578e0417b8df4cb289a9132d90febae91f9101610585565b60006108bd82826109f6565b905060286bffffffffffffffffffffffff601883901c16116109215760405162461bcd60e51b815260206004820152601260248201527f4e6f7420616e206174746573746174696f6e000000000000000000000000000060448201526064016101b9565b6109568361093462ffffff198416610a1a565b61095161094662ffffff198616610a2f565b62ffffff1916610a62565b610ab5565b6109a461096862ffffff198316610bab565b63ffffffff16600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816845290915290205460ff1690565b6109f05760405162461bcd60e51b815260206004820152601860248201527f5369676e6572206973206e6f7420616e2075706461746572000000000000000060448201526064016101b9565b92915050565b815160009060208401610a1164ffffffffff85168284610bbf565b95945050505050565b60006109f062ffffff19831682602881610c09565b60006109f06028610a5281601886901c6bffffffffffffffffffffffff166119fc565b62ffffff19851691906000610c09565b6060600080610a7f8460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506040519150819250610aa48483602001610c8f565b508181016020016040529052919050565b6000610ac662ffffff198416610e34565b9050610b1f816040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90508373ffffffffffffffffffffffffffffffffffffffff16610b428284610e91565b73ffffffffffffffffffffffffffffffffffffffff1614610ba55760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e617475726500000000000000000000000000000060448201526064016101b9565b50505050565b60006109f062ffffff198316826004610eb5565b600080610bcc8385611a13565b9050604051811115610bdc575060005b80600003610bf15762ffffff19915050610c02565b5050606083811b8317901b811760181b5b9392505050565b600080610c248660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050610c3d86610ee5565b84610c488784611a13565b610c529190611a13565b1115610c655762ffffff19915050610c87565b610c6f8582611a13565b9050610c838364ffffffffff168286610bbf565b9150505b949350505050565b600062ffffff1980841603610d0c5760405162461bcd60e51b815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201527f657220646572656600000000000000000000000000000000000000000000000060648201526084016101b9565b610d1583610f2d565b610d875760405162461bcd60e51b815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201527f696e74657220646572656600000000000000000000000000000000000000000060648201526084016101b9565b6000610da18460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000610dcb8560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000604051905084811115610df05760206060fd5b8285848460045afa50610e2a610e068760d81c90565b70ffffffffff000000000000000000000000606091821b168717901b841760181b90565b9695505050505050565b600080610e4f8360781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000610e798460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169091209392505050565b6000806000610ea08585610f6a565b91509150610ead81610fd8565b509392505050565b6000610ec2826020611a2b565b610ecd906008611a4e565b60ff16610edb8585856111c4565b901c949350505050565b6000610eff8260181c6bffffffffffffffffffffffff1690565b610f178360781c6bffffffffffffffffffffffff1690565b016bffffffffffffffffffffffff169050919050565b6000610f398260d81c90565b64ffffffffff1664ffffffffff03610f5357506000919050565b6000610f5e83610ee5565b60405110199392505050565b6000808251604103610fa05760208301516040840151606085015160001a610f9487828585611382565b94509450505050610fd1565b8251604003610fc95760208301516040840151610fbe86838361149a565b935093505050610fd1565b506000905060025b9250929050565b6000816004811115610fec57610fec611a77565b03610ff45750565b600181600481111561100857611008611a77565b036110555760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016101b9565b600281600481111561106957611069611a77565b036110b65760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016101b9565b60038160048111156110ca576110ca611a77565b0361113d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016101b9565b600481600481111561115157611151611a77565b036102ef5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016101b9565b60008160ff166000036111d957506000610c02565b6111f18460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1661120c60ff841685611a13565b11156112845761126b61122d8560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166112538660181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16858560ff166114ec565b60405162461bcd60e51b81526004016101b991906119ba565b60208260ff1611156112fe5760405162461bcd60e51b815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e20333220627974657300000000000060648201526084016101b9565b60088202600061131c8660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060007f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84011d91909501511695945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156113b95750600090506003611491565b8460ff16601b141580156113d157508460ff16601c14155b156113e25750600090506004611491565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611436573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661148a57600060019250925050611491565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316816114d060ff86901c601b611a13565b90506114de87828885611382565b935093505050935093915050565b606060006114f98661155a565b91505060006115078661155a565b91505060006115158661155a565b91505060006115238661155a565b9150508383838360405160200161153d9493929190611aa6565b604051602081830303815290604052945050505050949350505050565b600080601f5b600f8160ff1611156115cd576000611579826008611a4e565b60ff1685901c905061158a81611644565b61ffff16841793508160ff166010146115a557601084901b93505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611560565b50600f5b60ff8160ff16101561163e5760006115ea826008611a4e565b60ff1685901c90506115fb81611644565b61ffff16831792508160ff1660001461161657601083901b92505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016115d1565b50915091565b600061165660048360ff16901c611676565b60ff1661ffff919091161760081b61166d82611676565b60ff1617919050565b600060f08083179060ff821690036116915750603092915050565b8060ff1660f1036116a55750603192915050565b8060ff1660f2036116b95750603292915050565b8060ff1660f3036116cd5750603392915050565b8060ff1660f4036116e15750603492915050565b8060ff1660f5036116f55750603592915050565b8060ff1660f6036117095750603692915050565b8060ff1660f70361171d5750603792915050565b8060ff1660f8036117315750603892915050565b8060ff1660f9036117455750603992915050565b8060ff1660fa036117595750606192915050565b8060ff1660fb0361176d5750606292915050565b8060ff1660fc036117815750606392915050565b8060ff1660fd036117955750606492915050565b8060ff1660fe036117a95750606592915050565b8060ff1660ff036117bd5750606692915050565b50919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461075c57600080fd5b600080604083850312156117fa57600080fd5b823563ffffffff8116811461180e57600080fd5b915061181c602084016117c3565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561186757600080fd5b611870836117c3565b9150602083013567ffffffffffffffff8082111561188d57600080fd5b818501915085601f8301126118a157600080fd5b8135818111156118b3576118b3611825565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156118f9576118f9611825565b8160405282815288602084870101111561191257600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60006020828403121561194657600080fd5b610c02826117c3565b6000815180845260005b8181101561197557602081850181015186830182015201611959565b81811115611987576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610c02602083018461194f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a0e57611a0e6119cd565b500390565b60008219821115611a2657611a266119cd565b500190565b600060ff821660ff841680821015611a4557611a456119cd565b90039392505050565b600060ff821660ff84168160ff0481118215151615611a6f57611a6f6119cd565b029392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f54797065644d656d566965772f696e646578202d204f76657272616e2074686581527f20766965772e20536c696365206973206174203078000000000000000000000060208201527fffffffffffff000000000000000000000000000000000000000000000000000060d086811b821660358401527f2077697468206c656e6774682030780000000000000000000000000000000000603b840181905286821b8316604a8501527f2e20417474656d7074656420746f20696e646578206174206f6666736574203060508501527f7800000000000000000000000000000000000000000000000000000000000000607085015285821b83166071850152607784015283901b1660868201527f2e00000000000000000000000000000000000000000000000000000000000000608c8201526000608d8201610e2a56fea2646970667358221220520cdd88203931370e5cb8bbcf5094413443157a6e50223ddc347706587db5c164736f6c634300080d0033","runtime-code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100f5578063cefdf1491461011d578063ea3dd1db14610130578063f2fde38b1461014357600080fd5b8063021780f11461008d57806358fb6b36146100d0578063715018a6146100e55780638129fc1c146100ed575b600080fd5b6100bb61009b3660046117e7565b609760209081526000928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b6100e36100de3660046117e7565b610156565b005b6100e36101d0565b6100e3610243565b60655460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c7565b6100e361012b3660046117e7565b6102f2565b6100e361013e366004611854565b610363565b6100e3610151366004611934565b6103c4565b60655473ffffffffffffffffffffffffffffffffffffffff1633146101c25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6101cc82826104bd565b5050565b60655473ffffffffffffffffffffffffffffffffffffffff1633146102375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b6102416000610591565b565b600061024f6001610608565b9050801561028457603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61028c610761565b80156102ef57603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60655473ffffffffffffffffffffffffffffffffffffffff1633146103595760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b6101cc82826107e7565b600061036f83836108b1565b90508273ffffffffffffffffffffffffffffffffffffffff167f786431104fc3c4b19da7bae78f422f46b9c07528276a2ee430e8569cb8705f14836040516103b791906119ba565b60405180910390a2505050565b60655473ffffffffffffffffffffffffffffffffffffffff16331461042b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101b9565b73ffffffffffffffffffffffffffffffffffffffff81166104b45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101b9565b6102ef81610591565b63ffffffff8216600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166101cc5763ffffffff8216600081815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055519182527f7a3a28cc7dcc3a542ba3484ee58c7789cf2aa2c18993c7979e129e400719acf291015b60405180910390a25050565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b603254600090610100900460ff16156106a7578160ff16600114801561062d5750303b155b61069f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101b9565b506000919050565b60325460ff8084169116106107245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101b9565b50603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055600190565b919050565b603254610100900460ff166107de5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101b9565b61024133610591565b63ffffffff8216600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156101cc5763ffffffff8216600081815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055519182527f68013ab89ba87f3a94d66c35bd0ff2578e0417b8df4cb289a9132d90febae91f9101610585565b60006108bd82826109f6565b905060286bffffffffffffffffffffffff601883901c16116109215760405162461bcd60e51b815260206004820152601260248201527f4e6f7420616e206174746573746174696f6e000000000000000000000000000060448201526064016101b9565b6109568361093462ffffff198416610a1a565b61095161094662ffffff198616610a2f565b62ffffff1916610a62565b610ab5565b6109a461096862ffffff198316610bab565b63ffffffff16600090815260976020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816845290915290205460ff1690565b6109f05760405162461bcd60e51b815260206004820152601860248201527f5369676e6572206973206e6f7420616e2075706461746572000000000000000060448201526064016101b9565b92915050565b815160009060208401610a1164ffffffffff85168284610bbf565b95945050505050565b60006109f062ffffff19831682602881610c09565b60006109f06028610a5281601886901c6bffffffffffffffffffffffff166119fc565b62ffffff19851691906000610c09565b6060600080610a7f8460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506040519150819250610aa48483602001610c8f565b508181016020016040529052919050565b6000610ac662ffffff198416610e34565b9050610b1f816040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90508373ffffffffffffffffffffffffffffffffffffffff16610b428284610e91565b73ffffffffffffffffffffffffffffffffffffffff1614610ba55760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e617475726500000000000000000000000000000060448201526064016101b9565b50505050565b60006109f062ffffff198316826004610eb5565b600080610bcc8385611a13565b9050604051811115610bdc575060005b80600003610bf15762ffffff19915050610c02565b5050606083811b8317901b811760181b5b9392505050565b600080610c248660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050610c3d86610ee5565b84610c488784611a13565b610c529190611a13565b1115610c655762ffffff19915050610c87565b610c6f8582611a13565b9050610c838364ffffffffff168286610bbf565b9150505b949350505050565b600062ffffff1980841603610d0c5760405162461bcd60e51b815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201527f657220646572656600000000000000000000000000000000000000000000000060648201526084016101b9565b610d1583610f2d565b610d875760405162461bcd60e51b815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201527f696e74657220646572656600000000000000000000000000000000000000000060648201526084016101b9565b6000610da18460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000610dcb8560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000604051905084811115610df05760206060fd5b8285848460045afa50610e2a610e068760d81c90565b70ffffffffff000000000000000000000000606091821b168717901b841760181b90565b9695505050505050565b600080610e4f8360781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506000610e798460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169091209392505050565b6000806000610ea08585610f6a565b91509150610ead81610fd8565b509392505050565b6000610ec2826020611a2b565b610ecd906008611a4e565b60ff16610edb8585856111c4565b901c949350505050565b6000610eff8260181c6bffffffffffffffffffffffff1690565b610f178360781c6bffffffffffffffffffffffff1690565b016bffffffffffffffffffffffff169050919050565b6000610f398260d81c90565b64ffffffffff1664ffffffffff03610f5357506000919050565b6000610f5e83610ee5565b60405110199392505050565b6000808251604103610fa05760208301516040840151606085015160001a610f9487828585611382565b94509450505050610fd1565b8251604003610fc95760208301516040840151610fbe86838361149a565b935093505050610fd1565b506000905060025b9250929050565b6000816004811115610fec57610fec611a77565b03610ff45750565b600181600481111561100857611008611a77565b036110555760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016101b9565b600281600481111561106957611069611a77565b036110b65760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016101b9565b60038160048111156110ca576110ca611a77565b0361113d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016101b9565b600481600481111561115157611151611a77565b036102ef5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016101b9565b60008160ff166000036111d957506000610c02565b6111f18460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1661120c60ff841685611a13565b11156112845761126b61122d8560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166112538660181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16858560ff166114ec565b60405162461bcd60e51b81526004016101b991906119ba565b60208260ff1611156112fe5760405162461bcd60e51b815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e20333220627974657300000000000060648201526084016101b9565b60088202600061131c8660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060007f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84011d91909501511695945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156113b95750600090506003611491565b8460ff16601b141580156113d157508460ff16601c14155b156113e25750600090506004611491565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611436573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661148a57600060019250925050611491565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316816114d060ff86901c601b611a13565b90506114de87828885611382565b935093505050935093915050565b606060006114f98661155a565b91505060006115078661155a565b91505060006115158661155a565b91505060006115238661155a565b9150508383838360405160200161153d9493929190611aa6565b604051602081830303815290604052945050505050949350505050565b600080601f5b600f8160ff1611156115cd576000611579826008611a4e565b60ff1685901c905061158a81611644565b61ffff16841793508160ff166010146115a557601084901b93505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611560565b50600f5b60ff8160ff16101561163e5760006115ea826008611a4e565b60ff1685901c90506115fb81611644565b61ffff16831792508160ff1660001461161657601083901b92505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016115d1565b50915091565b600061165660048360ff16901c611676565b60ff1661ffff919091161760081b61166d82611676565b60ff1617919050565b600060f08083179060ff821690036116915750603092915050565b8060ff1660f1036116a55750603192915050565b8060ff1660f2036116b95750603292915050565b8060ff1660f3036116cd5750603392915050565b8060ff1660f4036116e15750603492915050565b8060ff1660f5036116f55750603592915050565b8060ff1660f6036117095750603692915050565b8060ff1660f70361171d5750603792915050565b8060ff1660f8036117315750603892915050565b8060ff1660f9036117455750603992915050565b8060ff1660fa036117595750606192915050565b8060ff1660fb0361176d5750606292915050565b8060ff1660fc036117815750606392915050565b8060ff1660fd036117955750606492915050565b8060ff1660fe036117a95750606592915050565b8060ff1660ff036117bd5750606692915050565b50919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461075c57600080fd5b600080604083850312156117fa57600080fd5b823563ffffffff8116811461180e57600080fd5b915061181c602084016117c3565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561186757600080fd5b611870836117c3565b9150602083013567ffffffffffffffff8082111561188d57600080fd5b818501915085601f8301126118a157600080fd5b8135818111156118b3576118b3611825565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156118f9576118f9611825565b8160405282815288602084870101111561191257600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60006020828403121561194657600080fd5b610c02826117c3565b6000815180845260005b8181101561197557602081850181015186830182015201611959565b81811115611987576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610c02602083018461194f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a0e57611a0e6119cd565b500390565b60008219821115611a2657611a266119cd565b500190565b600060ff821660ff841680821015611a4557611a456119cd565b90039392505050565b600060ff821660ff84168160ff0481118215151615611a6f57611a6f6119cd565b029392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f54797065644d656d566965772f696e646578202d204f76657272616e2074686581527f20766965772e20536c696365206973206174203078000000000000000000000060208201527fffffffffffff000000000000000000000000000000000000000000000000000060d086811b821660358401527f2077697468206c656e6774682030780000000000000000000000000000000000603b840181905286821b8316604a8501527f2e20417474656d7074656420746f20696e646578206174206f6666736574203060508501527f7800000000000000000000000000000000000000000000000000000000000000607085015285821b83166071850152607784015283901b1660868201527f2e00000000000000000000000000000000000000000000000000000000000000608c8201526000608d8201610e2a56fea2646970667358221220520cdd88203931370e5cb8bbcf5094413443157a6e50223ddc347706587db5c164736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"67628:5843:0:-:0;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"67628:5843:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69140:60;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;735:14:1;;728:22;710:41;;698:2;683:18;69140:60:0;;;;;;;;71008:120;;;;;;:::i;:::-;;:::i;:::-;;66540:101;;;:::i;70319:86::-;;;:::i;65908:85::-;65980:6;;65908:85;;65980:6;;;;908:74:1;;896:2;881:18;65908:85:0;762:226:1;71134:126:0;;;;;;:::i;:::-;;:::i;71806:248::-;;;;;;:::i;:::-;;:::i;66790:198::-;;;;;;:::i;:::-;;:::i;71008:120::-;65980:6;;66120:23;65980:6;64908:10;66120:23;66112:68;;;;-1:-1:-1;;;66112:68:0;;2634:2:1;66112:68:0;;;2616:21:1;;;2653:18;;;2646:30;2712:34;2692:18;;;2685:62;2764:18;;66112:68:0;;;;;;;;;71091:30:::1;71103:7;71112:8;71091:11;:30::i;:::-;71008:120:::0;;:::o;66540:101::-;65980:6;;66120:23;65980:6;64908:10;66120:23;66112:68;;;;-1:-1:-1;;;66112:68:0;;2634:2:1;66112:68:0;;;2616:21:1;;;2653:18;;;2646:30;2712:34;2692:18;;;2685:62;2764:18;;66112:68:0;2432:356:1;66112:68:0;66604:30:::1;66631:1;66604:18;:30::i;:::-;66540:101::o:0;70319:86::-;61088:19;61110:25;61133:1;61110:22;:25::i;:::-;61088:47;;61149:14;61145:65;;;61179:13;:20;;;;;;;;61145:65;70372:26:::1;:24;:26::i;:::-;61234:14:::0;61230:99;;;61264:13;:21;;;;;;61304:14;;-1:-1:-1;2945:36:1;;61304:14:0;;2933:2:1;2918:18;61304:14:0;;;;;;;61230:99;61078:257;70319:86::o;71134:126::-;65980:6;;66120:23;65980:6;64908:10;66120:23;66112:68;;;;-1:-1:-1;;;66112:68:0;;2634:2:1;66112:68:0;;;2616:21:1;;;2653:18;;;2646:30;2712:34;2692:18;;;2685:62;2764:18;;66112:68:0;2432:356:1;66112:68:0;71220:33:::1;71235:7;71244:8;71220:14;:33::i;71806:248::-:0;71897:13;71913:41;71931:8;71941:12;71913:17;:41::i;:::-;71897:57;;72024:8;72003:44;;;72034:12;72003:44;;;;;;:::i;:::-;;;;;;;;71887:167;71806:248;;:::o;66790:198::-;65980:6;;66120:23;65980:6;64908:10;66120:23;66112:68;;;;-1:-1:-1;;;66112:68:0;;2634:2:1;66112:68:0;;;2616:21:1;;;2653:18;;;2646:30;2712:34;2692:18;;;2685:62;2764:18;;66112:68:0;2432:356:1;66112:68:0;66878:22:::1;::::0;::::1;66870:73;;;::::0;-1:-1:-1;;;66870:73:0;;3951:2:1;66870:73:0::1;::::0;::::1;3933:21:1::0;3990:2;3970:18;;;3963:30;4029:34;4009:18;;;4002:62;4100:8;4080:18;;;4073:36;4126:19;;66870:73:0::1;3749:402:1::0;66870:73:0::1;66953:28;66972:8;66953:18;:28::i;72884:225::-:0;72963:18;;;;;;;:9;:18;;;;;;;;:28;;;;;;;;;;;;;72958:145;;73007:18;;;;;;;:9;:18;;;;;;;;:28;;;;;;;;;;;;;:35;;;;73038:4;73007:35;;;73061:31;908:74:1;;;73061:31:0;;881:18:1;73061:31:0;;;;;;;;72884:225;;:::o;67142:187::-;67234:6;;;;67250:17;;;;;;;;;;;67282:40;;67234:6;;;67250:17;67234:6;;67282:40;;67215:16;;67282:40;67205:124;67142:187;:::o;63264:808::-;63661:13;;63328:4;;63661:13;;;;;63657:409;;;63715:7;:12;;63726:1;63715:12;:61;;;;-1:-1:-1;63770:4:0;52235:19;:23;63715:61;63690:166;;;;-1:-1:-1;;;63690:166:0;;4358:2:1;63690:166:0;;;4340:21:1;4397:2;4377:18;;;4370:30;4436:34;4416:18;;;4409:62;4507:16;4487:18;;;4480:44;4541:19;;63690:166:0;4156:410:1;63690:166:0;-1:-1:-1;63877:5:0;;63264:808;-1:-1:-1;63264:808:0:o;63657:409::-;63921:12;;:22;;;;:12;;:22;63913:81;;;;-1:-1:-1;;;63913:81:0;;4358:2:1;63913:81:0;;;4340:21:1;4397:2;4377:18;;;4370:30;4436:34;4416:18;;;4409:62;4507:16;4487:18;;;4480:44;4541:19;;63913:81:0;4156:410:1;63913:81:0;-1:-1:-1;64008:12:0;:22;;;;;;;;;;;;;;;-1:-1:-1;;63264:808:0:o;63657:409::-;63264:808;;;:::o;65721:111::-;62675:13;;;;;;;62667:69;;;;-1:-1:-1;;;62667:69:0;;4773:2:1;62667:69:0;;;4755:21:1;4812:2;4792:18;;;4785:30;4851:34;4831:18;;;4824:62;4922:13;4902:18;;;4895:41;4953:19;;62667:69:0;4571:407:1;62667:69:0;65793:32:::1;64908:10:::0;65793:18:::1;:32::i;73115:230::-:0;73196:18;;;;;;;:9;:18;;;;;;;;:28;;;;;;;;;;;;;73192:147;;;73240:18;;;73271:5;73240:18;;;:9;:18;;;;;;;;:28;;;;;;;;;;;;;:36;;;;;;73295:33;908:74:1;;;73295:33:0;;881:18:1;73295:33:0;762:226:1;49301:538:0;49420:13;49457:19;:12;49420:13;49457:16;:19::i;:::-;49449:27;-1:-1:-1;32963:2:0;2670:26;16492:2;16488:16;;;16484:28;34217:37;49486:52;;;;-1:-1:-1;;;49486:52:0;;5185:2:1;49486:52:0;;;5167:21:1;5224:2;5204:18;;;5197:30;5263:20;5243:18;;;5236:48;5301:18;;49486:52:0;4983:342:1;49486:52:0;49600:138;49633:8;49655:23;-1:-1:-1;;49655:21:0;;;:23::i;:::-;49692:36;:28;-1:-1:-1;;49692:26:0;;;:28::i;:::-;-1:-1:-1;;49692:34:0;;:36::i;:::-;49600:19;:138::i;:::-;49756:47;49767:25;-1:-1:-1;;49767:23:0;;;:25::i;:::-;72749:22;;72722:4;72749:22;;;:9;:22;;;;;;;;:32;;;;;;;;;;;;;;72600:188;49756:47;49748:84;;;;-1:-1:-1;;;49748:84:0;;5532:2:1;49748:84:0;;;5514:21:1;5571:2;5551:18;;;5544:30;5610:26;5590:18;;;5583:54;5654:18;;49748:84:0;5330:348:1;49748:84:0;49301:538;;;;:::o;13655:359::-;13759:10;;13725:7;;13906:4;13897:14;;13981:26;;;;13897:14;13759:10;13981:5;:26::i;:::-;13974:33;13655:359;-1:-1:-1;;;;;13655:359:0:o;35074:155::-;35137:7;35163:59;-1:-1:-1;;35163:11:0;;35137:7;32963:2;35137:7;35163:11;:59::i;35312:172::-;35380:7;35406:71;32963:2;35436:37;32963:2;16492;16488:16;;;2670:26;16484:28;35436:37;:::i;:::-;-1:-1:-1;;35406:11:0;;;:71;35475:1;35406:11;:71::i;28308:632::-;28363:16;28391:11;28412:12;28427;28431:7;16492:2;16488:16;2670:26;16484:28;;16246:282;28427:12;28412:27;;;;28549:4;28543:11;28536:18;;28604:3;28597:10;;28650:33;28663:7;28672:3;28678:4;28672:10;28650:12;:33::i;:::-;-1:-1:-1;28807:14:0;;;28823:4;28803:25;28797:4;28790:39;28870:17;;28308:632;;-1:-1:-1;28308:632:0:o;46753:314::-;46888:14;46905;-1:-1:-1;;46905:12:0;;;:14::i;:::-;46888:31;;46938:36;46967:6;45309:58;;7544:66:1;45309:58:0;;;7532:79:1;7627:12;;;7620:28;;;45179:7:0;;7664:12:1;;45309:58:0;;;;;;;;;;;;45299:69;;;;;;45292:76;;45110:265;;;;46938:36;46929:45;;47030:7;46993:44;;:33;47007:6;47015:10;46993:13;:33::i;:::-;:44;;;46984:76;;;;-1:-1:-1;;;46984:76:0;;6204:2:1;46984:76:0;;;6186:21:1;6243:2;6223:18;;;6216:30;6282:19;6262:18;;;6255:47;6319:18;;46984:76:0;6002:341:1;46984:76:0;46878:189;46753:314;;;:::o;34358:143::-;34423:6;34455:38;-1:-1:-1;;34455:15:0;;34423:6;34491:1;34455:15;:38::i;12796:462::-;12907:15;;12949:11;12956:4;12949;:11;:::i;:::-;12934:26;;13075:4;13069:11;13063:4;13060:21;13057:66;;;-1:-1:-1;13108:1:0;13057:66;13146:4;13154:1;13146:9;13142:51;;-1:-1:-1;;13171:11:0;;;;;13142:51;-1:-1:-1;;12065:2:0;12061:27;;;12135:17;;12127:26;;12199:17;;12195:2;12191:26;12796:462;;;;;;:::o;17129:399::-;17268:7;17287:12;17302;17306:7;15386:3;15382:17;2670:26;15378:29;;15059:364;17302:12;17287:27;;;;17398:12;17402:7;17398:3;:12::i;:::-;17391:4;17375:13;17382:6;17375:4;:13;:::i;:::-;:20;;;;:::i;:::-;:35;17371:77;;;-1:-1:-1;;17426:11:0;;;;;17371:77;17465:13;17472:6;17465:4;:13;:::i;:::-;17458:20;;17495:26;17501:7;17495:26;;17510:4;17516;17495:5;:26::i;:::-;17488:33;;;17129:399;;;;;;;:::o;27036:902::-;27114:15;-1:-1:-1;;7972:15:0;;;;27141:69;;;;-1:-1:-1;;;27141:69:0;;6683:2:1;27141:69:0;;;6665:21:1;6722:2;6702:18;;;6695:30;6761:34;6741:18;;;6734:62;6832:10;6812:18;;;6805:38;6860:19;;27141:69:0;6481:404:1;27141:69:0;27228:16;27236:7;27228;:16::i;:::-;27220:72;;;;-1:-1:-1;;;27220:72:0;;7092:2:1;27220:72:0;;;7074:21:1;7131:2;7111:18;;;7104:30;7170:34;7150:18;;;7143:62;7241:13;7221:18;;;7214:41;7272:19;;27220:72:0;6890:407:1;27220:72:0;27302:12;27317;27321:7;16492:2;16488:16;2670:26;16484:28;;16246:282;27317:12;27302:27;;;;27339:15;27357:12;27361:7;15386:3;15382:17;2670:26;15378:29;;15059:364;27357:12;27339:30;;;;27380:11;27501:4;27495:11;27488:18;;27588:7;27583:3;27580:16;27577:94;;;27628:4;27622;27615:18;27577:94;27843:4;27834:7;27828:4;27819:7;27816:1;27809:5;27798:50;27794:55;27879:52;27900:15;27907:7;14417:3;14413:17;;14206:268;27900:15;12061:27;12065:2;12061:27;;;;12135:17;;12127:26;;12199:17;;12195:2;12191:26;;11811:446;27879:52;27869:62;27036:902;-1:-1:-1;;;;;;27036:902:0:o;22455:290::-;22511:14;22537:12;22552;22556:7;15386:3;15382:17;2670:26;15378:29;;15059:364;22552:12;22537:27;;;;22574:12;22589;22593:7;16492:2;16488:16;2670:26;16484:28;;16246:282;22589:12;22574:27;;22708:21;;;;22455:290;-1:-1:-1;;;22455:290:0:o;41406:227::-;41484:7;41504:17;41523:18;41545:27;41556:4;41562:9;41545:10;:27::i;:::-;41503:69;;;;41582:18;41594:5;41582:11;:18::i;:::-;-1:-1:-1;41617:9:0;41406:227;-1:-1:-1;;;41406:227:0:o;21121:221::-;21240:14;21318:11;21323:6;21318:2;:11;:::i;:::-;21317:17;;21333:1;21317:17;:::i;:::-;21273:62;;21281:30;21287:7;21296:6;21304;21281:5;:30::i;:::-;21273:62;;;21121:221;-1:-1:-1;;;;21121:221:0:o;16702:147::-;16755:7;16820:12;16824:7;16492:2;16488:16;2670:26;16484:28;;16246:282;16820:12;16805;16809:7;15386:3;15382:17;2670:26;15378:29;;15059:364;16805:12;:27;16798:34;;;;16702:147;;;:::o;8645:333::-;8702:8;8726:15;8733:7;14417:3;14413:17;;14206:268;8726:15;:31;;8745:12;8726:31;8722:74;;-1:-1:-1;8780:5:0;;8645:333;-1:-1:-1;8645:333:0:o;8722:74::-;8805:12;8820;8824:7;8820:3;:12::i;:::-;8955:4;8949:11;-1:-1:-1;8936:26:0;;8645:333;-1:-1:-1;;;8645:333:0:o;39341:1279::-;39422:7;39431:12;39652:9;:16;39672:2;39652:22;39648:966;;39941:4;39926:20;;39920:27;39990:4;39975:20;;39969:27;40047:4;40032:20;;40026:27;39690:9;40018:36;40088:25;40099:4;40018:36;39920:27;39969;40088:10;:25::i;:::-;40081:32;;;;;;;;;39648:966;40134:9;:16;40154:2;40134:22;40130:484;;40403:4;40388:20;;40382:27;40453:4;40438:20;;40432:27;40493:23;40504:4;40382:27;40432;40493:10;:23::i;:::-;40486:30;;;;;;;;40130:484;-1:-1:-1;40563:1:0;;-1:-1:-1;40567:35:0;40130:484;39341:1279;;;;;:::o;37646:631::-;37723:20;37714:5;:29;;;;;;;;:::i;:::-;;37710:561;;37646:631;:::o;37710:561::-;37819:29;37810:5;:38;;;;;;;;:::i;:::-;;37806:465;;37864:34;;-1:-1:-1;;;37864:34:0;;8521:2:1;37864:34:0;;;8503:21:1;8560:2;8540:18;;;8533:30;8599:26;8579:18;;;8572:54;8643:18;;37864:34:0;8319:348:1;37806:465:0;37928:35;37919:5;:44;;;;;;;;:::i;:::-;;37915:356;;37979:41;;-1:-1:-1;;;37979:41:0;;8874:2:1;37979:41:0;;;8856:21:1;8913:2;8893:18;;;8886:30;8952:33;8932:18;;;8925:61;9003:18;;37979:41:0;8672:355:1;37915:356:0;38050:30;38041:5;:39;;;;;;;;:::i;:::-;;38037:234;;38096:44;;-1:-1:-1;;;38096:44:0;;9234:2:1;38096:44:0;;;9216:21:1;9273:2;9253:18;;;9246:30;9312:34;9292:18;;;9285:62;9383:4;9363:18;;;9356:32;9405:19;;38096:44:0;9032:398:1;38037:234:0;38170:30;38161:5;:39;;;;;;;;:::i;:::-;;38157:114;;38216:44;;-1:-1:-1;;;38216:44:0;;9637:2:1;38216:44:0;;;9619:21:1;9676:2;9656:18;;;9649:30;9715:34;9695:18;;;9688:62;9786:4;9766:18;;;9759:32;9808:19;;38216:44:0;9435:398:1;20004:771:0;20119:14;20149:6;:11;;20159:1;20149:11;20145:59;;-1:-1:-1;20191:1:0;20176:17;;20145:59;20235:12;20239:7;16492:2;16488:16;2670:26;16484:28;;16246:282;20235:12;20217:30;;:15;;;;:6;:15;:::i;:::-;:30;20213:137;;;20270:68;20286:12;20290:7;15386:3;15382:17;2670:26;15378:29;;15059:364;20286:12;20270:68;;20300:12;20304:7;16492:2;16488:16;2670:26;16484:28;;16246:282;20300:12;20270:68;;20314:6;20330;20322:15;;20270;:68::i;:::-;20263:76;;-1:-1:-1;;;20263:76:0;;;;;;;;:::i;20213:137::-;20377:2;20367:6;:12;;;;20359:83;;;;-1:-1:-1;;;20359:83:0;;10264:2:1;20359:83:0;;;10246:21:1;10303:2;10283:18;;;10276:30;10342:34;10322:18;;;10315:62;10413:28;10393:18;;;10386:56;10459:19;;20359:83:0;10062:422:1;20359:83:0;20523:1;20514:10;;20453:15;20559:12;20563:7;15386:3;15382:17;2670:26;15378:29;;15059:364;20559:12;20544:27;;;-1:-1:-1;20581:13:0;7488:66;7458:12;;;7437:131;20733:17;;;;20727:24;20723:36;;;-1:-1:-1;;;;;20004:771:0:o;42814:1603::-;42940:7;;43864:66;43851:79;;43847:161;;;-1:-1:-1;43962:1:0;;-1:-1:-1;43966:30:0;43946:51;;43847:161;44021:1;:7;;44026:2;44021:7;;:18;;;;;44032:1;:7;;44037:2;44032:7;;44021:18;44017:100;;;-1:-1:-1;44071:1:0;;-1:-1:-1;44075:30:0;44055:51;;44017:100;44228:24;;;44211:14;44228:24;;;;;;;;;10716:25:1;;;10789:4;10777:17;;10757:18;;;10750:45;;;;10811:18;;;10804:34;;;10854:18;;;10847:34;;;44228:24:0;;10688:19:1;;44228:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;44228:24:0;;;;;;-1:-1:-1;;44266:20:0;;;44262:101;;44318:1;44322:29;44302:50;;;;;;;44262:101;44381:6;-1:-1:-1;44389:20:0;;-1:-1:-1;42814:1603:0;;;;;;;;:::o;41887:336::-;41997:7;;42055:66;42042:80;;41997:7;42148:25;42164:3;42149:18;;;42171:2;42148:25;:::i;:::-;42132:42;;42191:25;42202:4;42208:1;42211;42214;42191:10;:25::i;:::-;42184:32;;;;;;41887:336;;;;;;:::o;18761:741::-;18907:17;18939:9;18952:15;18962:4;18952:9;:15::i;:::-;18936:31;;;18980:9;18993:15;19003:4;18993:9;:15::i;:::-;18977:31;;;19021:9;19034:17;19044:6;19034:9;:17::i;:::-;19018:33;;;19064:9;19077:17;19087:6;19077:9;:17::i;:::-;19061:33;;;19244:1;19306;19386;19448;19130:355;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;19104:391;;18926:576;;;;18761:741;;;;;;:::o;5031:667::-;5085:13;;5141:2;5126:258;5149:2;5145:1;:6;;;5126:258;;;5169:11;5196:5;:1;5200;5196:5;:::i;:::-;5189:13;;:2;:13;;5169:34;;5226:14;5234:5;5226:7;:14::i;:::-;5217:23;;;;;;5258:1;:7;;5263:2;5258:7;5254:58;;5295:2;5285:12;;;;;5254:58;-1:-1:-1;5353:6:0;;5126:258;;;-1:-1:-1;5447:2:0;5432:260;5455:3;5451:1;:7;;;5432:260;;;5476:11;5503:5;:1;5507;5503:5;:::i;:::-;5496:13;;:2;:13;;5476:34;;5534:14;5542:5;5534:7;:14::i;:::-;5524:24;;;;;;5566:1;:6;;5571:1;5566:6;5562:58;;5603:2;5592:13;;;;;5562:58;-1:-1:-1;5661:6:0;;5432:260;;;;5031:667;;;:::o;4508:199::-;4558:14;4595:18;4611:1;4605:2;:7;;;;4595:9;:18::i;:::-;4584:29;;4637:13;;;;;;4649:1;4637:13;4671;4681:2;4671:9;:13::i;:::-;4660:24;;;;4508:199;-1:-1:-1;4508:199:0:o;2943:1393::-;2995:10;3161:4;3156:9;;;;3207:15;;;;;3203:57;;-1:-1:-1;3245:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3203:57::-;3278:7;:15;;3289:4;3278:15;3274:57;;-1:-1:-1;3316:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3274:57::-;3349:7;:15;;3360:4;3349:15;3345:57;;-1:-1:-1;3387:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3345:57::-;3420:7;:15;;3431:4;3420:15;3416:57;;-1:-1:-1;3458:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3416:57::-;3491:7;:15;;3502:4;3491:15;3487:57;;-1:-1:-1;3529:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3487:57::-;3562:7;:15;;3573:4;3562:15;3558:57;;-1:-1:-1;3600:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3558:57::-;3633:7;:15;;3644:4;3633:15;3629:57;;-1:-1:-1;3671:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3629:57::-;3704:7;:15;;3715:4;3704:15;3700:57;;-1:-1:-1;3742:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3700:57::-;3775:7;:15;;3786:4;3775:15;3771:57;;-1:-1:-1;3813:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3771:57::-;3846:7;:15;;3857:4;3846:15;3842:57;;-1:-1:-1;3884:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3842:57::-;3917:7;:15;;3928:4;3917:15;3913:57;;-1:-1:-1;3955:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3913:57::-;3988:7;:15;;3999:4;3988:15;3984:57;;-1:-1:-1;4026:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3984:57::-;4059:7;:15;;4070:4;4059:15;4055:57;;-1:-1:-1;4097:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4055:57::-;4130:7;:15;;4141:4;4130:15;4126:57;;-1:-1:-1;4168:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4126:57::-;4201:7;:15;;4212:4;4201:15;4197:57;;-1:-1:-1;4239:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4197:57::-;4272:7;:15;;4283:4;4272:15;4268:57;;-1:-1:-1;4310:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4268:57::-;3007:1329;2943:1393;;;:::o;14:196:1:-;82:20;;142:42;131:54;;121:65;;111:93;;200:1;197;190:12;215:350;282:6;290;343:2;331:9;322:7;318:23;314:32;311:52;;;359:1;356;349:12;311:52;398:9;385:23;448:10;441:5;437:22;430:5;427:33;417:61;;474:1;471;464:12;417:61;497:5;-1:-1:-1;521:38:1;555:2;540:18;;521:38;:::i;:::-;511:48;;215:350;;;;;:::o;993:184::-;1045:77;1042:1;1035:88;1142:4;1139:1;1132:15;1166:4;1163:1;1156:15;1182:1054;1259:6;1267;1320:2;1308:9;1299:7;1295:23;1291:32;1288:52;;;1336:1;1333;1326:12;1288:52;1359:29;1378:9;1359:29;:::i;:::-;1349:39;;1439:2;1428:9;1424:18;1411:32;1462:18;1503:2;1495:6;1492:14;1489:34;;;1519:1;1516;1509:12;1489:34;1557:6;1546:9;1542:22;1532:32;;1602:7;1595:4;1591:2;1587:13;1583:27;1573:55;;1624:1;1621;1614:12;1573:55;1660:2;1647:16;1682:2;1678;1675:10;1672:36;;;1688:18;;:::i;:::-;1822:2;1816:9;1884:4;1876:13;;1727:66;1872:22;;;1896:2;1868:31;1864:40;1852:53;;;1920:18;;;1940:22;;;1917:46;1914:72;;;1966:18;;:::i;:::-;2006:10;2002:2;1995:22;2041:2;2033:6;2026:18;2081:7;2076:2;2071;2067;2063:11;2059:20;2056:33;2053:53;;;2102:1;2099;2092:12;2053:53;2158:2;2153;2149;2145:11;2140:2;2132:6;2128:15;2115:46;2203:1;2198:2;2193;2185:6;2181:15;2177:24;2170:35;2224:6;2214:16;;;;;;;1182:1054;;;;;:::o;2241:186::-;2300:6;2353:2;2341:9;2332:7;2328:23;2324:32;2321:52;;;2369:1;2366;2359:12;2321:52;2392:29;2411:9;2392:29;:::i;2992:530::-;3033:3;3071:5;3065:12;3098:6;3093:3;3086:19;3123:1;3133:162;3147:6;3144:1;3141:13;3133:162;;;3209:4;3265:13;;;3261:22;;3255:29;3237:11;;;3233:20;;3226:59;3162:12;3133:162;;;3313:6;3310:1;3307:13;3304:87;;;3379:1;3372:4;3363:6;3358:3;3354:16;3350:27;3343:38;3304:87;-1:-1:-1;3436:2:1;3424:15;3441:66;3420:88;3411:98;;;;3511:4;3407:109;;2992:530;-1:-1:-1;;2992:530:1:o;3527:217::-;3674:2;3663:9;3656:21;3637:4;3694:44;3734:2;3723:9;3719:18;3711:6;3694:44;:::i;5683:184::-;5735:77;5732:1;5725:88;5832:4;5829:1;5822:15;5856:4;5853:1;5846:15;5872:125;5912:4;5940:1;5937;5934:8;5931:34;;;5945:18;;:::i;:::-;-1:-1:-1;5982:9:1;;5872:125::o;6348:128::-;6388:3;6419:1;6415:6;6412:1;6409:13;6406:39;;;6425:18;;:::i;:::-;-1:-1:-1;6461:9:1;;6348:128::o;7687:195::-;7725:4;7762;7759:1;7755:12;7794:4;7791:1;7787:12;7819:3;7814;7811:12;7808:38;;;7826:18;;:::i;:::-;7863:13;;;7687:195;-1:-1:-1;;;7687:195:1:o;7887:238::-;7925:7;7965:4;7962:1;7958:12;7997:4;7994:1;7990:12;8057:3;8051:4;8047:14;8042:3;8039:23;8032:3;8025:11;8018:19;8014:49;8011:75;;;8066:18;;:::i;:::-;8106:13;;7887:238;-1:-1:-1;;;7887:238:1:o;8130:184::-;8182:77;8179:1;8172:88;8279:4;8276:1;8269:15;8303:4;8300:1;8293:15;11011:1391;11733:34;11721:47;;11798:23;11793:2;11784:12;;11777:45;11841:66;11945:3;11941:16;;;11937:25;;11932:2;11923:12;;11916:47;11982:17;12024:2;12015:12;;12008:24;;;12066:16;;;12062:25;;12057:2;12048:12;;12041:47;12118:34;12113:2;12104:12;;12097:56;12184:3;12178;12169:13;;12162:26;12223:16;;;12219:25;;12213:3;12204:13;;12197:48;12270:3;12261:13;;12254:25;12314:16;;;12310:25;12304:3;12295:13;;12288:48;10969:3;12391;12382:13;;10957:16;-1:-1:-1;10989:11:1;;;12352:44;10892:114","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"updater","type":"address"},{"indexed":false,"internalType":"bytes","name":"attestation","type":"bytes"}],"name":"AttestationSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"updater","type":"address"}],"name":"UpdaterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"updater","type":"address"}],"name":"UpdaterRemoved","type":"event"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"address","name":"_updater","type":"address"}],"name":"addUpdater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"}],"name":"isUpdater","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"address","name":"_updater","type":"address"}],"name":"removeUpdater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_updater","type":"address"},{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"submitAttestation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{"owner()":{"details":"Returns the address of the current owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attestation\",\"type\":\"bytes\"}],\"name\":\"AttestationSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"}],\"name\":\"UpdaterAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"}],\"name\":\"UpdaterRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"addUpdater\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isUpdater\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"removeUpdater\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"submitAttestation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"AttestationCollector\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{"addUpdater(uint32,address)":"58fb6b36","initialize()":"8129fc1c","isUpdater(uint32,address)":"021780f1","owner()":"8da5cb5b","removeUpdater(uint32,address)":"cefdf149","renounceOwnership()":"715018a6","submitAttestation(address,bytes)":"ea3dd1db","transferOwnership(address)":"f2fde38b"}},"solidity/AttestationCollector.sol:Auth":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220166547638e80f3d27e55b19cbeec8aa8a2aea82406f1d001b9a37b1dd6ab571a64736f6c634300080d0033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220166547638e80f3d27e55b19cbeec8aa8a2aea82406f1d001b9a37b1dd6ab571a64736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"46393:676:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;46393:676:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"46393:676:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"Auth\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:AuthManager":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"AuthManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:ContextUpgradeable":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"ContextUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:ECDSA":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220099461ae85d64d015a240ca7028310fd9987755ed92fb2497c3529fa2dbb711864736f6c634300080d0033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220099461ae85d64d015a240ca7028310fd9987755ed92fb2497c3529fa2dbb711864736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"37467:8924:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;37467:8924:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"37467:8924:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"ECDSA\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:Initializable":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"custom:oz-upgrades-unsafe-allow":"constructor constructor() { _disableInitializers(); } ``` ====","details":"This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. The initialization functions use a version number. Once a version number is used, it is consumed and cannot be reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in case an upgrade adds a module that needs to be initialized. For example: [.hljs-theme-light.nopadding] ``` contract MyToken is ERC20Upgradeable { function initialize() initializer public { __ERC20_init(\"MyToken\", \"MTK\"); } } contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { function initializeV2() reinitializer(2) public { __ERC20Permit_init(\"MyToken\"); } } ``` TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: [.hljs-theme-light.nopadding] ```","events":{"Initialized(uint8)":{"details":"Triggered when the contract has been initialized or reinitialized."}},"kind":"dev","methods":{},"stateVariables":{"_initialized":{"custom:oz-retyped-from":"bool","details":"Indicates that the contract has been initialized."},"_initializing":{"details":"Indicates that the contract is in the process of being initialized."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}],\"devdoc\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor constructor() { _disableInitializers(); } ``` ====\",\"details\":\"This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. The initialization functions use a version number. Once a version number is used, it is consumed and cannot be reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in case an upgrade adds a module that needs to be initialized. For example: [.hljs-theme-light.nopadding] ``` contract MyToken is ERC20Upgradeable { function initialize() initializer public { __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\"); } } contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { function initializeV2() reinitializer(2) public { __ERC20Permit_init(\\\"MyToken\\\"); } } ``` TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: [.hljs-theme-light.nopadding] ```\",\"events\":{\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"_initialized\":{\"custom:oz-retyped-from\":\"bool\",\"details\":\"Indicates that the contract has been initialized.\"},\"_initializing\":{\"details\":\"Indicates that the contract is in the process of being initialized.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"Initializable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:OwnableUpgradeable":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{"owner()":{"details":"Returns the address of the current owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"OwnableUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{"owner()":"8da5cb5b","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/AttestationCollector.sol:Strings":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e257bed11037ec4fc2768d269bb17cb67558a254ec5b3812a3321b30c6e6e1a964736f6c634300080d0033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e257bed11037ec4fc2768d269bb17cb67558a254ec5b3812a3321b30c6e6e1a964736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"35580:1885:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;35580:1885:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"35580:1885:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"String operations.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"String operations.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"Strings\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationCollector.sol:TypedMemView":{"code":"0x60c9610038600b82828239805160001a607314602b57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b605e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000081565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000909116815260200160405180910390f3fea2646970667358221220ea6ef7ba43f5f066ef723e6a4a974ffc8341d84389459e3ed021a6c5892aa6d364736f6c634300080d0033","runtime-code":"0x730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b605e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000081565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000909116815260200160405180910390f3fea2646970667358221220ea6ef7ba43f5f066ef723e6a4a974ffc8341d84389459e3ed021a6c5892aa6d364736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp \u003e\u003e= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 \u0026\u0026 v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n\nlibrary Auth {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @notice Checks signer is authorized and that their signature is valid.\n * @param _signer Who signed the message\n * @param _data Data that was signed\n * @param _signature `_data` signed by `_signer`, reverts if invalid\n */\n function checkSignature(\n address _signer,\n bytes29 _data,\n bytes memory _signature\n ) internal pure {\n bytes32 digest = _data.keccak();\n digest = ECDSA.toEthSignedMessageHash(digest);\n require((ECDSA.recover(digest, _signature) == _signer), \"Invalid signature\");\n }\n}\n\nabstract contract AuthManager {\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ LIBRARIES ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[50] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n /**\n * @notice Checks if the passed payload is a valid Attestation message,\n * if the signature is valid and if the signer is an authorized updater.\n * @param _updater Signer of the message, needs to be authorized as updater, revert otherwise.\n * @param _attestation Attestation of Home merkle root. Needs to be valid, revert otherwise.\n * @return _view Memory view on attestation\n */\n function _checkUpdaterAuth(address _updater, bytes memory _attestation)\n internal\n view\n returns (bytes29 _view)\n {\n _view = _attestation.ref(0);\n require(_view.isAttestation(), \"Not an attestation\");\n // This will revert if signature is invalid\n Auth.checkSignature(\n _updater,\n _view.attestationData(),\n _view.attestationSignature().clone()\n );\n require(_isUpdater(_view.attestationDomain(), _updater), \"Signer is not an updater\");\n }\n\n function _checkWatchtowerAuth(address _watchtower, bytes memory _report)\n internal\n view\n returns (bytes29 _data)\n {\n // TODO: check if _report is valid, once watchtower message standard is finalized\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ VIRTUAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater) internal view virtual returns (bool);\n\n function _isWatchtower(address _watchtower) internal view virtual returns (bool);\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length \u003e 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// \n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n */\n modifier initializer() {\n bool isTopLevelCall = _setInitializedVersion(1);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n * initialization step. This is essential to configure modules that are added through upgrades and that require\n * initialization.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n */\n modifier reinitializer(uint8 version) {\n bool isTopLevelCall = _setInitializedVersion(version);\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(version);\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n */\n function _disableInitializers() internal virtual {\n _setInitializedVersion(type(uint8).max);\n }\n\n function _setInitializedVersion(uint8 version) private returns (bool) {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n // of initializers, because in other contexts the contract may have been reentered.\n if (_initializing) {\n require(\n version == 1 \u0026\u0026 !AddressUpgradeable.isContract(address(this)),\n \"Initializable: contract is already initialized\"\n );\n return false;\n } else {\n require(_initialized \u003c version, \"Initializable: contract is already initialized\");\n _initialized = version;\n return true;\n }\n }\n}\n\n// \n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n\n// \ncontract AttestationCollector is AuthManager, OwnableUpgradeable {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EVENTS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n event AttestationSubmitted(address indexed updater, bytes attestation);\n\n event UpdaterAdded(uint32 indexed domain, address updater);\n\n event UpdaterRemoved(uint32 indexed domain, address updater);\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ STORAGE ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // [homeDomain =\u003e [updater =\u003e isUpdater]]\n mapping(uint32 =\u003e mapping(address =\u003e bool)) public isUpdater;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ UPGRADE GAP ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n uint256[49] private __GAP;\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INITIALIZER ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function initialize() external initializer {\n __Ownable_init_unchained();\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ OWNER ONLY ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n // TODO: add/remove updaters upon bonding/unbonding\n\n function addUpdater(uint32 _domain, address _updater) external onlyOwner {\n _addUpdater(_domain, _updater);\n }\n\n function removeUpdater(uint32 _domain, address _updater) external onlyOwner {\n _removeUpdater(_domain, _updater);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ EXTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function submitAttestation(address _updater, bytes memory _attestation) external {\n bytes29 _view = _checkUpdaterAuth(_updater, _attestation);\n _storeAttestation(_view);\n emit AttestationSubmitted(_updater, _attestation);\n }\n\n /*╔══════════════════════════════════════════════════════════════════════╗*\\\n ▏*║ INTERNAL FUNCTIONS ║*▕\n \\*╚══════════════════════════════════════════════════════════════════════╝*/\n\n function _isUpdater(uint32 _homeDomain, address _updater)\n internal\n view\n override\n returns (bool)\n {\n return isUpdater[_homeDomain][_updater];\n }\n\n function _isWatchtower(address _watchtower) internal view override returns (bool) {}\n\n function _addUpdater(uint32 _domain, address _updater) internal {\n if (!isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = true;\n emit UpdaterAdded(_domain, _updater);\n }\n }\n\n function _removeUpdater(uint32 _domain, address _updater) internal {\n if (isUpdater[_domain][_updater]) {\n isUpdater[_domain][_updater] = false;\n emit UpdaterRemoved(_domain, _updater);\n }\n }\n\n function _storeAttestation(bytes29 _view) internal {\n // TODO: implement storing logic for easy retrieval\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"26:32242:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;26:32242:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"26:32242:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;2539:94;;;;;;;;198:66:1;186:79;;;168:98;;156:2;141:18;2539:94:0;;;;;;","abiDefinition":[{"inputs":[],"name":"NULL","outputs":[{"internalType":"bytes29","name":"","type":"bytes29"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NULL\",\"outputs\":[{\"internalType\":\"bytes29\",\"name\":\"\",\"type\":\"bytes29\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationCollector.sol\":\"TypedMemView\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationCollector.sol\":{\"keccak256\":\"0x24c06fcee446ce19c067bb617ea53ed870dd4bb5216d32ca30d889f9038df01b\",\"urls\":[\"bzz-raw://5202f8863ba2508b944d05e1148f50b8615504544819dfaaf91479f3407278da\",\"dweb:/ipfs/QmTL7ZJ4ZxqUmk7EEyW1csp5zsEXcKL7TV4oC8yqcEZPdE\"]}},\"version\":1}"},"hashes":{"NULL()":"f26be3fc"}}} \ No newline at end of file diff --git a/core/contracts/attestationcollector/attestationcollector.metadata.go b/core/contracts/attestationcollector/attestationcollector.metadata.go new file mode 100644 index 0000000000..d56ec8fa9f --- /dev/null +++ b/core/contracts/attestationcollector/attestationcollector.metadata.go @@ -0,0 +1,24 @@ +// Code generated by synapse abigen DO NOT EDIT. +package attestationcollector + +import ( + _ "embed" + "encoding/json" + "github.com/ethereum/go-ethereum/common/compiler" +) + +// rawContracts are the json we use to dervive the processed contracts +//go:embed attestationcollector.contractinfo.json +var rawContracts []byte + +// Contracts are unmarshalled on start +var Contracts map[string]*compiler.Contract + +func init() { + // load contract metadata + var err error + err = json.Unmarshal(rawContracts, &Contracts) + if err != nil { + panic(err) + } +} diff --git a/core/contracts/attestationcollector/generate.go b/core/contracts/attestationcollector/generate.go new file mode 100644 index 0000000000..a58d534604 --- /dev/null +++ b/core/contracts/attestationcollector/generate.go @@ -0,0 +1,3 @@ +package attestationcollector + +//go:generate go run github.com/synapsecns/sanguine/tools/abigen generate --sol ../../../packages/contracts/flattened/AttestationCollector.sol --pkg attestationcollector --sol-version 0.8.13 --filename attestationcollector diff --git a/core/contracts/attestationcollector/helpers.go b/core/contracts/attestationcollector/helpers.go new file mode 100644 index 0000000000..8cc8f58641 --- /dev/null +++ b/core/contracts/attestationcollector/helpers.go @@ -0,0 +1,34 @@ +package attestationcollector + +import ( + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +// AttestationCollectorRef is a bound attestatoin collector contract that returns the address of the attestation collector contract. +//nolint: golint +type AttestationCollectorRef struct { + *AttestationCollector + address common.Address +} + +// Address gets the address of the attestation contract. +func (a AttestationCollectorRef) Address() common.Address { + return a.address +} + +// NewAttestationCollectorRef creates an attestation contract with a contract ref. +func NewAttestationCollectorRef(address common.Address, backend bind.ContractBackend) (*AttestationCollectorRef, error) { + attestationContract, err := NewAttestationCollector(address, backend) + if err != nil { + return nil, err + } + + return &AttestationCollectorRef{ + AttestationCollector: attestationContract, + address: address, + }, nil +} + +var _ vm.ContractRef = AttestationCollectorRef{} diff --git a/core/contracts/test/attestationharness/attestationharness.abigen.go b/core/contracts/test/attestationharness/attestationharness.abigen.go new file mode 100644 index 0000000000..12a646dd8f --- /dev/null +++ b/core/contracts/test/attestationharness/attestationharness.abigen.go @@ -0,0 +1,848 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package attestationharness + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// AttestationMetaData contains all meta data concerning the Attestation contract. +var AttestationMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220174c7e2cc841c5259dfc83352f41e0130d1b4723ec6fa05b680a64dd0aedc30e64736f6c634300080d0033", +} + +// AttestationABI is the input ABI used to generate the binding from. +// Deprecated: Use AttestationMetaData.ABI instead. +var AttestationABI = AttestationMetaData.ABI + +// AttestationBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AttestationMetaData.Bin instead. +var AttestationBin = AttestationMetaData.Bin + +// DeployAttestation deploys a new Ethereum contract, binding an instance of Attestation to it. +func DeployAttestation(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Attestation, error) { + parsed, err := AttestationMetaData.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(AttestationBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Attestation{AttestationCaller: AttestationCaller{contract: contract}, AttestationTransactor: AttestationTransactor{contract: contract}, AttestationFilterer: AttestationFilterer{contract: contract}}, nil +} + +// Attestation is an auto generated Go binding around an Ethereum contract. +type Attestation struct { + AttestationCaller // Read-only binding to the contract + AttestationTransactor // Write-only binding to the contract + AttestationFilterer // Log filterer for contract events +} + +// AttestationCaller is an auto generated read-only Go binding around an Ethereum contract. +type AttestationCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AttestationTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AttestationFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AttestationSession struct { + Contract *Attestation // 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 +} + +// AttestationCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AttestationCallerSession struct { + Contract *AttestationCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AttestationTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AttestationTransactorSession struct { + Contract *AttestationTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AttestationRaw is an auto generated low-level Go binding around an Ethereum contract. +type AttestationRaw struct { + Contract *Attestation // Generic contract binding to access the raw methods on +} + +// AttestationCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AttestationCallerRaw struct { + Contract *AttestationCaller // Generic read-only contract binding to access the raw methods on +} + +// AttestationTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AttestationTransactorRaw struct { + Contract *AttestationTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAttestation creates a new instance of Attestation, bound to a specific deployed contract. +func NewAttestation(address common.Address, backend bind.ContractBackend) (*Attestation, error) { + contract, err := bindAttestation(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Attestation{AttestationCaller: AttestationCaller{contract: contract}, AttestationTransactor: AttestationTransactor{contract: contract}, AttestationFilterer: AttestationFilterer{contract: contract}}, nil +} + +// NewAttestationCaller creates a new read-only instance of Attestation, bound to a specific deployed contract. +func NewAttestationCaller(address common.Address, caller bind.ContractCaller) (*AttestationCaller, error) { + contract, err := bindAttestation(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AttestationCaller{contract: contract}, nil +} + +// NewAttestationTransactor creates a new write-only instance of Attestation, bound to a specific deployed contract. +func NewAttestationTransactor(address common.Address, transactor bind.ContractTransactor) (*AttestationTransactor, error) { + contract, err := bindAttestation(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AttestationTransactor{contract: contract}, nil +} + +// NewAttestationFilterer creates a new log filterer instance of Attestation, bound to a specific deployed contract. +func NewAttestationFilterer(address common.Address, filterer bind.ContractFilterer) (*AttestationFilterer, error) { + contract, err := bindAttestation(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AttestationFilterer{contract: contract}, nil +} + +// bindAttestation binds a generic wrapper to an already deployed contract. +func bindAttestation(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AttestationABI)) + 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 (_Attestation *AttestationRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Attestation.Contract.AttestationCaller.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 (_Attestation *AttestationRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Attestation.Contract.AttestationTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Attestation *AttestationRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Attestation.Contract.AttestationTransactor.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 (_Attestation *AttestationCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Attestation.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 (_Attestation *AttestationTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Attestation.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Attestation *AttestationTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Attestation.Contract.contract.Transact(opts, method, params...) +} + +// AttestationHarnessMetaData contains all meta data concerning the AttestationHarness contract. +var AttestationHarnessMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"domain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"formatAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"}],\"name\":\"formatAttestationData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"isAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"root\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"signature\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "d3d29df1": "data(bytes)", + "fbad0313": "domain(bytes)", + "4d358d65": "formatAttestation(uint32,uint32,bytes32,bytes)", + "ef6d4cad": "formatAttestationData(uint32,uint32,bytes32)", + "3ae7034d": "isAttestation(bytes)", + "4e765004": "nonce(bytes)", + "c2e9e208": "root(bytes)", + "58d18e3a": "signature(bytes)", + }, + Bin: "0x608060405234801561001057600080fd5b5061109b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c2e9e2081161005b578063c2e9e20814610110578063d3d29df114610131578063ef6d4cad14610144578063fbad03131461015757600080fd5b80633ae7034d1461008d5780634d358d65146100b55780634e765004146100d557806358d18e3a146100fd575b600080fd5b6100a061009b366004610cd0565b61016a565b60405190151581526020015b60405180910390f35b6100c86100c3366004610d1e565b61019f565b6040516100ac9190610e00565b6100e86100e3366004610cd0565b6101c0565b60405163ffffffff90911681526020016100ac565b6100c861010b366004610cd0565b6101da565b61012361011e366004610cd0565b610203565b6040519081526020016100ac565b6100c861013f366004610cd0565b61021d565b6100c8610152366004610e13565b61023b565b6100e8610165366004610cd0565b610297565b600061019961017983836102b1565b62ffffff1916602860189190911c6bffffffffffffffffffffffff161190565b92915050565b60606101b56101af86868661023b565b836102d5565b90505b949350505050565b60006101996101cf83836102b1565b62ffffff1916610301565b60606101996101f86101ed8460006102b1565b62ffffff1916610315565b62ffffff1916610348565b600061019961021283836102b1565b62ffffff191661039b565b60606101996101f86102308460006102b1565b62ffffff19166103b0565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086811b8216602084015285901b16602482015260288082018490528251808303909101815260489091019091525b9392505050565b60006101996102a683836102b1565b62ffffff19166103c5565b8151600090602084016102cc64ffffffffff851682846103d9565b95945050505050565b606082826040516020016102ea929190610e4f565b604051602081830303815290604052905092915050565b600061019962ffffff198316600480610420565b6000610199602861033881601886901c6bffffffffffffffffffffffff16610ead565b62ffffff19851691906000610450565b60606000806103658460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050604051915081925061038a84836020016104d4565b508181016020016040529052919050565b600061019962ffffff198316600860206106a8565b600061019962ffffff19831682602881610450565b600061019962ffffff198316826004610420565b6000806103e68385610ec4565b90506040518111156103f6575060005b8060000361040b5762ffffff19915050610290565b5050606092831b9190911790911b1760181b90565b600061042d826020610edc565b610438906008610eff565b60ff166104468585856106a8565b901c949350505050565b60008061046b8660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506104848661089a565b8461048f8784610ec4565b6104999190610ec4565b11156104ac5762ffffff199150506101b8565b6104b68582610ec4565b90506104ca8364ffffffffff1682866103d9565b9695505050505050565b600062ffffff1980841603610570576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201527f657220646572656600000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610579836108e2565b610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201527f696e7465722064657265660000000000000000000000000000000000000000006064820152608401610567565b600061061f8460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060006106498560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050600060405190508481111561066e5760206060fd5b8285848460045afa506104ca6106848760d81c90565b70ffffffffff000000000000000000000000606091821b168717901b841760181b90565b60008160ff166000036106bd57506000610290565b6106d58460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166106f060ff841685610ec4565b11156107825761074f6107118560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166107378660181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16858560ff1661091f565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105679190610e00565b60208260ff161115610816576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e2033322062797465730000000000006064820152608401610567565b6008820260006108348660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060007f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84011d91909501511695945050505050565b60006108b48260181c6bffffffffffffffffffffffff1690565b6108cc8360781c6bffffffffffffffffffffffff1690565b016bffffffffffffffffffffffff169050919050565b60006108ee8260d81c90565b64ffffffffff1664ffffffffff0361090857506000919050565b60006109138361089a565b60405110199392505050565b6060600061092c8661098d565b915050600061093a8661098d565b91505060006109488661098d565b91505060006109568661098d565b915050838383836040516020016109709493929190610f28565b604051602081830303815290604052945050505050949350505050565b600080601f5b600f8160ff161115610a005760006109ac826008610eff565b60ff1685901c90506109bd81610a77565b61ffff16841793508160ff166010146109d857601084901b93505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01610993565b50600f5b60ff8160ff161015610a71576000610a1d826008610eff565b60ff1685901c9050610a2e81610a77565b61ffff16831792508160ff16600014610a4957601083901b92505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01610a04565b50915091565b6000610a8960048360ff16901c610aa9565b60ff1661ffff919091161760081b610aa082610aa9565b60ff1617919050565b600060f08083179060ff82169003610ac45750603092915050565b8060ff1660f103610ad85750603192915050565b8060ff1660f203610aec5750603292915050565b8060ff1660f303610b005750603392915050565b8060ff1660f403610b145750603492915050565b8060ff1660f503610b285750603592915050565b8060ff1660f603610b3c5750603692915050565b8060ff1660f703610b505750603792915050565b8060ff1660f803610b645750603892915050565b8060ff1660f903610b785750603992915050565b8060ff1660fa03610b8c5750606192915050565b8060ff1660fb03610ba05750606292915050565b8060ff1660fc03610bb45750606392915050565b8060ff1660fd03610bc85750606492915050565b8060ff1660fe03610bdc5750606592915050565b8060ff1660ff03610bf05750606692915050565b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c3657600080fd5b813567ffffffffffffffff80821115610c5157610c51610bf6565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c9757610c97610bf6565b81604052838152866020858801011115610cb057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610ce257600080fd5b813567ffffffffffffffff811115610cf957600080fd5b6101b884828501610c25565b803563ffffffff81168114610d1957600080fd5b919050565b60008060008060808587031215610d3457600080fd5b610d3d85610d05565b9350610d4b60208601610d05565b925060408501359150606085013567ffffffffffffffff811115610d6e57600080fd5b610d7a87828801610c25565b91505092959194509250565b60005b83811015610da1578181015183820152602001610d89565b83811115610db0576000848401525b50505050565b60008151808452610dce816020860160208601610d86565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006102906020830184610db6565b600080600060608486031215610e2857600080fd5b610e3184610d05565b9250610e3f60208501610d05565b9150604084013590509250925092565b60008351610e61818460208801610d86565b835190830190610e75818360208801610d86565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610ebf57610ebf610e7e565b500390565b60008219821115610ed757610ed7610e7e565b500190565b600060ff821660ff841680821015610ef657610ef6610e7e565b90039392505050565b600060ff821660ff84168160ff0481118215151615610f2057610f20610e7e565b029392505050565b7f54797065644d656d566965772f696e646578202d204f76657272616e2074686581527f20766965772e20536c696365206973206174203078000000000000000000000060208201527fffffffffffff000000000000000000000000000000000000000000000000000060d086811b821660358401527f2077697468206c656e6774682030780000000000000000000000000000000000603b840181905286821b8316604a8501527f2e20417474656d7074656420746f20696e646578206174206f6666736574203060508501527f7800000000000000000000000000000000000000000000000000000000000000607085015285821b83166071850152607784015283901b1660868201527f2e00000000000000000000000000000000000000000000000000000000000000608c8201526000608d82016104ca56fea26469706673582212203593e560245ba73c8625f6dae52e94664942ef8a7d7beda4098e2242844aab2064736f6c634300080d0033", +} + +// AttestationHarnessABI is the input ABI used to generate the binding from. +// Deprecated: Use AttestationHarnessMetaData.ABI instead. +var AttestationHarnessABI = AttestationHarnessMetaData.ABI + +// Deprecated: Use AttestationHarnessMetaData.Sigs instead. +// AttestationHarnessFuncSigs maps the 4-byte function signature to its string representation. +var AttestationHarnessFuncSigs = AttestationHarnessMetaData.Sigs + +// AttestationHarnessBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AttestationHarnessMetaData.Bin instead. +var AttestationHarnessBin = AttestationHarnessMetaData.Bin + +// DeployAttestationHarness deploys a new Ethereum contract, binding an instance of AttestationHarness to it. +func DeployAttestationHarness(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *AttestationHarness, error) { + parsed, err := AttestationHarnessMetaData.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(AttestationHarnessBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &AttestationHarness{AttestationHarnessCaller: AttestationHarnessCaller{contract: contract}, AttestationHarnessTransactor: AttestationHarnessTransactor{contract: contract}, AttestationHarnessFilterer: AttestationHarnessFilterer{contract: contract}}, nil +} + +// AttestationHarness is an auto generated Go binding around an Ethereum contract. +type AttestationHarness struct { + AttestationHarnessCaller // Read-only binding to the contract + AttestationHarnessTransactor // Write-only binding to the contract + AttestationHarnessFilterer // Log filterer for contract events +} + +// AttestationHarnessCaller is an auto generated read-only Go binding around an Ethereum contract. +type AttestationHarnessCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationHarnessTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AttestationHarnessTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationHarnessFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AttestationHarnessFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AttestationHarnessSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AttestationHarnessSession struct { + Contract *AttestationHarness // 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 +} + +// AttestationHarnessCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AttestationHarnessCallerSession struct { + Contract *AttestationHarnessCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AttestationHarnessTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AttestationHarnessTransactorSession struct { + Contract *AttestationHarnessTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AttestationHarnessRaw is an auto generated low-level Go binding around an Ethereum contract. +type AttestationHarnessRaw struct { + Contract *AttestationHarness // Generic contract binding to access the raw methods on +} + +// AttestationHarnessCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AttestationHarnessCallerRaw struct { + Contract *AttestationHarnessCaller // Generic read-only contract binding to access the raw methods on +} + +// AttestationHarnessTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AttestationHarnessTransactorRaw struct { + Contract *AttestationHarnessTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAttestationHarness creates a new instance of AttestationHarness, bound to a specific deployed contract. +func NewAttestationHarness(address common.Address, backend bind.ContractBackend) (*AttestationHarness, error) { + contract, err := bindAttestationHarness(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AttestationHarness{AttestationHarnessCaller: AttestationHarnessCaller{contract: contract}, AttestationHarnessTransactor: AttestationHarnessTransactor{contract: contract}, AttestationHarnessFilterer: AttestationHarnessFilterer{contract: contract}}, nil +} + +// NewAttestationHarnessCaller creates a new read-only instance of AttestationHarness, bound to a specific deployed contract. +func NewAttestationHarnessCaller(address common.Address, caller bind.ContractCaller) (*AttestationHarnessCaller, error) { + contract, err := bindAttestationHarness(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AttestationHarnessCaller{contract: contract}, nil +} + +// NewAttestationHarnessTransactor creates a new write-only instance of AttestationHarness, bound to a specific deployed contract. +func NewAttestationHarnessTransactor(address common.Address, transactor bind.ContractTransactor) (*AttestationHarnessTransactor, error) { + contract, err := bindAttestationHarness(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AttestationHarnessTransactor{contract: contract}, nil +} + +// NewAttestationHarnessFilterer creates a new log filterer instance of AttestationHarness, bound to a specific deployed contract. +func NewAttestationHarnessFilterer(address common.Address, filterer bind.ContractFilterer) (*AttestationHarnessFilterer, error) { + contract, err := bindAttestationHarness(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AttestationHarnessFilterer{contract: contract}, nil +} + +// bindAttestationHarness binds a generic wrapper to an already deployed contract. +func bindAttestationHarness(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AttestationHarnessABI)) + 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 (_AttestationHarness *AttestationHarnessRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AttestationHarness.Contract.AttestationHarnessCaller.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 (_AttestationHarness *AttestationHarnessRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AttestationHarness.Contract.AttestationHarnessTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AttestationHarness *AttestationHarnessRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AttestationHarness.Contract.AttestationHarnessTransactor.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 (_AttestationHarness *AttestationHarnessCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AttestationHarness.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 (_AttestationHarness *AttestationHarnessTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AttestationHarness.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AttestationHarness *AttestationHarnessTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AttestationHarness.Contract.contract.Transact(opts, method, params...) +} + +// Data is a free data retrieval call binding the contract method 0xd3d29df1. +// +// Solidity: function data(bytes _attestation) view returns(bytes) +func (_AttestationHarness *AttestationHarnessCaller) Data(opts *bind.CallOpts, _attestation []byte) ([]byte, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "data", _attestation) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// Data is a free data retrieval call binding the contract method 0xd3d29df1. +// +// Solidity: function data(bytes _attestation) view returns(bytes) +func (_AttestationHarness *AttestationHarnessSession) Data(_attestation []byte) ([]byte, error) { + return _AttestationHarness.Contract.Data(&_AttestationHarness.CallOpts, _attestation) +} + +// Data is a free data retrieval call binding the contract method 0xd3d29df1. +// +// Solidity: function data(bytes _attestation) view returns(bytes) +func (_AttestationHarness *AttestationHarnessCallerSession) Data(_attestation []byte) ([]byte, error) { + return _AttestationHarness.Contract.Data(&_AttestationHarness.CallOpts, _attestation) +} + +// Domain is a free data retrieval call binding the contract method 0xfbad0313. +// +// Solidity: function domain(bytes _attestation) pure returns(uint32) +func (_AttestationHarness *AttestationHarnessCaller) Domain(opts *bind.CallOpts, _attestation []byte) (uint32, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "domain", _attestation) + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// Domain is a free data retrieval call binding the contract method 0xfbad0313. +// +// Solidity: function domain(bytes _attestation) pure returns(uint32) +func (_AttestationHarness *AttestationHarnessSession) Domain(_attestation []byte) (uint32, error) { + return _AttestationHarness.Contract.Domain(&_AttestationHarness.CallOpts, _attestation) +} + +// Domain is a free data retrieval call binding the contract method 0xfbad0313. +// +// Solidity: function domain(bytes _attestation) pure returns(uint32) +func (_AttestationHarness *AttestationHarnessCallerSession) Domain(_attestation []byte) (uint32, error) { + return _AttestationHarness.Contract.Domain(&_AttestationHarness.CallOpts, _attestation) +} + +// FormatAttestation is a free data retrieval call binding the contract method 0x4d358d65. +// +// Solidity: function formatAttestation(uint32 _domain, uint32 _nonce, bytes32 _root, bytes _signature) pure returns(bytes) +func (_AttestationHarness *AttestationHarnessCaller) FormatAttestation(opts *bind.CallOpts, _domain uint32, _nonce uint32, _root [32]byte, _signature []byte) ([]byte, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "formatAttestation", _domain, _nonce, _root, _signature) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// FormatAttestation is a free data retrieval call binding the contract method 0x4d358d65. +// +// Solidity: function formatAttestation(uint32 _domain, uint32 _nonce, bytes32 _root, bytes _signature) pure returns(bytes) +func (_AttestationHarness *AttestationHarnessSession) FormatAttestation(_domain uint32, _nonce uint32, _root [32]byte, _signature []byte) ([]byte, error) { + return _AttestationHarness.Contract.FormatAttestation(&_AttestationHarness.CallOpts, _domain, _nonce, _root, _signature) +} + +// FormatAttestation is a free data retrieval call binding the contract method 0x4d358d65. +// +// Solidity: function formatAttestation(uint32 _domain, uint32 _nonce, bytes32 _root, bytes _signature) pure returns(bytes) +func (_AttestationHarness *AttestationHarnessCallerSession) FormatAttestation(_domain uint32, _nonce uint32, _root [32]byte, _signature []byte) ([]byte, error) { + return _AttestationHarness.Contract.FormatAttestation(&_AttestationHarness.CallOpts, _domain, _nonce, _root, _signature) +} + +// FormatAttestationData is a free data retrieval call binding the contract method 0xef6d4cad. +// +// Solidity: function formatAttestationData(uint32 _domain, uint32 _nonce, bytes32 _root) pure returns(bytes) +func (_AttestationHarness *AttestationHarnessCaller) FormatAttestationData(opts *bind.CallOpts, _domain uint32, _nonce uint32, _root [32]byte) ([]byte, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "formatAttestationData", _domain, _nonce, _root) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// FormatAttestationData is a free data retrieval call binding the contract method 0xef6d4cad. +// +// Solidity: function formatAttestationData(uint32 _domain, uint32 _nonce, bytes32 _root) pure returns(bytes) +func (_AttestationHarness *AttestationHarnessSession) FormatAttestationData(_domain uint32, _nonce uint32, _root [32]byte) ([]byte, error) { + return _AttestationHarness.Contract.FormatAttestationData(&_AttestationHarness.CallOpts, _domain, _nonce, _root) +} + +// FormatAttestationData is a free data retrieval call binding the contract method 0xef6d4cad. +// +// Solidity: function formatAttestationData(uint32 _domain, uint32 _nonce, bytes32 _root) pure returns(bytes) +func (_AttestationHarness *AttestationHarnessCallerSession) FormatAttestationData(_domain uint32, _nonce uint32, _root [32]byte) ([]byte, error) { + return _AttestationHarness.Contract.FormatAttestationData(&_AttestationHarness.CallOpts, _domain, _nonce, _root) +} + +// IsAttestation is a free data retrieval call binding the contract method 0x3ae7034d. +// +// Solidity: function isAttestation(bytes _attestation) pure returns(bool) +func (_AttestationHarness *AttestationHarnessCaller) IsAttestation(opts *bind.CallOpts, _attestation []byte) (bool, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "isAttestation", _attestation) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsAttestation is a free data retrieval call binding the contract method 0x3ae7034d. +// +// Solidity: function isAttestation(bytes _attestation) pure returns(bool) +func (_AttestationHarness *AttestationHarnessSession) IsAttestation(_attestation []byte) (bool, error) { + return _AttestationHarness.Contract.IsAttestation(&_AttestationHarness.CallOpts, _attestation) +} + +// IsAttestation is a free data retrieval call binding the contract method 0x3ae7034d. +// +// Solidity: function isAttestation(bytes _attestation) pure returns(bool) +func (_AttestationHarness *AttestationHarnessCallerSession) IsAttestation(_attestation []byte) (bool, error) { + return _AttestationHarness.Contract.IsAttestation(&_AttestationHarness.CallOpts, _attestation) +} + +// Nonce is a free data retrieval call binding the contract method 0x4e765004. +// +// Solidity: function nonce(bytes _attestation) pure returns(uint32) +func (_AttestationHarness *AttestationHarnessCaller) Nonce(opts *bind.CallOpts, _attestation []byte) (uint32, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "nonce", _attestation) + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// Nonce is a free data retrieval call binding the contract method 0x4e765004. +// +// Solidity: function nonce(bytes _attestation) pure returns(uint32) +func (_AttestationHarness *AttestationHarnessSession) Nonce(_attestation []byte) (uint32, error) { + return _AttestationHarness.Contract.Nonce(&_AttestationHarness.CallOpts, _attestation) +} + +// Nonce is a free data retrieval call binding the contract method 0x4e765004. +// +// Solidity: function nonce(bytes _attestation) pure returns(uint32) +func (_AttestationHarness *AttestationHarnessCallerSession) Nonce(_attestation []byte) (uint32, error) { + return _AttestationHarness.Contract.Nonce(&_AttestationHarness.CallOpts, _attestation) +} + +// Root is a free data retrieval call binding the contract method 0xc2e9e208. +// +// Solidity: function root(bytes _attestation) pure returns(bytes32) +func (_AttestationHarness *AttestationHarnessCaller) Root(opts *bind.CallOpts, _attestation []byte) ([32]byte, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "root", _attestation) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// Root is a free data retrieval call binding the contract method 0xc2e9e208. +// +// Solidity: function root(bytes _attestation) pure returns(bytes32) +func (_AttestationHarness *AttestationHarnessSession) Root(_attestation []byte) ([32]byte, error) { + return _AttestationHarness.Contract.Root(&_AttestationHarness.CallOpts, _attestation) +} + +// Root is a free data retrieval call binding the contract method 0xc2e9e208. +// +// Solidity: function root(bytes _attestation) pure returns(bytes32) +func (_AttestationHarness *AttestationHarnessCallerSession) Root(_attestation []byte) ([32]byte, error) { + return _AttestationHarness.Contract.Root(&_AttestationHarness.CallOpts, _attestation) +} + +// Signature is a free data retrieval call binding the contract method 0x58d18e3a. +// +// Solidity: function signature(bytes _attestation) view returns(bytes) +func (_AttestationHarness *AttestationHarnessCaller) Signature(opts *bind.CallOpts, _attestation []byte) ([]byte, error) { + var out []interface{} + err := _AttestationHarness.contract.Call(opts, &out, "signature", _attestation) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// Signature is a free data retrieval call binding the contract method 0x58d18e3a. +// +// Solidity: function signature(bytes _attestation) view returns(bytes) +func (_AttestationHarness *AttestationHarnessSession) Signature(_attestation []byte) ([]byte, error) { + return _AttestationHarness.Contract.Signature(&_AttestationHarness.CallOpts, _attestation) +} + +// Signature is a free data retrieval call binding the contract method 0x58d18e3a. +// +// Solidity: function signature(bytes _attestation) view returns(bytes) +func (_AttestationHarness *AttestationHarnessCallerSession) Signature(_attestation []byte) ([]byte, error) { + return _AttestationHarness.Contract.Signature(&_AttestationHarness.CallOpts, _attestation) +} + +// TypedMemViewMetaData contains all meta data concerning the TypedMemView contract. +var TypedMemViewMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"NULL\",\"outputs\":[{\"internalType\":\"bytes29\",\"name\":\"\",\"type\":\"bytes29\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "f26be3fc": "NULL()", + }, + Bin: "0x60c9610038600b82828239805160001a607314602b57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b605e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000081565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000909116815260200160405180910390f3fea26469706673582212209ea5273888337b1496057049c57d442a265b849725273d42b7024200b638c69464736f6c634300080d0033", +} + +// TypedMemViewABI is the input ABI used to generate the binding from. +// Deprecated: Use TypedMemViewMetaData.ABI instead. +var TypedMemViewABI = TypedMemViewMetaData.ABI + +// Deprecated: Use TypedMemViewMetaData.Sigs instead. +// TypedMemViewFuncSigs maps the 4-byte function signature to its string representation. +var TypedMemViewFuncSigs = TypedMemViewMetaData.Sigs + +// TypedMemViewBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use TypedMemViewMetaData.Bin instead. +var TypedMemViewBin = TypedMemViewMetaData.Bin + +// DeployTypedMemView deploys a new Ethereum contract, binding an instance of TypedMemView to it. +func DeployTypedMemView(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *TypedMemView, error) { + parsed, err := TypedMemViewMetaData.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(TypedMemViewBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &TypedMemView{TypedMemViewCaller: TypedMemViewCaller{contract: contract}, TypedMemViewTransactor: TypedMemViewTransactor{contract: contract}, TypedMemViewFilterer: TypedMemViewFilterer{contract: contract}}, nil +} + +// TypedMemView is an auto generated Go binding around an Ethereum contract. +type TypedMemView struct { + TypedMemViewCaller // Read-only binding to the contract + TypedMemViewTransactor // Write-only binding to the contract + TypedMemViewFilterer // Log filterer for contract events +} + +// TypedMemViewCaller is an auto generated read-only Go binding around an Ethereum contract. +type TypedMemViewCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TypedMemViewTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TypedMemViewTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TypedMemViewFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TypedMemViewFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TypedMemViewSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TypedMemViewSession struct { + Contract *TypedMemView // 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 +} + +// TypedMemViewCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TypedMemViewCallerSession struct { + Contract *TypedMemViewCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TypedMemViewTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TypedMemViewTransactorSession struct { + Contract *TypedMemViewTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TypedMemViewRaw is an auto generated low-level Go binding around an Ethereum contract. +type TypedMemViewRaw struct { + Contract *TypedMemView // Generic contract binding to access the raw methods on +} + +// TypedMemViewCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TypedMemViewCallerRaw struct { + Contract *TypedMemViewCaller // Generic read-only contract binding to access the raw methods on +} + +// TypedMemViewTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TypedMemViewTransactorRaw struct { + Contract *TypedMemViewTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTypedMemView creates a new instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemView(address common.Address, backend bind.ContractBackend) (*TypedMemView, error) { + contract, err := bindTypedMemView(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &TypedMemView{TypedMemViewCaller: TypedMemViewCaller{contract: contract}, TypedMemViewTransactor: TypedMemViewTransactor{contract: contract}, TypedMemViewFilterer: TypedMemViewFilterer{contract: contract}}, nil +} + +// NewTypedMemViewCaller creates a new read-only instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemViewCaller(address common.Address, caller bind.ContractCaller) (*TypedMemViewCaller, error) { + contract, err := bindTypedMemView(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TypedMemViewCaller{contract: contract}, nil +} + +// NewTypedMemViewTransactor creates a new write-only instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemViewTransactor(address common.Address, transactor bind.ContractTransactor) (*TypedMemViewTransactor, error) { + contract, err := bindTypedMemView(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TypedMemViewTransactor{contract: contract}, nil +} + +// NewTypedMemViewFilterer creates a new log filterer instance of TypedMemView, bound to a specific deployed contract. +func NewTypedMemViewFilterer(address common.Address, filterer bind.ContractFilterer) (*TypedMemViewFilterer, error) { + contract, err := bindTypedMemView(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TypedMemViewFilterer{contract: contract}, nil +} + +// bindTypedMemView binds a generic wrapper to an already deployed contract. +func bindTypedMemView(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(TypedMemViewABI)) + 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 (_TypedMemView *TypedMemViewRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TypedMemView.Contract.TypedMemViewCaller.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 (_TypedMemView *TypedMemViewRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TypedMemView.Contract.TypedMemViewTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TypedMemView *TypedMemViewRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TypedMemView.Contract.TypedMemViewTransactor.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 (_TypedMemView *TypedMemViewCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _TypedMemView.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 (_TypedMemView *TypedMemViewTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _TypedMemView.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_TypedMemView *TypedMemViewTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _TypedMemView.Contract.contract.Transact(opts, method, params...) +} + +// NULL is a free data retrieval call binding the contract method 0xf26be3fc. +// +// Solidity: function NULL() view returns(bytes29) +func (_TypedMemView *TypedMemViewCaller) NULL(opts *bind.CallOpts) ([29]byte, error) { + var out []interface{} + err := _TypedMemView.contract.Call(opts, &out, "NULL") + + if err != nil { + return *new([29]byte), err + } + + out0 := *abi.ConvertType(out[0], new([29]byte)).(*[29]byte) + + return out0, err + +} + +// NULL is a free data retrieval call binding the contract method 0xf26be3fc. +// +// Solidity: function NULL() view returns(bytes29) +func (_TypedMemView *TypedMemViewSession) NULL() ([29]byte, error) { + return _TypedMemView.Contract.NULL(&_TypedMemView.CallOpts) +} + +// NULL is a free data retrieval call binding the contract method 0xf26be3fc. +// +// Solidity: function NULL() view returns(bytes29) +func (_TypedMemView *TypedMemViewCallerSession) NULL() ([29]byte, error) { + return _TypedMemView.Contract.NULL(&_TypedMemView.CallOpts) +} diff --git a/core/contracts/test/attestationharness/attestationharness.contractinfo.json b/core/contracts/test/attestationharness/attestationharness.contractinfo.json new file mode 100644 index 0000000000..7759629694 --- /dev/null +++ b/core/contracts/test/attestationharness/attestationharness.contractinfo.json @@ -0,0 +1 @@ +{"solidity/AttestationHarness.sol:Attestation":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220174c7e2cc841c5259dfc83352f41e0130d1b4723ec6fa05b680a64dd0aedc30e64736f6c634300080d0033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220174c7e2cc841c5259dfc83352f41e0130d1b4723ec6fa05b680a64dd0aedc30e64736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \ncontract AttestationHarness {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n function formatAttestation(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root,\n bytes memory _signature\n ) public pure returns (bytes memory) {\n return\n Attestation.formatAttestation(\n formatAttestationData(_domain, _nonce, _root),\n _signature\n );\n }\n\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) public pure returns (bytes memory) {\n return Attestation.formatAttestationData(_domain, _nonce, _root);\n }\n\n function isAttestation(bytes memory _attestation) public pure returns (bool) {\n return _attestation.ref(0).isAttestation();\n }\n\n function domain(bytes memory _attestation) public pure returns (uint32) {\n return _attestation.ref(0).attestationDomain();\n }\n\n function nonce(bytes memory _attestation) public pure returns (uint32) {\n return _attestation.ref(0).attestationNonce();\n }\n\n function root(bytes memory _attestation) public pure returns (bytes32) {\n return _attestation.ref(0).attestationRoot();\n }\n\n function data(bytes memory _attestation) public view returns (bytes memory) {\n return _attestation.ref(0).attestationData().clone();\n }\n\n function signature(bytes memory _attestation) public view returns (bytes memory) {\n return _attestation.ref(0).attestationSignature().clone();\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"32270:3216:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;32270:3216:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"32270:3216:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"OFFSET_HOME_DOMAIN":{"details":"AttestationData memory layout [000 .. 004): homeDomain uint32 4 bytes [004 .. 008): nonce uint32 4 bytes [008 .. 040): root bytes32 32 bytes Attestation memory layout [000 .. 040): data bytes 40 bytes (see above) [040 .. END): signature bytes ?? bytes (64/65 bytes)"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_HOME_DOMAIN\":{\"details\":\"AttestationData memory layout [000 .. 004): homeDomain uint32 4 bytes [004 .. 008): nonce uint32 4 bytes [008 .. 040): root bytes32 32 bytes Attestation memory layout [000 .. 040): data bytes 40 bytes (see above) [040 .. END): signature bytes ?? bytes (64/65 bytes)\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationHarness.sol\":\"Attestation\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationHarness.sol\":{\"keccak256\":\"0xa1ecb092d1bb125607ee9b568767f9cf0366164f77583e3051f0fb987bc51f77\",\"urls\":[\"bzz-raw://c9a84f9b2d6e2e88831aa5435b0ad28738a7ca90a0abe8a5e3d7247797b99d03\",\"dweb:/ipfs/QmQbt2LQ26nimJJ4DWfzUB5EJ4ufLmYGdWnkDGV1ff7HqE\"]}},\"version\":1}"},"hashes":{}},"solidity/AttestationHarness.sol:AttestationHarness":{"code":"0x608060405234801561001057600080fd5b5061109b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c2e9e2081161005b578063c2e9e20814610110578063d3d29df114610131578063ef6d4cad14610144578063fbad03131461015757600080fd5b80633ae7034d1461008d5780634d358d65146100b55780634e765004146100d557806358d18e3a146100fd575b600080fd5b6100a061009b366004610cd0565b61016a565b60405190151581526020015b60405180910390f35b6100c86100c3366004610d1e565b61019f565b6040516100ac9190610e00565b6100e86100e3366004610cd0565b6101c0565b60405163ffffffff90911681526020016100ac565b6100c861010b366004610cd0565b6101da565b61012361011e366004610cd0565b610203565b6040519081526020016100ac565b6100c861013f366004610cd0565b61021d565b6100c8610152366004610e13565b61023b565b6100e8610165366004610cd0565b610297565b600061019961017983836102b1565b62ffffff1916602860189190911c6bffffffffffffffffffffffff161190565b92915050565b60606101b56101af86868661023b565b836102d5565b90505b949350505050565b60006101996101cf83836102b1565b62ffffff1916610301565b60606101996101f86101ed8460006102b1565b62ffffff1916610315565b62ffffff1916610348565b600061019961021283836102b1565b62ffffff191661039b565b60606101996101f86102308460006102b1565b62ffffff19166103b0565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086811b8216602084015285901b16602482015260288082018490528251808303909101815260489091019091525b9392505050565b60006101996102a683836102b1565b62ffffff19166103c5565b8151600090602084016102cc64ffffffffff851682846103d9565b95945050505050565b606082826040516020016102ea929190610e4f565b604051602081830303815290604052905092915050565b600061019962ffffff198316600480610420565b6000610199602861033881601886901c6bffffffffffffffffffffffff16610ead565b62ffffff19851691906000610450565b60606000806103658460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050604051915081925061038a84836020016104d4565b508181016020016040529052919050565b600061019962ffffff198316600860206106a8565b600061019962ffffff19831682602881610450565b600061019962ffffff198316826004610420565b6000806103e68385610ec4565b90506040518111156103f6575060005b8060000361040b5762ffffff19915050610290565b5050606092831b9190911790911b1760181b90565b600061042d826020610edc565b610438906008610eff565b60ff166104468585856106a8565b901c949350505050565b60008061046b8660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506104848661089a565b8461048f8784610ec4565b6104999190610ec4565b11156104ac5762ffffff199150506101b8565b6104b68582610ec4565b90506104ca8364ffffffffff1682866103d9565b9695505050505050565b600062ffffff1980841603610570576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201527f657220646572656600000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610579836108e2565b610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201527f696e7465722064657265660000000000000000000000000000000000000000006064820152608401610567565b600061061f8460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060006106498560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050600060405190508481111561066e5760206060fd5b8285848460045afa506104ca6106848760d81c90565b70ffffffffff000000000000000000000000606091821b168717901b841760181b90565b60008160ff166000036106bd57506000610290565b6106d58460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166106f060ff841685610ec4565b11156107825761074f6107118560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166107378660181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16858560ff1661091f565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105679190610e00565b60208260ff161115610816576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e2033322062797465730000000000006064820152608401610567565b6008820260006108348660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060007f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84011d91909501511695945050505050565b60006108b48260181c6bffffffffffffffffffffffff1690565b6108cc8360781c6bffffffffffffffffffffffff1690565b016bffffffffffffffffffffffff169050919050565b60006108ee8260d81c90565b64ffffffffff1664ffffffffff0361090857506000919050565b60006109138361089a565b60405110199392505050565b6060600061092c8661098d565b915050600061093a8661098d565b91505060006109488661098d565b91505060006109568661098d565b915050838383836040516020016109709493929190610f28565b604051602081830303815290604052945050505050949350505050565b600080601f5b600f8160ff161115610a005760006109ac826008610eff565b60ff1685901c90506109bd81610a77565b61ffff16841793508160ff166010146109d857601084901b93505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01610993565b50600f5b60ff8160ff161015610a71576000610a1d826008610eff565b60ff1685901c9050610a2e81610a77565b61ffff16831792508160ff16600014610a4957601083901b92505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01610a04565b50915091565b6000610a8960048360ff16901c610aa9565b60ff1661ffff919091161760081b610aa082610aa9565b60ff1617919050565b600060f08083179060ff82169003610ac45750603092915050565b8060ff1660f103610ad85750603192915050565b8060ff1660f203610aec5750603292915050565b8060ff1660f303610b005750603392915050565b8060ff1660f403610b145750603492915050565b8060ff1660f503610b285750603592915050565b8060ff1660f603610b3c5750603692915050565b8060ff1660f703610b505750603792915050565b8060ff1660f803610b645750603892915050565b8060ff1660f903610b785750603992915050565b8060ff1660fa03610b8c5750606192915050565b8060ff1660fb03610ba05750606292915050565b8060ff1660fc03610bb45750606392915050565b8060ff1660fd03610bc85750606492915050565b8060ff1660fe03610bdc5750606592915050565b8060ff1660ff03610bf05750606692915050565b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c3657600080fd5b813567ffffffffffffffff80821115610c5157610c51610bf6565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c9757610c97610bf6565b81604052838152866020858801011115610cb057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610ce257600080fd5b813567ffffffffffffffff811115610cf957600080fd5b6101b884828501610c25565b803563ffffffff81168114610d1957600080fd5b919050565b60008060008060808587031215610d3457600080fd5b610d3d85610d05565b9350610d4b60208601610d05565b925060408501359150606085013567ffffffffffffffff811115610d6e57600080fd5b610d7a87828801610c25565b91505092959194509250565b60005b83811015610da1578181015183820152602001610d89565b83811115610db0576000848401525b50505050565b60008151808452610dce816020860160208601610d86565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006102906020830184610db6565b600080600060608486031215610e2857600080fd5b610e3184610d05565b9250610e3f60208501610d05565b9150604084013590509250925092565b60008351610e61818460208801610d86565b835190830190610e75818360208801610d86565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610ebf57610ebf610e7e565b500390565b60008219821115610ed757610ed7610e7e565b500190565b600060ff821660ff841680821015610ef657610ef6610e7e565b90039392505050565b600060ff821660ff84168160ff0481118215151615610f2057610f20610e7e565b029392505050565b7f54797065644d656d566965772f696e646578202d204f76657272616e2074686581527f20766965772e20536c696365206973206174203078000000000000000000000060208201527fffffffffffff000000000000000000000000000000000000000000000000000060d086811b821660358401527f2077697468206c656e6774682030780000000000000000000000000000000000603b840181905286821b8316604a8501527f2e20417474656d7074656420746f20696e646578206174206f6666736574203060508501527f7800000000000000000000000000000000000000000000000000000000000000607085015285821b83166071850152607784015283901b1660868201527f2e00000000000000000000000000000000000000000000000000000000000000608c8201526000608d82016104ca56fea26469706673582212203593e560245ba73c8625f6dae52e94664942ef8a7d7beda4098e2242844aab2064736f6c634300080d0033","runtime-code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063c2e9e2081161005b578063c2e9e20814610110578063d3d29df114610131578063ef6d4cad14610144578063fbad03131461015757600080fd5b80633ae7034d1461008d5780634d358d65146100b55780634e765004146100d557806358d18e3a146100fd575b600080fd5b6100a061009b366004610cd0565b61016a565b60405190151581526020015b60405180910390f35b6100c86100c3366004610d1e565b61019f565b6040516100ac9190610e00565b6100e86100e3366004610cd0565b6101c0565b60405163ffffffff90911681526020016100ac565b6100c861010b366004610cd0565b6101da565b61012361011e366004610cd0565b610203565b6040519081526020016100ac565b6100c861013f366004610cd0565b61021d565b6100c8610152366004610e13565b61023b565b6100e8610165366004610cd0565b610297565b600061019961017983836102b1565b62ffffff1916602860189190911c6bffffffffffffffffffffffff161190565b92915050565b60606101b56101af86868661023b565b836102d5565b90505b949350505050565b60006101996101cf83836102b1565b62ffffff1916610301565b60606101996101f86101ed8460006102b1565b62ffffff1916610315565b62ffffff1916610348565b600061019961021283836102b1565b62ffffff191661039b565b60606101996101f86102308460006102b1565b62ffffff19166103b0565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086811b8216602084015285901b16602482015260288082018490528251808303909101815260489091019091525b9392505050565b60006101996102a683836102b1565b62ffffff19166103c5565b8151600090602084016102cc64ffffffffff851682846103d9565b95945050505050565b606082826040516020016102ea929190610e4f565b604051602081830303815290604052905092915050565b600061019962ffffff198316600480610420565b6000610199602861033881601886901c6bffffffffffffffffffffffff16610ead565b62ffffff19851691906000610450565b60606000806103658460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050604051915081925061038a84836020016104d4565b508181016020016040529052919050565b600061019962ffffff198316600860206106a8565b600061019962ffffff19831682602881610450565b600061019962ffffff198316826004610420565b6000806103e68385610ec4565b90506040518111156103f6575060005b8060000361040b5762ffffff19915050610290565b5050606092831b9190911790911b1760181b90565b600061042d826020610edc565b610438906008610eff565b60ff166104468585856106a8565b901c949350505050565b60008061046b8660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff1690506104848661089a565b8461048f8784610ec4565b6104999190610ec4565b11156104ac5762ffffff199150506101b8565b6104b68582610ec4565b90506104ca8364ffffffffff1682866103d9565b9695505050505050565b600062ffffff1980841603610570576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201527f657220646572656600000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610579836108e2565b610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201527f696e7465722064657265660000000000000000000000000000000000000000006064820152608401610567565b600061061f8460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060006106498560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff169050600060405190508481111561066e5760206060fd5b8285848460045afa506104ca6106848760d81c90565b70ffffffffff000000000000000000000000606091821b168717901b841760181b90565b60008160ff166000036106bd57506000610290565b6106d58460181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166106f060ff841685610ec4565b11156107825761074f6107118560781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff166107378660181c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16858560ff1661091f565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105679190610e00565b60208260ff161115610816576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e2033322062797465730000000000006064820152608401610567565b6008820260006108348660781c6bffffffffffffffffffffffff1690565b6bffffffffffffffffffffffff16905060007f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84011d91909501511695945050505050565b60006108b48260181c6bffffffffffffffffffffffff1690565b6108cc8360781c6bffffffffffffffffffffffff1690565b016bffffffffffffffffffffffff169050919050565b60006108ee8260d81c90565b64ffffffffff1664ffffffffff0361090857506000919050565b60006109138361089a565b60405110199392505050565b6060600061092c8661098d565b915050600061093a8661098d565b91505060006109488661098d565b91505060006109568661098d565b915050838383836040516020016109709493929190610f28565b604051602081830303815290604052945050505050949350505050565b600080601f5b600f8160ff161115610a005760006109ac826008610eff565b60ff1685901c90506109bd81610a77565b61ffff16841793508160ff166010146109d857601084901b93505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01610993565b50600f5b60ff8160ff161015610a71576000610a1d826008610eff565b60ff1685901c9050610a2e81610a77565b61ffff16831792508160ff16600014610a4957601083901b92505b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01610a04565b50915091565b6000610a8960048360ff16901c610aa9565b60ff1661ffff919091161760081b610aa082610aa9565b60ff1617919050565b600060f08083179060ff82169003610ac45750603092915050565b8060ff1660f103610ad85750603192915050565b8060ff1660f203610aec5750603292915050565b8060ff1660f303610b005750603392915050565b8060ff1660f403610b145750603492915050565b8060ff1660f503610b285750603592915050565b8060ff1660f603610b3c5750603692915050565b8060ff1660f703610b505750603792915050565b8060ff1660f803610b645750603892915050565b8060ff1660f903610b785750603992915050565b8060ff1660fa03610b8c5750606192915050565b8060ff1660fb03610ba05750606292915050565b8060ff1660fc03610bb45750606392915050565b8060ff1660fd03610bc85750606492915050565b8060ff1660fe03610bdc5750606592915050565b8060ff1660ff03610bf05750606692915050565b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c3657600080fd5b813567ffffffffffffffff80821115610c5157610c51610bf6565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c9757610c97610bf6565b81604052838152866020858801011115610cb057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610ce257600080fd5b813567ffffffffffffffff811115610cf957600080fd5b6101b884828501610c25565b803563ffffffff81168114610d1957600080fd5b919050565b60008060008060808587031215610d3457600080fd5b610d3d85610d05565b9350610d4b60208601610d05565b925060408501359150606085013567ffffffffffffffff811115610d6e57600080fd5b610d7a87828801610c25565b91505092959194509250565b60005b83811015610da1578181015183820152602001610d89565b83811115610db0576000848401525b50505050565b60008151808452610dce816020860160208601610d86565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006102906020830184610db6565b600080600060608486031215610e2857600080fd5b610e3184610d05565b9250610e3f60208501610d05565b9150604084013590509250925092565b60008351610e61818460208801610d86565b835190830190610e75818360208801610d86565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610ebf57610ebf610e7e565b500390565b60008219821115610ed757610ed7610e7e565b500190565b600060ff821660ff841680821015610ef657610ef6610e7e565b90039392505050565b600060ff821660ff84168160ff0481118215151615610f2057610f20610e7e565b029392505050565b7f54797065644d656d566965772f696e646578202d204f76657272616e2074686581527f20766965772e20536c696365206973206174203078000000000000000000000060208201527fffffffffffff000000000000000000000000000000000000000000000000000060d086811b821660358401527f2077697468206c656e6774682030780000000000000000000000000000000000603b840181905286821b8316604a8501527f2e20417474656d7074656420746f20696e646578206174206f6666736574203060508501527f7800000000000000000000000000000000000000000000000000000000000000607085015285821b83166071850152607784015283901b1660868201527f2e00000000000000000000000000000000000000000000000000000000000000608c8201526000608d82016104ca56fea26469706673582212203593e560245ba73c8625f6dae52e94664942ef8a7d7beda4098e2242844aab2064736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \ncontract AttestationHarness {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n function formatAttestation(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root,\n bytes memory _signature\n ) public pure returns (bytes memory) {\n return\n Attestation.formatAttestation(\n formatAttestationData(_domain, _nonce, _root),\n _signature\n );\n }\n\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) public pure returns (bytes memory) {\n return Attestation.formatAttestationData(_domain, _nonce, _root);\n }\n\n function isAttestation(bytes memory _attestation) public pure returns (bool) {\n return _attestation.ref(0).isAttestation();\n }\n\n function domain(bytes memory _attestation) public pure returns (uint32) {\n return _attestation.ref(0).attestationDomain();\n }\n\n function nonce(bytes memory _attestation) public pure returns (uint32) {\n return _attestation.ref(0).attestationNonce();\n }\n\n function root(bytes memory _attestation) public pure returns (bytes32) {\n return _attestation.ref(0).attestationRoot();\n }\n\n function data(bytes memory _attestation) public view returns (bytes memory) {\n return _attestation.ref(0).attestationData().clone();\n }\n\n function signature(bytes memory _attestation) public view returns (bytes memory) {\n return _attestation.ref(0).attestationSignature().clone();\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"35492:1584:0:-:0;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"35492:1584:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36208:136;;;;;;:::i;:::-;;:::i;:::-;;;1475:14:1;;1468:22;1450:41;;1438:2;1423:18;36208:136:0;;;;;;;;35632:341;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;36491:133::-;;;;;;:::i;:::-;;:::i;:::-;;;3188:10:1;3176:23;;;3158:42;;3146:2;3131:18;36491:133:0;3014:192:1;36919:155:0;;;;;;:::i;:::-;;:::i;36630:132::-;;;;;;:::i;:::-;;:::i;:::-;;;3357:25:1;;;3345:2;3330:18;36630:132:0;3211:177:1;36768:145:0;;;;;;:::i;:::-;;:::i;35979:223::-;;;;;;:::i;:::-;;:::i;36350:135::-;;;;;;:::i;:::-;;:::i;36208:136::-;36279:4;36302:35;:19;:12;36279:4;36302:16;:19::i;:::-;-1:-1:-1;;36302:33:0;32963:2;16492;16488:16;;;;2670:26;16484:28;34217:37;;34044:217;36302:35;36295:42;36208:136;-1:-1:-1;;36208:136:0:o;35632:341::-;35789:12;35832:134;35879:45;35901:7;35910:6;35918:5;35879:21;:45::i;:::-;35942:10;35832:29;:134::i;:::-;35813:153;;35632:341;;;;;;;:::o;36491:133::-;36554:6;36579:38;:19;:12;36554:6;36579:16;:19::i;:::-;-1:-1:-1;;36579:36:0;;:38::i;36919:155::-;36986:12;37017:50;:42;:19;:12;37034:1;37017:16;:19::i;:::-;-1:-1:-1;;37017:40:0;;:42::i;:::-;-1:-1:-1;;37017:48:0;;:50::i;36630:132::-;36692:7;36718:37;:19;:12;36692:7;36718:16;:19::i;:::-;-1:-1:-1;;36718:35:0;;:37::i;36768:145::-;36830:12;36861:45;:37;:19;:12;36878:1;36861:16;:19::i;:::-;-1:-1:-1;;36861:35:0;;:37::i;35979:223::-;33898:40;;;4703:66:1;4798:3;4794:16;;;4790:25;;33898:40:0;;;4778:38:1;4849:16;;;4845:25;4832:11;;;4825:46;4887:11;;;;4880:27;;;33898:40:0;;;;;;;;;;4923:12:1;;;;33898:40:0;;;35979:223;;;;;;:::o;36350:135::-;36414:6;36439:39;:19;:12;36414:6;36439:16;:19::i;:::-;-1:-1:-1;;36439:37:0;;:39::i;13655:359::-;13759:10;;13725:7;;13906:4;13897:14;;13981:26;;;;13897:14;13759:10;13981:5;:26::i;:::-;13974:33;13655:359;-1:-1:-1;;;;;13655:359:0:o;33281:196::-;33400:12;33452:5;33459:10;33435:35;;;;;;;;;:::i;:::-;;;;;;;;;;;;;33428:42;;33281:196;;;;:::o;34615:136::-;34679:6;34711:32;-1:-1:-1;;34711:15:0;;32857:1;;34711:15;:32::i;35312:172::-;35380:7;35406:71;32963:2;35436:37;32963:2;16492;16488:16;;;2670:26;16484:28;35436:37;:::i;:::-;-1:-1:-1;;35406:11:0;;;:71;35475:1;35406:11;:71::i;28308:632::-;28363:16;28391:11;28412:12;28427;28431:7;16492:2;16488:16;2670:26;16484:28;;16246:282;28427:12;28412:27;;;;28549:4;28543:11;28536:18;;28604:3;28597:10;;28650:33;28663:7;28672:3;28678:4;28672:10;28650:12;:33::i;:::-;-1:-1:-1;28807:14:0;;;28823:4;28803:25;28797:4;28790:39;28870:17;;28308:632;;-1:-1:-1;28308:632:0:o;34844:124::-;34907:7;34933:28;-1:-1:-1;;34933:11:0;;32904:1;34958:2;34933:11;:28::i;35074:155::-;35137:7;35163:59;-1:-1:-1;;35163:11:0;;35137:7;32963:2;35137:7;35163:11;:59::i;34358:143::-;34423:6;34455:38;-1:-1:-1;;34455:15:0;;34423:6;34491:1;34455:15;:38::i;12796:462::-;12907:15;;12949:11;12956:4;12949;:11;:::i;:::-;12934:26;;13075:4;13069:11;13063:4;13060:21;13057:66;;;-1:-1:-1;13108:1:0;13057:66;13146:4;13154:1;13146:9;13142:51;;-1:-1:-1;;13171:11:0;;;;;13142:51;-1:-1:-1;;12065:2:0;12061:27;;;12135:17;;;;12127:26;;;12199:17;12195:2;12191:26;;12796:462::o;21121:221::-;21240:14;21318:11;21323:6;21318:2;:11;:::i;:::-;21317:17;;21333:1;21317:17;:::i;:::-;21273:62;;21281:30;21287:7;21296:6;21304;21281:5;:30::i;:::-;21273:62;;;21121:221;-1:-1:-1;;;;21121:221:0:o;17129:399::-;17268:7;17287:12;17302;17306:7;15386:3;15382:17;2670:26;15378:29;;15059:364;17302:12;17287:27;;;;17398:12;17402:7;17398:3;:12::i;:::-;17391:4;17375:13;17382:6;17375:4;:13;:::i;:::-;:20;;;;:::i;:::-;:35;17371:77;;;-1:-1:-1;;17426:11:0;;;;;17371:77;17465:13;17472:6;17465:4;:13;:::i;:::-;17458:20;;17495:26;17501:7;17495:26;;17510:4;17516;17495:5;:26::i;:::-;17488:33;17129:399;-1:-1:-1;;;;;;17129:399:0:o;27036:902::-;27114:15;-1:-1:-1;;7972:15:0;;;;27141:69;;;;;;;5724:2:1;27141:69:0;;;5706:21:1;5763:2;5743:18;;;5736:30;5802:34;5782:18;;;5775:62;5873:10;5853:18;;;5846:38;5901:19;;27141:69:0;;;;;;;;;27228:16;27236:7;27228;:16::i;:::-;27220:72;;;;;;;6133:2:1;27220:72:0;;;6115:21:1;6172:2;6152:18;;;6145:30;6211:34;6191:18;;;6184:62;6282:13;6262:18;;;6255:41;6313:19;;27220:72:0;5931:407:1;27220:72:0;27302:12;27317;27321:7;16492:2;16488:16;2670:26;16484:28;;16246:282;27317:12;27302:27;;;;27339:15;27357:12;27361:7;15386:3;15382:17;2670:26;15378:29;;15059:364;27357:12;27339:30;;;;27380:11;27501:4;27495:11;27488:18;;27588:7;27583:3;27580:16;27577:94;;;27628:4;27622;27615:18;27577:94;27843:4;27834:7;27828:4;27819:7;27816:1;27809:5;27798:50;27794:55;27879:52;27900:15;27907:7;14417:3;14413:17;;14206:268;27900:15;12061:27;12065:2;12061:27;;;;12135:17;;12127:26;;12199:17;;12195:2;12191:26;;11811:446;20004:771;20119:14;20149:6;:11;;20159:1;20149:11;20145:59;;-1:-1:-1;20191:1:0;20176:17;;20145:59;20235:12;20239:7;16492:2;16488:16;2670:26;16484:28;;16246:282;20235:12;20217:30;;:15;;;;:6;:15;:::i;:::-;:30;20213:137;;;20270:68;20286:12;20290:7;15386:3;15382:17;2670:26;15378:29;;15059:364;20286:12;20270:68;;20300:12;20304:7;16492:2;16488:16;2670:26;16484:28;;16246:282;20300:12;20270:68;;20314:6;20330;20322:15;;20270;:68::i;:::-;20263:76;;;;;;;;;;;:::i;20213:137::-;20377:2;20367:6;:12;;;;20359:83;;;;;;;6769:2:1;20359:83:0;;;6751:21:1;6808:2;6788:18;;;6781:30;6847:34;6827:18;;;6820:62;6918:28;6898:18;;;6891:56;6964:19;;20359:83:0;6567:422:1;20359:83:0;20523:1;20514:10;;20453:15;20559:12;20563:7;15386:3;15382:17;2670:26;15378:29;;15059:364;20559:12;20544:27;;;-1:-1:-1;20581:13:0;7488:66;7458:12;;;7437:131;20733:17;;;;20727:24;20723:36;;;-1:-1:-1;;;;;20004:771:0:o;16702:147::-;16755:7;16820:12;16824:7;16492:2;16488:16;2670:26;16484:28;;16246:282;16820:12;16805;16809:7;15386:3;15382:17;2670:26;15378:29;;15059:364;16805:12;:27;16798:34;;;;16702:147;;;:::o;8645:333::-;8702:8;8726:15;8733:7;14417:3;14413:17;;14206:268;8726:15;:31;;8745:12;8726:31;8722:74;;-1:-1:-1;8780:5:0;;8645:333;-1:-1:-1;8645:333:0:o;8722:74::-;8805:12;8820;8824:7;8820:3;:12::i;:::-;8955:4;8949:11;-1:-1:-1;8936:26:0;;8645:333;-1:-1:-1;;;8645:333:0:o;18761:741::-;18907:17;18939:9;18952:15;18962:4;18952:9;:15::i;:::-;18936:31;;;18980:9;18993:15;19003:4;18993:9;:15::i;:::-;18977:31;;;19021:9;19034:17;19044:6;19034:9;:17::i;:::-;19018:33;;;19064:9;19077:17;19087:6;19077:9;:17::i;:::-;19061:33;;;19244:1;19306;19386;19448;19130:355;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;19104:391;;18926:576;;;;18761:741;;;;;;:::o;5031:667::-;5085:13;;5141:2;5126:258;5149:2;5145:1;:6;;;5126:258;;;5169:11;5196:5;:1;5200;5196:5;:::i;:::-;5189:13;;:2;:13;;5169:34;;5226:14;5234:5;5226:7;:14::i;:::-;5217:23;;;;;;5258:1;:7;;5263:2;5258:7;5254:58;;5295:2;5285:12;;;;;5254:58;-1:-1:-1;5353:6:0;;5126:258;;;-1:-1:-1;5447:2:0;5432:260;5455:3;5451:1;:7;;;5432:260;;;5476:11;5503:5;:1;5507;5503:5;:::i;:::-;5496:13;;:2;:13;;5476:34;;5534:14;5542:5;5534:7;:14::i;:::-;5524:24;;;;;;5566:1;:6;;5571:1;5566:6;5562:58;;5603:2;5592:13;;;;;5562:58;-1:-1:-1;5661:6:0;;5432:260;;;;5031:667;;;:::o;4508:199::-;4558:14;4595:18;4611:1;4605:2;:7;;;;4595:9;:18::i;:::-;4584:29;;4637:13;;;;;;4649:1;4637:13;4671;4681:2;4671:9;:13::i;:::-;4660:24;;;;4508:199;-1:-1:-1;4508:199:0:o;2943:1393::-;2995:10;3161:4;3156:9;;;;3207:15;;;;;3203:57;;-1:-1:-1;3245:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3203:57::-;3278:7;:15;;3289:4;3278:15;3274:57;;-1:-1:-1;3316:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3274:57::-;3349:7;:15;;3360:4;3349:15;3345:57;;-1:-1:-1;3387:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3345:57::-;3420:7;:15;;3431:4;3420:15;3416:57;;-1:-1:-1;3458:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3416:57::-;3491:7;:15;;3502:4;3491:15;3487:57;;-1:-1:-1;3529:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3487:57::-;3562:7;:15;;3573:4;3562:15;3558:57;;-1:-1:-1;3600:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3558:57::-;3633:7;:15;;3644:4;3633:15;3629:57;;-1:-1:-1;3671:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3629:57::-;3704:7;:15;;3715:4;3704:15;3700:57;;-1:-1:-1;3742:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3700:57::-;3775:7;:15;;3786:4;3775:15;3771:57;;-1:-1:-1;3813:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3771:57::-;3846:7;:15;;3857:4;3846:15;3842:57;;-1:-1:-1;3884:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3842:57::-;3917:7;:15;;3928:4;3917:15;3913:57;;-1:-1:-1;3955:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3913:57::-;3988:7;:15;;3999:4;3988:15;3984:57;;-1:-1:-1;4026:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;3984:57::-;4059:7;:15;;4070:4;4059:15;4055:57;;-1:-1:-1;4097:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4055:57::-;4130:7;:15;;4141:4;4130:15;4126:57;;-1:-1:-1;4168:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4126:57::-;4201:7;:15;;4212:4;4201:15;4197:57;;-1:-1:-1;4239:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4197:57::-;4272:7;:15;;4283:4;4272:15;4268:57;;-1:-1:-1;4310:4:0;;2943:1393;-1:-1:-1;;2943:1393:0:o;4268:57::-;3007:1329;2943:1393;;;:::o;14:184:1:-;66:77;63:1;56:88;163:4;160:1;153:15;187:4;184:1;177:15;203:777;245:5;298:3;291:4;283:6;279:17;275:27;265:55;;316:1;313;306:12;265:55;352:6;339:20;378:18;415:2;411;408:10;405:36;;;421:18;;:::i;:::-;555:2;549:9;617:4;609:13;;460:66;605:22;;;629:2;601:31;597:40;585:53;;;653:18;;;673:22;;;650:46;647:72;;;699:18;;:::i;:::-;739:10;735:2;728:22;774:2;766:6;759:18;820:3;813:4;808:2;800:6;796:15;792:26;789:35;786:55;;;837:1;834;827:12;786:55;901:2;894:4;886:6;882:17;875:4;867:6;863:17;850:54;948:1;941:4;936:2;928:6;924:15;920:26;913:37;968:6;959:15;;;;;;203:777;;;;:::o;985:320::-;1053:6;1106:2;1094:9;1085:7;1081:23;1077:32;1074:52;;;1122:1;1119;1112:12;1074:52;1162:9;1149:23;1195:18;1187:6;1184:30;1181:50;;;1227:1;1224;1217:12;1181:50;1250:49;1291:7;1282:6;1271:9;1267:22;1250:49;:::i;1502:163::-;1569:20;;1629:10;1618:22;;1608:33;;1598:61;;1655:1;1652;1645:12;1598:61;1502:163;;;:::o;1670:533::-;1763:6;1771;1779;1787;1840:3;1828:9;1819:7;1815:23;1811:33;1808:53;;;1857:1;1854;1847:12;1808:53;1880:28;1898:9;1880:28;:::i;:::-;1870:38;;1927:37;1960:2;1949:9;1945:18;1927:37;:::i;:::-;1917:47;;2011:2;2000:9;1996:18;1983:32;1973:42;;2066:2;2055:9;2051:18;2038:32;2093:18;2085:6;2082:30;2079:50;;;2125:1;2122;2115:12;2079:50;2148:49;2189:7;2180:6;2169:9;2165:22;2148:49;:::i;:::-;2138:59;;;1670:533;;;;;;;:::o;2208:258::-;2280:1;2290:113;2304:6;2301:1;2298:13;2290:113;;;2380:11;;;2374:18;2361:11;;;2354:39;2326:2;2319:10;2290:113;;;2421:6;2418:1;2415:13;2412:48;;;2456:1;2447:6;2442:3;2438:16;2431:27;2412:48;;2208:258;;;:::o;2471:316::-;2512:3;2550:5;2544:12;2577:6;2572:3;2565:19;2593:63;2649:6;2642:4;2637:3;2633:14;2626:4;2619:5;2615:16;2593:63;:::i;:::-;2701:2;2689:15;2706:66;2685:88;2676:98;;;;2776:4;2672:109;;2471:316;-1:-1:-1;;2471:316:1:o;2792:217::-;2939:2;2928:9;2921:21;2902:4;2959:44;2999:2;2988:9;2984:18;2976:6;2959:44;:::i;3393:324::-;3468:6;3476;3484;3537:2;3525:9;3516:7;3512:23;3508:32;3505:52;;;3553:1;3550;3543:12;3505:52;3576:28;3594:9;3576:28;:::i;:::-;3566:38;;3623:37;3656:2;3645:9;3641:18;3623:37;:::i;:::-;3613:47;;3707:2;3696:9;3692:18;3679:32;3669:42;;3393:324;;;;;:::o;3722:466::-;3897:3;3935:6;3929:13;3951:53;3997:6;3992:3;3985:4;3977:6;3973:17;3951:53;:::i;:::-;4067:13;;4026:16;;;;4089:57;4067:13;4026:16;4123:4;4111:17;;4089:57;:::i;:::-;4162:20;;3722:466;-1:-1:-1;;;;3722:466:1:o;4193:184::-;4245:77;4242:1;4235:88;4342:4;4339:1;4332:15;4366:4;4363:1;4356:15;4382:125;4422:4;4450:1;4447;4444:8;4441:34;;;4455:18;;:::i;:::-;-1:-1:-1;4492:9:1;;4382:125::o;4946:128::-;4986:3;5017:1;5013:6;5010:1;5007:13;5004:39;;;5023:18;;:::i;:::-;-1:-1:-1;5059:9:1;;4946:128::o;5079:195::-;5117:4;5154;5151:1;5147:12;5186:4;5183:1;5179:12;5211:3;5206;5203:12;5200:38;;;5218:18;;:::i;:::-;5255:13;;;5079:195;-1:-1:-1;;;5079:195:1:o;5279:238::-;5317:7;5357:4;5354:1;5350:12;5389:4;5386:1;5382:12;5449:3;5443:4;5439:14;5434:3;5431:23;5424:3;5417:11;5410:19;5406:49;5403:75;;;5458:18;;:::i;:::-;5498:13;;5279:238;-1:-1:-1;;;5279:238:1:o;7113:1391::-;7835:34;7823:47;;7900:23;7895:2;7886:12;;7879:45;7943:66;8047:3;8043:16;;;8039:25;;8034:2;8025:12;;8018:47;8084:17;8126:2;8117:12;;8110:24;;;8168:16;;;8164:25;;8159:2;8150:12;;8143:47;8220:34;8215:2;8206:12;;8199:56;8286:3;8280;8271:13;;8264:26;8325:16;;;8321:25;;8315:3;8306:13;;8299:48;8372:3;8363:13;;8356:25;8416:16;;;8412:25;8406:3;8397:13;;8390:48;7071:3;8493;8484:13;;7059:16;-1:-1:-1;7091:11:1;;;8454:44;6994:114","abiDefinition":[{"inputs":[{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"data","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"domain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint32","name":"_nonce","type":"uint32"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"formatAttestation","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint32","name":"_nonce","type":"uint32"},{"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"formatAttestationData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"isAttestation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"nonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"root","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_attestation","type":"bytes"}],"name":"signature","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"domain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"formatAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"_root\",\"type\":\"bytes32\"}],\"name\":\"formatAttestationData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"isAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"root\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_attestation\",\"type\":\"bytes\"}],\"name\":\"signature\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationHarness.sol\":\"AttestationHarness\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationHarness.sol\":{\"keccak256\":\"0xa1ecb092d1bb125607ee9b568767f9cf0366164f77583e3051f0fb987bc51f77\",\"urls\":[\"bzz-raw://c9a84f9b2d6e2e88831aa5435b0ad28738a7ca90a0abe8a5e3d7247797b99d03\",\"dweb:/ipfs/QmQbt2LQ26nimJJ4DWfzUB5EJ4ufLmYGdWnkDGV1ff7HqE\"]}},\"version\":1}"},"hashes":{"data(bytes)":"d3d29df1","domain(bytes)":"fbad0313","formatAttestation(uint32,uint32,bytes32,bytes)":"4d358d65","formatAttestationData(uint32,uint32,bytes32)":"ef6d4cad","isAttestation(bytes)":"3ae7034d","nonce(bytes)":"4e765004","root(bytes)":"c2e9e208","signature(bytes)":"58d18e3a"}},"solidity/AttestationHarness.sol:TypedMemView":{"code":"0x60c9610038600b82828239805160001a607314602b57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b605e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000081565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000909116815260200160405180910390f3fea26469706673582212209ea5273888337b1496057049c57d442a265b849725273d42b7024200b638c69464736f6c634300080d0033","runtime-code":"0x730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063f26be3fc146038575b600080fd5b605e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000081565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000909116815260200160405180910390f3fea26469706673582212209ea5273888337b1496057049c57d442a265b849725273d42b7024200b638c69464736f6c634300080d0033","info":{"source":"pragma solidity 0.8.13;\n\n\nlibrary TypedMemView {\n // Why does this exist?\n // the solidity `bytes memory` type has a few weaknesses.\n // 1. You can't index ranges effectively\n // 2. You can't slice without copying\n // 3. The underlying data may represent any type\n // 4. Solidity never deallocates memory, and memory costs grow\n // superlinearly\n\n // By using a memory view instead of a `bytes memory` we get the following\n // advantages:\n // 1. Slices are done on the stack, by manipulating the pointer\n // 2. We can index arbitrary ranges and quickly convert them to stack types\n // 3. We can insert type info into the pointer, and typecheck at runtime\n\n // This makes `TypedMemView` a useful tool for efficient zero-copy\n // algorithms.\n\n // Why bytes29?\n // We want to avoid confusion between views, digests, and other common\n // types so we chose a large and uncommonly used odd number of bytes\n //\n // Note that while bytes are left-aligned in a word, integers and addresses\n // are right-aligned. This means when working in assembly we have to\n // account for the 3 unused bytes on the righthand side\n //\n // First 5 bytes are a type flag.\n // - ff_ffff_fffe is reserved for unknown type.\n // - ff_ffff_ffff is reserved for invalid types/errors.\n // next 12 are memory address\n // next 12 are len\n // bottom 3 bytes are empty\n\n // Assumptions:\n // - non-modification of memory.\n // - No Solidity updates\n // - - wrt free mem point\n // - - wrt bytes representation in memory\n // - - wrt memory addressing in general\n\n // Usage:\n // - create type constants\n // - use `assertType` for runtime type assertions\n // - - unfortunately we can't do this at compile time yet :(\n // - recommended: implement modifiers that perform type checking\n // - - e.g.\n // - - `uint40 constant MY_TYPE = 3;`\n // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`\n // - instantiate a typed view from a bytearray using `ref`\n // - use `index` to inspect the contents of the view\n // - use `slice` to create smaller views into the same memory\n // - - `slice` can increase the offset\n // - - `slice can decrease the length`\n // - - must specify the output type of `slice`\n // - - `slice` will return a null view if you try to overrun\n // - - make sure to explicitly check for this with `notNull` or `assertType`\n // - use `equal` for typed comparisons.\n\n // The null view\n bytes29 public constant NULL = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;\n uint8 constant TWELVE_BYTES = 96;\n\n /**\n * @notice Returns the encoded hex character that represents the lower 4 bits of the argument.\n * @param _b The byte\n * @return char - The encoded hex character\n */\n function nibbleHex(uint8 _b) internal pure returns (uint8 char) {\n // This can probably be done more efficiently, but it's only in error\n // paths, so we don't really care :)\n uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4\n if (_nibble == 0xf0) {\n return 0x30;\n } // 0\n if (_nibble == 0xf1) {\n return 0x31;\n } // 1\n if (_nibble == 0xf2) {\n return 0x32;\n } // 2\n if (_nibble == 0xf3) {\n return 0x33;\n } // 3\n if (_nibble == 0xf4) {\n return 0x34;\n } // 4\n if (_nibble == 0xf5) {\n return 0x35;\n } // 5\n if (_nibble == 0xf6) {\n return 0x36;\n } // 6\n if (_nibble == 0xf7) {\n return 0x37;\n } // 7\n if (_nibble == 0xf8) {\n return 0x38;\n } // 8\n if (_nibble == 0xf9) {\n return 0x39;\n } // 9\n if (_nibble == 0xfa) {\n return 0x61;\n } // a\n if (_nibble == 0xfb) {\n return 0x62;\n } // b\n if (_nibble == 0xfc) {\n return 0x63;\n } // c\n if (_nibble == 0xfd) {\n return 0x64;\n } // d\n if (_nibble == 0xfe) {\n return 0x65;\n } // e\n if (_nibble == 0xff) {\n return 0x66;\n } // f\n }\n\n /**\n * @notice Returns a uint16 containing the hex-encoded byte.\n * @param _b The byte\n * @return encoded - The hex-encoded byte\n */\n function byteHex(uint8 _b) internal pure returns (uint16 encoded) {\n encoded |= nibbleHex(_b \u003e\u003e 4); // top 4 bits\n encoded \u003c\u003c= 8;\n encoded |= nibbleHex(_b); // lower 4 bits\n }\n\n /**\n * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes.\n * `second` contains the encoded lower 16 bytes.\n *\n * @param _b The 32 bytes as uint256\n * @return first - The top 16 bytes\n * @return second - The bottom 16 bytes\n */\n function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) {\n for (uint8 i = 31; i \u003e 15; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n first |= byteHex(_byte);\n if (i != 16) {\n first \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n\n // abusing underflow here =_=\n for (uint8 i = 15; i \u003c 255; ) {\n uint8 _byte = uint8(_b \u003e\u003e (i * 8));\n second |= byteHex(_byte);\n if (i != 0) {\n second \u003c\u003c= 16;\n }\n unchecked {\n i -= 1;\n }\n }\n }\n\n /**\n * @notice Changes the endianness of a uint256.\n * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel\n * @param _b The unsigned integer to reverse\n * @return v - The reversed value\n */\n function reverseUint256(uint256 _b) internal pure returns (uint256 v) {\n v = _b;\n\n // swap bytes\n v =\n ((v \u003e\u003e 8) \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((v \u0026 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) \u003c\u003c 8);\n // swap 2-byte long pairs\n v =\n ((v \u003e\u003e 16) \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((v \u0026 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) \u003c\u003c 16);\n // swap 4-byte long pairs\n v =\n ((v \u003e\u003e 32) \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((v \u0026 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) \u003c\u003c 32);\n // swap 8-byte long pairs\n v =\n ((v \u003e\u003e 64) \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((v \u0026 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) \u003c\u003c 64);\n // swap 16-byte long pairs\n v = (v \u003e\u003e 128) | (v \u003c\u003c 128);\n }\n\n /**\n * @notice Create a mask with the highest `_len` bits set.\n * @param _len The length\n * @return mask - The mask\n */\n function leftMask(uint8 _len) private pure returns (uint256 mask) {\n // ugly. redo without assembly?\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mask := sar(\n sub(_len, 1),\n 0x8000000000000000000000000000000000000000000000000000000000000000\n )\n }\n }\n\n /**\n * @notice Return the null view.\n * @return bytes29 - The null view\n */\n function nullView() internal pure returns (bytes29) {\n return NULL;\n }\n\n /**\n * @notice Check if the view is null.\n * @return bool - True if the view is null\n */\n function isNull(bytes29 memView) internal pure returns (bool) {\n return memView == NULL;\n }\n\n /**\n * @notice Check if the view is not null.\n * @return bool - True if the view is not null\n */\n function notNull(bytes29 memView) internal pure returns (bool) {\n return !isNull(memView);\n }\n\n /**\n * @notice Check if the view is of a valid type and points to a valid location\n * in memory.\n * @dev We perform this check by examining solidity's unallocated memory\n * pointer and ensuring that the view's upper bound is less than that.\n * @param memView The view\n * @return ret - True if the view is valid\n */\n function isValid(bytes29 memView) internal pure returns (bool ret) {\n if (typeOf(memView) == 0xffffffffff) {\n return false;\n }\n uint256 _end = end(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ret := not(gt(_end, mload(0x40)))\n }\n }\n\n /**\n * @notice Require that a typed memory view be valid.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @return bytes29 - The validated view\n */\n function assertValid(bytes29 memView) internal pure returns (bytes29) {\n require(isValid(memView), \"Validity assertion failed\");\n return memView;\n }\n\n /**\n * @notice Return true if the memview is of the expected type. Otherwise false.\n * @param memView The view\n * @param _expected The expected type\n * @return bool - True if the memview is of the expected type\n */\n function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {\n return typeOf(memView) == _expected;\n }\n\n /**\n * @notice Require that a typed memory view has a specific type.\n * @dev Returns the view for easy chaining.\n * @param memView The view\n * @param _expected The expected type\n * @return bytes29 - The view with validated type\n */\n function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {\n if (!isType(memView, _expected)) {\n (, uint256 g) = encodeHex(uint256(typeOf(memView)));\n (, uint256 e) = encodeHex(uint256(_expected));\n string memory err = string(\n abi.encodePacked(\n \"Type assertion failed. Got 0x\",\n uint80(g),\n \". Expected 0x\",\n uint80(e)\n )\n );\n revert(err);\n }\n return memView;\n }\n\n /**\n * @notice Return an identical view with a different type.\n * @param memView The view\n * @param _newType The new type\n * @return newView - The new view with the specified type\n */\n function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {\n // then | in the new type\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // shift off the top 5 bytes\n newView := or(newView, shr(40, shl(40, memView)))\n newView := or(newView, shl(216, _newType))\n }\n }\n\n /**\n * @notice Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Unsafe raw pointer construction. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function unsafeBuildUnchecked(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) private pure returns (bytes29 newView) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n newView := shl(96, or(newView, _type)) // insert type\n newView := shl(96, or(newView, _loc)) // insert loc\n newView := shl(24, or(newView, _len)) // empty bottom 3 bytes\n }\n }\n\n /**\n * @notice Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @dev Instantiate a new memory view. This should generally not be called\n * directly. Prefer `ref` wherever possible.\n * @param _type The type\n * @param _loc The memory address\n * @param _len The length\n * @return newView - The new view with the specified type, location and length\n */\n function build(\n uint256 _type,\n uint256 _loc,\n uint256 _len\n ) internal pure returns (bytes29 newView) {\n uint256 _end = _loc + _len;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n if gt(_end, mload(0x40)) {\n _end := 0\n }\n }\n if (_end == 0) {\n return NULL;\n }\n newView = unsafeBuildUnchecked(_type, _loc, _len);\n }\n\n /**\n * @notice Instantiate a memory view from a byte array.\n * @dev Note that due to Solidity memory representation, it is not possible to\n * implement a deref, as the `bytes` type stores its len in memory.\n * @param arr The byte array\n * @param newType The type\n * @return bytes29 - The memory view\n */\n function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {\n uint256 _len = arr.length;\n\n uint256 _loc;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _loc := add(arr, 0x20) // our view is of the data, not the struct\n }\n\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Return the associated type information.\n * @param memView The memory view\n * @return _type - The type associated with the view\n */\n function typeOf(bytes29 memView) internal pure returns (uint40 _type) {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 216 == 256 - 40\n _type := shr(216, memView) // shift out lower 24 bytes\n }\n }\n\n /**\n * @notice Optimized type comparison. Checks that the 5-byte type flag is equal.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the 5-byte type flag is equal\n */\n function sameType(bytes29 left, bytes29 right) internal pure returns (bool) {\n return (left ^ right) \u003e\u003e (2 * TWELVE_BYTES) == 0;\n }\n\n /**\n * @notice Return the memory address of the underlying bytes.\n * @param memView The view\n * @return _loc - The memory address\n */\n function loc(bytes29 memView) internal pure returns (uint96 _loc) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)\n _loc := and(shr(120, memView), _mask)\n }\n }\n\n /**\n * @notice The number of memory words this memory view occupies, rounded up.\n * @param memView The view\n * @return uint256 - The number of memory words\n */\n function words(bytes29 memView) internal pure returns (uint256) {\n return (uint256(len(memView)) + 32) / 32;\n }\n\n /**\n * @notice The in-memory footprint of a fresh copy of the view.\n * @param memView The view\n * @return uint256 - The in-memory footprint of a fresh copy of the view.\n */\n function footprint(bytes29 memView) internal pure returns (uint256) {\n return words(memView) * 32;\n }\n\n /**\n * @notice The number of bytes of the view.\n * @param memView The view\n * @return _len - The length of the view\n */\n function len(bytes29 memView) internal pure returns (uint96 _len) {\n uint256 _mask = LOW_12_MASK; // assembly can't use globals\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n _len := and(shr(24, memView), _mask)\n }\n }\n\n /**\n * @notice Returns the endpoint of `memView`.\n * @param memView The view\n * @return uint256 - The endpoint of `memView`\n */\n function end(bytes29 memView) internal pure returns (uint256) {\n unchecked {\n return loc(memView) + len(memView);\n }\n }\n\n /**\n * @notice Safe slicing without memory modification.\n * @param memView The view\n * @param _index The start index\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function slice(\n bytes29 memView,\n uint256 _index,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n uint256 _loc = loc(memView);\n\n // Ensure it doesn't overrun the view\n if (_loc + _index + _len \u003e end(memView)) {\n return NULL;\n }\n\n _loc = _loc + _index;\n return build(newType, _loc, _len);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function prefix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, 0, _len, newType);\n }\n\n /**\n * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte.\n * @param memView The view\n * @param _len The length\n * @param newType The new type\n * @return bytes29 - The new view\n */\n function postfix(\n bytes29 memView,\n uint256 _len,\n uint40 newType\n ) internal pure returns (bytes29) {\n return slice(memView, uint256(len(memView)) - _len, _len, newType);\n }\n\n /**\n * @notice Construct an error message for an indexing overrun.\n * @param _loc The memory address\n * @param _len The length\n * @param _index The index\n * @param _slice The slice where the overrun occurred\n * @return err - The err\n */\n function indexErrOverrun(\n uint256 _loc,\n uint256 _len,\n uint256 _index,\n uint256 _slice\n ) internal pure returns (string memory err) {\n (, uint256 a) = encodeHex(_loc);\n (, uint256 b) = encodeHex(_len);\n (, uint256 c) = encodeHex(_index);\n (, uint256 d) = encodeHex(_slice);\n err = string(\n abi.encodePacked(\n \"TypedMemView/index - Overran the view. Slice is at 0x\",\n uint48(a),\n \" with length 0x\",\n uint48(b),\n \". Attempted to index at offset 0x\",\n uint48(c),\n \" with length 0x\",\n uint48(d),\n \".\"\n )\n );\n }\n\n /**\n * @notice Load up to 32 bytes from the view onto the stack.\n * @dev Returns a bytes32 with only the `_bytes` highest bytes set.\n * This can be immediately cast to a smaller fixed-length byte array.\n * To automatically cast to an integer, use `indexUint`.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The 32 byte result\n */\n function index(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (bytes32 result) {\n if (_bytes == 0) {\n return bytes32(0);\n }\n if (_index + _bytes \u003e len(memView)) {\n revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes)));\n }\n require(_bytes \u003c= 32, \"TypedMemView/index - Attempted to index more than 32 bytes\");\n\n uint8 bitLength;\n unchecked {\n bitLength = _bytes * 8;\n }\n uint256 _loc = loc(memView);\n uint256 _mask = leftMask(bitLength);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n result := and(mload(add(_loc, _index)), _mask)\n }\n }\n\n /**\n * @notice Parse an unsigned integer from the view at `_index`.\n * @dev Requires that the view have \u003e= `_bytes` bytes following that index.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return uint256(index(memView, _index, _bytes)) \u003e\u003e ((32 - _bytes) * 8);\n }\n\n /**\n * @notice Parse an unsigned integer from LE bytes.\n * @param memView The view\n * @param _index The index\n * @param _bytes The bytes\n * @return result - The unsigned integer\n */\n function indexLEUint(\n bytes29 memView,\n uint256 _index,\n uint8 _bytes\n ) internal pure returns (uint256 result) {\n return reverseUint256(uint256(index(memView, _index, _bytes)));\n }\n\n /**\n * @notice Parse an address from the view at `_index`. Requires that the view have \u003e= 20 bytes\n * following that index.\n * @param memView The view\n * @param _index The index\n * @return address - The address\n */\n function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {\n return address(uint160(indexUint(memView, _index, 20)));\n }\n\n /**\n * @notice Return the keccak256 hash of the underlying memory\n * @param memView The view\n * @return digest - The keccak256 hash of the underlying memory\n */\n function keccak(bytes29 memView) internal pure returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n digest := keccak256(_loc, _len)\n }\n }\n\n /**\n * @notice Return the sha2 digest of the underlying memory.\n * @dev We explicitly deallocate memory afterwards.\n * @param memView The view\n * @return digest - The sha2 hash of the underlying memory\n */\n function sha2(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Implements bitcoin's hash160 (rmd160(sha2()))\n * @param memView The pre-image\n * @return digest - the Digest\n */\n function hash160(bytes29 memView) internal view returns (bytes20 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2\n pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160\n digest := mload(add(ptr, 0xc)) // return value is 0-prefixed.\n }\n }\n\n /**\n * @notice Implements bitcoin's hash256 (double sha2)\n * @param memView A view of the preimage\n * @return digest - the Digest\n */\n function hash256(bytes29 memView) internal view returns (bytes32 digest) {\n uint256 _loc = loc(memView);\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1\n pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2\n digest := mload(ptr)\n }\n }\n\n /**\n * @notice Return true if the underlying memory is equal. Else false.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the underlying memory is equal\n */\n function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return\n (loc(left) == loc(right) \u0026\u0026 len(left) == len(right)) || keccak(left) == keccak(right);\n }\n\n /**\n * @notice Return false if the underlying memory is equal. Else true.\n * @param left The first view\n * @param right The second view\n * @return bool - False if the underlying memory is equal\n */\n function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !untypedEqual(left, right);\n }\n\n /**\n * @notice Compares type equality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are the same\n */\n function equal(bytes29 left, bytes29 right) internal pure returns (bool) {\n return left == right || (typeOf(left) == typeOf(right) \u0026\u0026 keccak(left) == keccak(right));\n }\n\n /**\n * @notice Compares type inequality.\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param left The first view\n * @param right The second view\n * @return bool - True if the types are not the same\n */\n function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {\n return !equal(left, right);\n }\n\n /**\n * @notice Copy the view to a location, return an unsafe memory reference\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memView The view\n * @param _newLoc The new location\n * @return written - the unsafe memory reference\n */\n function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {\n require(notNull(memView), \"TypedMemView/copyTo - Null pointer deref\");\n require(isValid(memView), \"TypedMemView/copyTo - Invalid pointer deref\");\n uint256 _len = len(memView);\n uint256 _oldLoc = loc(memView);\n\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _newLoc) {\n revert(0x60, 0x20) // empty revert message\n }\n\n // use the identity precompile to copy\n // guaranteed not to fail, so pop the success\n pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len))\n }\n\n written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);\n }\n\n /**\n * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to\n * the new memory\n * @dev Shortcuts if the pointers are identical, otherwise compares type and digest.\n * @param memView The view\n * @return ret - The view pointing to the new memory\n */\n function clone(bytes29 memView) internal view returns (bytes memory ret) {\n uint256 ptr;\n uint256 _len = len(memView);\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n ret := ptr\n }\n unchecked {\n unsafeCopyTo(memView, ptr + 0x20);\n }\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer\n mstore(ptr, _len) // write len of new array (in bytes)\n }\n }\n\n /**\n * @notice Join the views in memory, return an unsafe reference to the memory.\n * @dev Super Dangerous direct memory access.\n *\n * This reference can be overwritten if anything else modifies memory (!!!).\n * As such it MUST be consumed IMMEDIATELY.\n * This function is private to prevent unsafe usage by callers.\n * @param memViews The views\n * @return unsafeView - The conjoined view pointing to the new memory\n */\n function unsafeJoin(bytes29[] memory memViews, uint256 _location)\n private\n view\n returns (bytes29 unsafeView)\n {\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n let ptr := mload(0x40)\n // revert if we're writing in occupied memory\n if gt(ptr, _location) {\n revert(0x60, 0x20) // empty revert message\n }\n }\n\n uint256 _offset = 0;\n for (uint256 i = 0; i \u003c memViews.length; i++) {\n bytes29 memView = memViews[i];\n unchecked {\n unsafeCopyTo(memView, _location + _offset);\n _offset += len(memView);\n }\n }\n unsafeView = unsafeBuildUnchecked(0, _location, _offset);\n }\n\n /**\n * @notice Produce the keccak256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The keccak256 digest\n */\n function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return keccak(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice Produce the sha256 digest of the concatenated contents of multiple views.\n * @param memViews The views\n * @return bytes32 - The sha256 digest\n */\n function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n return sha2(unsafeJoin(memViews, ptr));\n }\n\n /**\n * @notice copies all views, joins them into a new bytearray.\n * @param memViews The views\n * @return ret - The new byte array\n */\n function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {\n uint256 ptr;\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n ptr := mload(0x40) // load unused memory pointer\n }\n\n bytes29 _newView;\n unchecked {\n _newView = unsafeJoin(memViews, ptr + 0x20);\n }\n uint256 _written = len(_newView);\n uint256 _footprint = footprint(_newView);\n\n assembly {\n // solhint-disable-previous-line no-inline-assembly\n // store the legnth\n mstore(ptr, _written)\n // new pointer is old + 0x20 + the footprint of the body\n mstore(0x40, add(add(ptr, _footprint), 0x20))\n ret := ptr\n }\n }\n}\n\nlibrary Attestation {\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n /**\n * @dev AttestationData memory layout\n * [000 .. 004): homeDomain uint32 4 bytes\n * [004 .. 008): nonce uint32 4 bytes\n * [008 .. 040): root bytes32 32 bytes\n *\n * Attestation memory layout\n * [000 .. 040): data bytes 40 bytes (see above)\n * [040 .. END): signature bytes ?? bytes (64/65 bytes)\n */\n\n uint256 internal constant OFFSET_HOME_DOMAIN = 0;\n uint256 internal constant OFFSET_NONCE = 4;\n uint256 internal constant OFFSET_ROOT = 8;\n uint256 internal constant ATTESTATION_DATA_LENGTH = 40;\n uint256 internal constant OFFSET_SIGNATURE = ATTESTATION_DATA_LENGTH;\n\n /**\n * @notice Returns formatted Attestation with provided fields\n * @param _data Attestation Data (see above)\n * @param _signature Notary's signature on `_data`\n * @return Formatted attestation\n **/\n function formatAttestation(bytes memory _data, bytes memory _signature)\n internal\n pure\n returns (bytes memory)\n {\n return abi.encodePacked(_data, _signature);\n }\n\n /**\n * @notice Returns formatted Attestation Data with provided fields\n * @param _domain Domain of Home's chain\n * @param _root New merkle root\n * @param _nonce Nonce of the merkle root\n * @return Formatted data\n **/\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n return abi.encodePacked(_domain, _nonce, _root);\n }\n\n /**\n * @notice Checks that message is an Attestation, by checking its length\n */\n function isAttestation(bytes29 _view) internal pure returns (bool) {\n // Should have non-zero length for signature. Signature validity is not checked.\n return _view.len() \u003e ATTESTATION_DATA_LENGTH;\n }\n\n /**\n * @notice Returns domain of chain where the Home contract is deployed\n */\n function attestationDomain(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_HOME_DOMAIN, 4));\n }\n\n /**\n * @notice Returns nonce of Home contract at the time, when `root` was the Merkle root.\n */\n function attestationNonce(bytes29 _view) internal pure returns (uint32) {\n return uint32(_view.indexUint(OFFSET_NONCE, 4));\n }\n\n /**\n * @notice Returns a historical Merkle root from the Home contract\n */\n function attestationRoot(bytes29 _view) internal pure returns (bytes32) {\n return _view.index(OFFSET_ROOT, 32);\n }\n\n /**\n * @notice Returns Attestation's Data, that is going to be signed by the Notary\n */\n function attestationData(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_HOME_DOMAIN, ATTESTATION_DATA_LENGTH, 0);\n }\n\n /**\n * @notice Returns Notary's signature on AttestationData\n */\n function attestationSignature(bytes29 _view) internal pure returns (bytes29) {\n return _view.slice(OFFSET_SIGNATURE, _view.len() - ATTESTATION_DATA_LENGTH, 0);\n }\n}\n\n// \ncontract AttestationHarness {\n using Attestation for bytes29;\n using TypedMemView for bytes;\n using TypedMemView for bytes29;\n\n function formatAttestation(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root,\n bytes memory _signature\n ) public pure returns (bytes memory) {\n return\n Attestation.formatAttestation(\n formatAttestationData(_domain, _nonce, _root),\n _signature\n );\n }\n\n function formatAttestationData(\n uint32 _domain,\n uint32 _nonce,\n bytes32 _root\n ) public pure returns (bytes memory) {\n return Attestation.formatAttestationData(_domain, _nonce, _root);\n }\n\n function isAttestation(bytes memory _attestation) public pure returns (bool) {\n return _attestation.ref(0).isAttestation();\n }\n\n function domain(bytes memory _attestation) public pure returns (uint32) {\n return _attestation.ref(0).attestationDomain();\n }\n\n function nonce(bytes memory _attestation) public pure returns (uint32) {\n return _attestation.ref(0).attestationNonce();\n }\n\n function root(bytes memory _attestation) public pure returns (bytes32) {\n return _attestation.ref(0).attestationRoot();\n }\n\n function data(bytes memory _attestation) public view returns (bytes memory) {\n return _attestation.ref(0).attestationData().clone();\n }\n\n function signature(bytes memory _attestation) public view returns (bytes memory) {\n return _attestation.ref(0).attestationSignature().clone();\n }\n}","language":"Solidity","languageVersion":"0.8.13","compilerVersion":"0.8.13","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"26:32242:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;26:32242:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"26:32242:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;2539:94;;;;;;;;198:66:1;186:79;;;168:98;;156:2;141:18;2539:94:0;;;;;;","abiDefinition":[{"inputs":[],"name":"NULL","outputs":[{"internalType":"bytes29","name":"","type":"bytes29"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NULL\",\"outputs\":[{\"internalType\":\"bytes29\",\"name\":\"\",\"type\":\"bytes29\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/AttestationHarness.sol\":\"TypedMemView\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/AttestationHarness.sol\":{\"keccak256\":\"0xa1ecb092d1bb125607ee9b568767f9cf0366164f77583e3051f0fb987bc51f77\",\"urls\":[\"bzz-raw://c9a84f9b2d6e2e88831aa5435b0ad28738a7ca90a0abe8a5e3d7247797b99d03\",\"dweb:/ipfs/QmQbt2LQ26nimJJ4DWfzUB5EJ4ufLmYGdWnkDGV1ff7HqE\"]}},\"version\":1}"},"hashes":{"NULL()":"f26be3fc"}}} \ No newline at end of file diff --git a/core/contracts/test/attestationharness/attestationharness.metadata.go b/core/contracts/test/attestationharness/attestationharness.metadata.go new file mode 100644 index 0000000000..99e636babf --- /dev/null +++ b/core/contracts/test/attestationharness/attestationharness.metadata.go @@ -0,0 +1,24 @@ +// Code generated by synapse abigen DO NOT EDIT. +package attestationharness + +import ( + _ "embed" + "encoding/json" + "github.com/ethereum/go-ethereum/common/compiler" +) + +// rawContracts are the json we use to dervive the processed contracts +//go:embed attestationharness.contractinfo.json +var rawContracts []byte + +// Contracts are unmarshalled on start +var Contracts map[string]*compiler.Contract + +func init() { + // load contract metadata + var err error + err = json.Unmarshal(rawContracts, &Contracts) + if err != nil { + panic(err) + } +} diff --git a/core/contracts/test/attestationharness/generate.go b/core/contracts/test/attestationharness/generate.go new file mode 100644 index 0000000000..ab471c0480 --- /dev/null +++ b/core/contracts/test/attestationharness/generate.go @@ -0,0 +1,4 @@ +package attestationharness + +//go:generate go run github.com/synapsecns/sanguine/tools/abigen generate --sol ../../../../packages/contracts/flattened/AttestationHarness.sol --pkg attestationharness --sol-version 0.8.13 --filename attestationharness +// line after go:generate cannot be left blank diff --git a/core/contracts/test/attestationharness/helpers.go b/core/contracts/test/attestationharness/helpers.go new file mode 100644 index 0000000000..9079b8c714 --- /dev/null +++ b/core/contracts/test/attestationharness/helpers.go @@ -0,0 +1,35 @@ +package attestationharness + +import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +// AttestationHarnessRef is an attestation harness reference +//nolint: golint +type AttestationHarnessRef struct { + *AttestationHarness + address common.Address +} + +// Address gets the address of the contract. +func (a AttestationHarnessRef) Address() common.Address { + return a.address +} + +// NewAttestationHarnessRef creates a new attestation harness. +func NewAttestationHarnessRef(address common.Address, backend bind.ContractBackend) (*AttestationHarnessRef, error) { + contract, err := NewAttestationHarness(address, backend) + if err != nil { + return nil, fmt.Errorf("could not create home harness: %w", err) + } + + return &AttestationHarnessRef{ + AttestationHarness: contract, + address: address, + }, nil +} + +var _ vm.ContractRef = &AttestationHarnessRef{} diff --git a/core/db/datastore/pebble/sdb.go b/core/db/datastore/pebble/sdb.go index b813efa613..ef9bb8ea8a 100644 --- a/core/db/datastore/pebble/sdb.go +++ b/core/db/datastore/pebble/sdb.go @@ -194,7 +194,7 @@ func (d *pebbleDB) StoreLeaf(leafIndex uint32, destinationAndNonce uint64, leaf return nil } -// MessageByNonce retreives a raw committed message by its leaf hash. +// MessageByNonce retrieves a raw committed message by its leaf hash. func (d *pebbleDB) MessageByNonce(destination, nonce uint32) (types.CommittedMessage, error) { leaf, err := d.LeafByNonce(destination, nonce) if err != nil { @@ -223,7 +223,7 @@ func (d *pebbleDB) MessageByLeaf(leaf common.Hash) (types.CommittedMessage, erro return committedMessage, nil } -// LeafByNonce retreives the leaf hash keyed by destination and nonce. +// LeafByNonce retrieves the leaf hash keyed by destination and nonce. func (d *pebbleDB) LeafByNonce(destination, nonce uint32) (common.Hash, error) { destAndNonce := types.CombineDestinationAndNonce(destination, nonce) value, _, err := d.DB.Get(d.FullKey(LEAF, []byte(fmt.Sprintf("%d", destAndNonce)))) @@ -252,7 +252,7 @@ func (d *pebbleDB) LeafByIndex(leafIndex uint32) (common.Hash, error) { return common.BytesToHash(value), nil } -// MessageByLeafIndex retreives a message by its leaf index. +// MessageByLeafIndex retrieves a message by its leaf index. func (d *pebbleDB) MessageByLeafIndex(leafIndex uint32) (types.CommittedMessage, error) { leaf, err := d.LeafByIndex(leafIndex) if err != nil { diff --git a/core/db/db_test.go b/core/db/db_test.go index d7515f9588..7ce38ee738 100644 --- a/core/db/db_test.go +++ b/core/db/db_test.go @@ -54,7 +54,7 @@ func (m *MessageSuite) TestStoresAndRetrievesMessages() { }) } -func (m *MessageSuite) TestStoresAndRetreivesProofs() { +func (m *MessageSuite) TestStoresAndretrievesProofs() { m.RunOnAllDBs(func(newDB db.MessageDB) { leaf := common.BigToHash(big.NewInt(gofakeit.Int64())) index := gofakeit.Uint32() @@ -101,10 +101,10 @@ func (m *MessageSuite) TestStoreAndRetrieveLatestRoot() { err = newDB.StoreLatestRoot(latestRoot) Nil(m.T(), err) - retreivedRoot, err := newDB.RetrieveLatestRoot() + retrievedRoot, err := newDB.RetrieveLatestRoot() Nil(m.T(), err) - Equal(m.T(), retreivedRoot, latestRoot) + Equal(m.T(), retrievedRoot, latestRoot) }) } diff --git a/core/db/message.go b/core/db/message.go index 2e70bfd955..1fa504e833 100644 --- a/core/db/message.go +++ b/core/db/message.go @@ -25,7 +25,7 @@ type MessageDB interface { StoreCommittedMessage(committedMessage types.CommittedMessage) error // StoreLatestMessage stores a raw committed message building off the leaf index StoreLatestMessage(committedMessage types.CommittedMessage) error - // MessageByNonce retreives a raw committed message by its leaf hash. + // MessageByNonce retrieves a raw committed message by its leaf hash. MessageByNonce(destination, nonce uint32) (types.CommittedMessage, error) // MessageByLeaf fetches a message by leaf MessageByLeaf(leaf common.Hash) (types.CommittedMessage, error) @@ -47,7 +47,7 @@ type MessageDB interface { // GetMessageLatestBlockEnd gets the message latest block GetMessageLatestBlockEnd() (height uint32, err error) - // RetrieveLatestRoot retreives latest root + // RetrieveLatestRoot retrieves latest root RetrieveLatestRoot() (common.Hash, error) // StoreLatestRoot stores the latest root StoreLatestRoot(latestRoot common.Hash) error diff --git a/core/domains/domain.go b/core/domains/domain.go index 8db685cd22..7ef62537f0 100644 --- a/core/domains/domain.go +++ b/core/domains/domain.go @@ -20,7 +20,7 @@ type DomainClient interface { Config() config.DomainConfig // BlockNumber gets the latest block BlockNumber(ctx context.Context) (uint32, error) - // Home retreives a handle for the home contract + // Home retrieves a handle for the home contract Home() HomeContract } @@ -36,5 +36,10 @@ type HomeContract interface { Update(ctx context.Context, signer signer.Signer, update types.SignedUpdate) error } +// AttestationCollectorContract contains the interface for the attestation collector. +type AttestationCollectorContract interface { + SubmitAttestation(signer signer.Signer, attestation types.SignedAttestation) error +} + // ErrNoUpdate indicates no update has been produced. var ErrNoUpdate = errors.New("no update produced") diff --git a/core/domains/evm/collector.go b/core/domains/evm/collector.go new file mode 100644 index 0000000000..bb07dc0c55 --- /dev/null +++ b/core/domains/evm/collector.go @@ -0,0 +1,62 @@ +package evm + +import ( + "context" + "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/synapsecns/sanguine/core/contracts/attestationcollector" + "github.com/synapsecns/sanguine/core/domains" + "github.com/synapsecns/sanguine/core/types" + "github.com/synapsecns/sanguine/ethergo/signer/nonce" + "github.com/synapsecns/sanguine/ethergo/signer/signer" + "github.com/synapsecns/synapse-node/pkg/evm" +) + +// NewAttestationCollectorContract returns a bound attestation collector contract. +func NewAttestationCollectorContract(ctx context.Context, client evm.Chain, attestationAddress common.Address) (domains.AttestationCollectorContract, error) { + boundCountract, err := attestationcollector.NewAttestationCollectorRef(attestationAddress, client) + if err != nil { + return nil, fmt.Errorf("could not create %T: %w", &attestationcollector.AttestationCollectorRef{}, err) + } + + nonceManager := nonce.NewNonceManager(ctx, client, client.GetBigChainID()) + return attestationCollectorContract{ + contract: boundCountract, + client: client, + nonceManager: nonceManager, + }, nil +} + +type attestationCollectorContract struct { + // contract contains the conract handle + contract *attestationcollector.AttestationCollectorRef + // client contains the evm client + client evm.Chain + // nonceManager is the nonce manager used for transacting with the chain + nonceManager nonce.Manager +} + +// SubmitAttestation submits an attestation to the attestation collector. +func (a attestationCollectorContract) SubmitAttestation(signer signer.Signer, attestation types.SignedAttestation) error { + transactor, err := signer.GetTransactor(a.client.GetBigChainID()) + if err != nil { + return fmt.Errorf("could not sign tx: %w", err) + } + + transactOpts, err := a.nonceManager.NewKeyedTransactor(transactor) + if err != nil { + return fmt.Errorf("could not create tx: %w", err) + } + + encodedAttestation, err := types.EncodeSignedAttestation(attestation) + if err != nil { + return fmt.Errorf("could not get signed attestations: %w", err) + } + + _, err = a.contract.SubmitAttestation(transactOpts, transactOpts.From, encodedAttestation) + if err != nil { + return fmt.Errorf("could not submit attestation: %w", err) + } + + return nil +} diff --git a/core/domains/evm/collector_test.go b/core/domains/evm/collector_test.go new file mode 100644 index 0000000000..eb0b98e3eb --- /dev/null +++ b/core/domains/evm/collector_test.go @@ -0,0 +1,35 @@ +package evm_test + +import ( + "github.com/brianvoe/gofakeit/v6" + "github.com/ethereum/go-ethereum/common" + . "github.com/stretchr/testify/assert" + "github.com/synapsecns/sanguine/core/agents/updater" + pebble2 "github.com/synapsecns/sanguine/core/db/datastore/pebble" + "github.com/synapsecns/sanguine/core/domains/evm" + "github.com/synapsecns/sanguine/core/types" + "math/big" +) + +func (i ContractSuite) TestSubmitAttestation() { + attestionCollector, err := evm.NewAttestationCollectorContract(i.GetTestContext(), i.attestationBackend, i.attestationContract.Address()) + Nil(i.T(), err) + + localDomain := attestationDomain + nonce := gofakeit.Uint32() + root := common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())) + + unsignedAttestation := types.NewAttestation(uint32(localDomain), nonce, root) + hashedAttestation, err := updater.HashAttestation(unsignedAttestation) + Nil(i.T(), err) + + signature, err := i.signer.SignMessage(i.GetTestContext(), pebble2.ToSlice(hashedAttestation), false) + Nil(i.T(), err) + + signedAttestation := types.NewSignedAttestation(unsignedAttestation, signature) + + err = attestionCollector.SubmitAttestation(i.signer, signedAttestation) + Nil(i.T(), err) + + // TODO retrieve once we have a way to +} diff --git a/core/domains/evm/suite_test.go b/core/domains/evm/suite_test.go index 96722cb4a3..9dd6fd5170 100644 --- a/core/domains/evm/suite_test.go +++ b/core/domains/evm/suite_test.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/params" . "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" + "github.com/synapsecns/sanguine/core/contracts/attestationcollector" "github.com/synapsecns/sanguine/core/contracts/home" "github.com/synapsecns/sanguine/core/domains/evm" "github.com/synapsecns/sanguine/core/testutil" @@ -49,9 +50,11 @@ func TestEVMSuite(t *testing.T) { // ContractSuite defines a suite for testing contracts. This uses the simulated backend. type ContractSuite struct { *testutils.TestSuite - homeContract *home.HomeRef - testBackend backends.SimulatedTestBackend - signer signer.Signer + homeContract *home.HomeRef + attestationContract *attestationcollector.AttestationCollectorRef + testBackend backends.SimulatedTestBackend + attestationBackend backends.SimulatedTestBackend + signer signer.Signer } func NewContractSuite(tb testing.TB) *ContractSuite { @@ -61,19 +64,26 @@ func NewContractSuite(tb testing.TB) *ContractSuite { } } +const attestationDomain = 4 + func (i *ContractSuite) SetupTest() { i.TestSuite.SetupTest() deployManager := testutil.NewDeployManager(i.T()) - i.testBackend = simulated.NewSimulatedBackend(i.GetTestContext(), i.T()) + i.testBackend = simulated.NewSimulatedBackendWithChainID(i.GetTestContext(), i.T(), big.NewInt(1)) + i.attestationBackend = simulated.NewSimulatedBackendWithChainID(i.GetTestContext(), i.T(), big.NewInt(2)) _, i.homeContract = deployManager.GetHome(i.GetTestContext(), i.testBackend) + var attestationContract backends.DeployedContract + attestationContract, i.attestationContract = deployManager.GetAttestationCollector(i.GetTestContext(), i.attestationBackend) + wall, err := wallet.FromRandom() Nil(i.T(), err) i.signer = localsigner.NewSigner(wall.PrivateKey()) i.testBackend.FundAccount(i.GetTestContext(), wall.Address(), *big.NewInt(params.Ether)) + i.attestationBackend.FundAccount(i.GetTestContext(), wall.Address(), *big.NewInt(params.Ether)) // change the updater as defined by the update manager contract _, updaterManager := deployManager.GetUpdaterManager(i.GetTestContext(), i.testBackend) @@ -85,8 +95,14 @@ func (i *ContractSuite) SetupTest() { // set the signer address to the updater tx, err := updaterManager.SetUpdater(transactOpts.TransactOpts, i.signer.Address()) Nil(i.T(), err) - i.testBackend.WaitForConfirmation(i.GetTestContext(), tx) + + // add the updater to attestation contract + auth := i.attestationBackend.GetTxContext(i.GetTestContext(), attestationContract.OwnerPtr()) + + tx, err = i.attestationContract.AddUpdater(auth.TransactOpts, attestationDomain, i.signer.Address()) + Nil(i.T(), err) + i.attestationBackend.WaitForConfirmation(i.GetTestContext(), tx) } func TestContractSuite(t *testing.T) { diff --git a/core/testutil/contracttype.go b/core/testutil/contracttype.go index c98f8faf0e..599b9cbff6 100644 --- a/core/testutil/contracttype.go +++ b/core/testutil/contracttype.go @@ -2,7 +2,9 @@ package testutil import ( "github.com/ethereum/go-ethereum/common/compiler" + "github.com/synapsecns/sanguine/core/contracts/attestationcollector" "github.com/synapsecns/sanguine/core/contracts/home" + "github.com/synapsecns/sanguine/core/contracts/test/attestationharness" "github.com/synapsecns/sanguine/core/contracts/test/homeharness" "github.com/synapsecns/sanguine/core/contracts/test/messageharness" "github.com/synapsecns/sanguine/core/contracts/updatermanager" @@ -46,8 +48,12 @@ const ( MessageHarnessType contractTypeImpl = iota // MessageHarness // HomeHarnessType is the home harness type. HomeHarnessType contractTypeImpl = iota // HomeHarness + // AttestationHarnessType is the attestation harness type. + AttestationHarnessType contractTypeImpl = iota // UpdaterManagerType is the type of the update manager. UpdaterManagerType contractTypeImpl = iota // UpdaterManager + // AttestationCollectorType is the type of the attestation collector. + AttestationCollectorType contractTypeImpl = iota // AttestationCollector ) // ID gets the contract type as an id. @@ -76,8 +82,12 @@ func (c contractTypeImpl) ContractInfo() *compiler.Contract { return messageharness.Contracts["solidity/MessageHarness.sol:MessageHarness"] case HomeHarnessType: return homeharness.Contracts["solidity/HomeHarness.sol:HomeHarness"] + case AttestationHarnessType: + return attestationharness.Contracts["solidity/AttestationHarness.sol:AttestationHarness"] case UpdaterManagerType: return updatermanager.Contracts["solidity/UpdaterManager.sol:UpdaterManager"] + case AttestationCollectorType: + return attestationcollector.Contracts["solidity/AttestationCollector.sol:AttestationCollector"] default: panic("not yet implemented") } diff --git a/core/testutil/contracttypeimpl_string.go b/core/testutil/contracttypeimpl_string.go index 88030ed6fd..67b996125c 100644 --- a/core/testutil/contracttypeimpl_string.go +++ b/core/testutil/contracttypeimpl_string.go @@ -12,12 +12,14 @@ func _() { _ = x[XAppConfigType-1] _ = x[MessageHarnessType-2] _ = x[HomeHarnessType-3] - _ = x[UpdaterManagerType-4] + _ = x[AttestationHarnessType-4] + _ = x[UpdaterManagerType-5] + _ = x[AttestationCollectorType-6] } -const _contractTypeImpl_name = "HomeXAppConfigMessageHarnessHomeHarnessUpdaterManager" +const _contractTypeImpl_name = "HomeXAppConfigMessageHarnessHomeHarnessAttestationHarnessTypeUpdaterManagerAttestationCollector" -var _contractTypeImpl_index = [...]uint8{0, 4, 14, 28, 39, 53} +var _contractTypeImpl_index = [...]uint8{0, 4, 14, 28, 39, 61, 75, 95} func (i contractTypeImpl) String() string { if i < 0 || i >= contractTypeImpl(len(_contractTypeImpl_index)-1) { diff --git a/core/testutil/deployers.go b/core/testutil/deployers.go index 9047b9fa0f..6b9f5fe141 100644 --- a/core/testutil/deployers.go +++ b/core/testutil/deployers.go @@ -6,7 +6,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/synapsecns/sanguine/core/contracts/attestationcollector" "github.com/synapsecns/sanguine/core/contracts/home" + "github.com/synapsecns/sanguine/core/contracts/test/attestationharness" "github.com/synapsecns/sanguine/core/contracts/test/homeharness" "github.com/synapsecns/sanguine/core/contracts/test/messageharness" "github.com/synapsecns/sanguine/core/contracts/updatermanager" @@ -160,6 +162,25 @@ func (h HomeHarnessDeployer) Deploy(ctx context.Context) (backends.DeployedContr }) } +// AttestionHarnessDeployer deploys the attestation harness. +type AttestionHarnessDeployer struct { + *deployer.BaseDeployer +} + +// NewAttestationHarnessDeployer creates a new deployer for the attestation harness. +func NewAttestationHarnessDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer { + return AttestionHarnessDeployer{deployer.NewSimpleDeployer(registry, backend, AttestationHarnessType)} +} + +// Deploy deploys the attestation harness. +func (a AttestionHarnessDeployer) Deploy(ctx context.Context) (backends.DeployedContract, error) { + return a.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { + return attestationharness.DeployAttestationHarness(transactOps, backend) + }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) { + return attestationharness.NewAttestationHarnessRef(address, backend) + }) +} + // UpdateManagerDeployer deploys the update manager. type UpdateManagerDeployer struct { *deployer.BaseDeployer @@ -178,3 +199,34 @@ func (u UpdateManagerDeployer) Deploy(ctx context.Context) (backends.DeployedCon return updatermanager.NewUpdaterManagerRef(address, backend) }) } + +// AttestationCollectorDeployer deploys the attestation collector. +type AttestationCollectorDeployer struct { + *deployer.BaseDeployer +} + +// NewAttestationCollectorDeployer creates the deployer for the attestation collecotr. +func NewAttestationCollectorDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer { + return AttestationCollectorDeployer{deployer.NewSimpleDeployer(registry, backend, AttestationCollectorType)} +} + +// Deploy deploys the attestation collector. +func (a AttestationCollectorDeployer) Deploy(ctx context.Context) (backends.DeployedContract, error) { + return a.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { + attestationAddress, attestationTx, collector, err := attestationcollector.DeployAttestationCollector(transactOps, backend) + if err != nil { + return common.Address{}, nil, nil, fmt.Errorf("could not deploy attesation collector: %w", err) + } + + auth := a.Backend().GetTxContext(ctx, &transactOps.From) + initTx, err := collector.Initialize(auth.TransactOpts) + if err != nil { + return common.Address{}, nil, nil, fmt.Errorf("could not initialize attesation collector: %w", err) + } + a.Backend().WaitForConfirmation(ctx, initTx) + + return attestationAddress, attestationTx, collector, nil + }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) { + return attestationcollector.NewAttestationCollectorRef(address, backend) + }) +} diff --git a/core/testutil/manager.go b/core/testutil/manager.go index 0520daeedf..e8fb5469ab 100644 --- a/core/testutil/manager.go +++ b/core/testutil/manager.go @@ -9,7 +9,7 @@ import ( func NewDeployManager(t *testing.T) *DeployManager { t.Helper() - parentManager := manager.NewDeployerManager(t, NewHomeDeployer, NewXAppConfigDeployer, NewMessageHarnessDeployer, NewHomeHarnessDeployer, NewUpdateManagerDeployer) + parentManager := manager.NewDeployerManager(t, NewHomeDeployer, NewXAppConfigDeployer, NewMessageHarnessDeployer, NewHomeHarnessDeployer, NewUpdateManagerDeployer, NewAttestationCollectorDeployer, NewAttestationHarnessDeployer) return &DeployManager{parentManager} } diff --git a/core/testutil/typecast.go b/core/testutil/typecast.go index 9ad93bb995..ef62d62783 100644 --- a/core/testutil/typecast.go +++ b/core/testutil/typecast.go @@ -3,7 +3,9 @@ package testutil import ( "context" "github.com/stretchr/testify/assert" + "github.com/synapsecns/sanguine/core/contracts/attestationcollector" "github.com/synapsecns/sanguine/core/contracts/home" + "github.com/synapsecns/sanguine/core/contracts/test/attestationharness" "github.com/synapsecns/sanguine/core/contracts/test/homeharness" "github.com/synapsecns/sanguine/core/contracts/test/messageharness" "github.com/synapsecns/sanguine/core/contracts/updatermanager" @@ -51,12 +53,24 @@ func (d *DeployManager) GetMessageHarness(ctx context.Context, backend backends. func (d *DeployManager) GetHomeHarness(ctx context.Context, backend backends.SimulatedTestBackend) (contract backends.DeployedContract, handle *homeharness.HomeHarnessRef) { d.T().Helper() - homeHarnessContract := d.GetContractRegistry(backend).Get(ctx, HomeHarnessType) + messageHarnessContract := d.GetContractRegistry(backend).Get(ctx, HomeHarnessType) - messageHarness, ok := homeHarnessContract.ContractHandle().(*homeharness.HomeHarnessRef) + messageHarness, ok := messageHarnessContract.ContractHandle().(*homeharness.HomeHarnessRef) assert.True(d.T(), ok) - return homeHarnessContract, messageHarness + return messageHarnessContract, messageHarness +} + +// GetAttestionHarness gets the attestation harness. +func (d *DeployManager) GetAttestionHarness(ctx context.Context, backend backends.SimulatedTestBackend) (contract backends.DeployedContract, handle *attestationharness.AttestationHarnessRef) { + d.T().Helper() + + attestationHarnessContract := d.GetContractRegistry(backend).Get(ctx, AttestationHarnessType) + + attestionHarness, ok := attestationHarnessContract.ContractHandle().(*attestationharness.AttestationHarnessRef) + assert.True(d.T(), ok) + + return attestationHarnessContract, attestionHarness } // GetUpdaterManager gets the update manager. @@ -69,3 +83,14 @@ func (d *DeployManager) GetUpdaterManager(ctx context.Context, backend backends. return updaterManagerContract, updaterManager } + +// GetAttestationCollector gets the attestation collector contract. +func (d *DeployManager) GetAttestationCollector(ctx context.Context, backend backends.SimulatedTestBackend) (contract backends.DeployedContract, handle *attestationcollector.AttestationCollectorRef) { + d.T().Helper() + + attestionContract := d.GetContractRegistry(backend).Get(ctx, AttestationCollectorType) + attestationCollector, ok := attestionContract.ContractHandle().(*attestationcollector.AttestationCollectorRef) + assert.True(d.T(), ok) + + return attestionContract, attestationCollector +} diff --git a/core/testutil/typecast_test.go b/core/testutil/typecast_test.go index a606ca7a8c..c361038193 100644 --- a/core/testutil/typecast_test.go +++ b/core/testutil/typecast_test.go @@ -36,3 +36,17 @@ func (s SimulatedSuite) TestTypecastUpdaterManager() { NotNil(s.T(), updaterManager) }) } + +func (s SimulatedSuite) TestTypecastAttesationCollector() { + NotPanics(s.T(), func() { + _, attestationCollector := s.deployManager.GetAttestationCollector(s.GetTestContext(), s.testBackend) + NotNil(s.T(), attestationCollector) + }) +} + +func (s SimulatedSuite) TestTypecastAttestionHarness() { + NotPanics(s.T(), func() { + _, attestationHarness := s.deployManager.GetAttestionHarness(s.GetTestContext(), s.testBackend) + NotNil(s.T(), attestationHarness) + }) +} diff --git a/core/types/attestation.go b/core/types/attestation.go new file mode 100644 index 0000000000..f9c8382058 --- /dev/null +++ b/core/types/attestation.go @@ -0,0 +1,75 @@ +package types + +// Attestation is the attestation. +type Attestation interface { + // Domain gets the domain of the attestation + Domain() uint32 + // Nonce gets the nonce of the attestation + Nonce() uint32 + // Root gets the root of the contract + Root() [32]byte +} + +type attestation struct { + // domain of the attestation + domain uint32 + // nonce of the attestation + nonce uint32 + // root - the merkle root + root [32]byte +} + +// NewAttestation creates a new attesation. +func NewAttestation(localDomain, nonce uint32, root [32]byte) Attestation { + return attestation{ + domain: localDomain, + nonce: nonce, + root: root, + } +} + +func (a attestation) Domain() uint32 { + return a.domain +} + +func (a attestation) Nonce() uint32 { + return a.nonce +} + +func (a attestation) Root() [32]byte { + return a.root +} + +var _ Attestation = attestation{} + +// SignedAttestation is a signed attestation. +type SignedAttestation interface { + // Attestation gets the unsigned attestation + Attestation() Attestation + // Signature is the signature of the attestation + Signature() Signature +} + +// signedAttestation is a struct that conforms to SignedAttesation. +type signedAttestation struct { + attestation Attestation + signature Signature +} + +// NewSignedAttestation creates a new signed attestation. +func NewSignedAttestation(attestation Attestation, signature Signature) SignedAttestation { + return signedAttestation{ + attestation: attestation, + signature: signature, + } +} + +func (s signedAttestation) Attestation() Attestation { + return s.attestation +} + +func (s signedAttestation) Signature() Signature { + return s.signature +} + +var _ SignedAttestation = signedAttestation{} diff --git a/core/types/encoder.go b/core/types/encoder.go index 8cd53aa4b9..0acdd2fd50 100644 --- a/core/types/encoder.go +++ b/core/types/encoder.go @@ -22,6 +22,43 @@ func EncodeSignedUpdate(signed SignedUpdate) ([]byte, error) { return append(encodedUpdate, encodedSignature...), nil } +// EncodeSignedAttestation encodes a signed attestation. +func EncodeSignedAttestation(signed SignedAttestation) ([]byte, error) { + encodedAttestation, err := EncodeAttestation(signed.Attestation()) + if err != nil { + return nil, fmt.Errorf("could not encode attestation: %w", err) + } + + encodedSignature, err := EncodeSignature(signed.Signature()) + if err != nil { + return nil, fmt.Errorf("could not encode signature: %w", err) + } + + return append(encodedAttestation, encodedSignature...), nil +} + +// DecodeSignedAttestation decodes a signed attestation. +func DecodeSignedAttestation(toDecode []byte) (SignedAttestation, error) { + var decAttestation attestation + + signedAttesationSize := binary.Size(decAttestation) + + attestationBin := toDecode[0:signedAttesationSize] + signBin := toDecode[signedAttesationSize:] + + att, err := DecodeAttestation(attestationBin) + if err != nil { + return nil, fmt.Errorf("could not decode attestation: %w", err) + } + + sig, err := DecodeSignature(signBin) + if err != nil { + return nil, fmt.Errorf("could not decode signature: %w", err) + } + + return NewSignedAttestation(att, sig), nil +} + // DecodeSignedUpdate decodes a signed update. func DecodeSignedUpdate(toDecode []byte) (SignedUpdate, error) { var decUpdate updateEncoder @@ -106,3 +143,50 @@ func DecodeSignature(toDecode []byte) (sig Signature, err error) { return NewSignature(v, r, s), nil } + +// attestationEncoder encodes attestations. +type attestationEncoder struct { + Domain, Nonce uint32 + Root [32]byte +} + +// EncodeAttestation encodes an attestation. +func EncodeAttestation(attestation Attestation) ([]byte, error) { + buf := new(bytes.Buffer) + + encodedUpdate := attestationEncoder{ + Domain: attestation.Domain(), + Nonce: attestation.Nonce(), + Root: attestation.Root(), + } + + err := binary.Write(buf, binary.BigEndian, encodedUpdate) + if err != nil { + return nil, fmt.Errorf("could not write binary: %w", err) + } + + return buf.Bytes(), nil +} + +// DecodeAttestation decodes an attestation. +func DecodeAttestation(toDecode []byte) (Attestation, error) { + reader := bytes.NewReader(toDecode) + + var encodedAttestation attestationEncoder + dataSize := binary.Size(encodedAttestation) + + if dataSize > len(toDecode) { + return nil, fmt.Errorf("message too small, expected at least %d, got %d", dataSize, len(toDecode)) + } + + err := binary.Read(reader, binary.BigEndian, &encodedAttestation) + if err != nil { + return nil, fmt.Errorf("could not read: %w", err) + } + + return attestation{ + domain: encodedAttestation.Domain, + nonce: encodedAttestation.Nonce, + root: encodedAttestation.Root, + }, nil +} diff --git a/core/types/encoder_test.go b/core/types/encoder_test.go index b5a59de14f..a08e7204de 100644 --- a/core/types/encoder_test.go +++ b/core/types/encoder_test.go @@ -68,3 +68,50 @@ func TestEncodeDecodeUpdate(t *testing.T) { _, err = types.DecodeUpdate(res) Nil(t, err) } + +func TestEncodeDecodeAttestation(t *testing.T) { + domain := gofakeit.Uint32() + nonce := gofakeit.Uint32() + root := common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())) + + formattedData, err := types.EncodeAttestation(types.NewAttestation(domain, nonce, root)) + Nil(t, err) + + decodedAttestation, err := types.DecodeAttestation(formattedData) + Nil(t, err) + + Equal(t, decodedAttestation.Domain(), domain) + Equal(t, decodedAttestation.Nonce(), nonce) + + rawRoot := decodedAttestation.Root() + Equal(t, common.BytesToHash(rawRoot[:]), root) +} + +func TestEncodeDecodeSignedAttestation(t *testing.T) { + domain := gofakeit.Uint32() + nonce := gofakeit.Uint32() + root := common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())) + + fakeV := new(big.Int).SetUint64(uint64(gofakeit.Uint8())) + fakeR := big.NewInt(gofakeit.Int64()) + fakeS := big.NewInt(gofakeit.Int64()) + + signedAttestation := types.NewSignedAttestation( + types.NewAttestation(domain, nonce, root), + types.NewSignature(fakeV, fakeR, fakeS), + ) + + encoded, err := types.EncodeSignedAttestation(signedAttestation) + Nil(t, err) + + decoded, err := types.DecodeSignedAttestation(encoded) + Nil(t, err) + + Equal(t, decoded.Attestation().Root(), signedAttestation.Attestation().Root()) + Equal(t, decoded.Attestation().Domain(), signedAttestation.Attestation().Domain()) + Equal(t, decoded.Attestation().Nonce(), signedAttestation.Attestation().Nonce()) + + Equal(t, decoded.Signature().V(), signedAttestation.Signature().V()) + Equal(t, decoded.Signature().R(), signedAttestation.Signature().R()) + Equal(t, decoded.Signature().S(), signedAttestation.Signature().S()) +} diff --git a/core/types/message_test.go b/core/types/parity_test.go similarity index 68% rename from core/types/message_test.go rename to core/types/parity_test.go index 003d60f9d6..543ccd23d9 100644 --- a/core/types/message_test.go +++ b/core/types/parity_test.go @@ -14,6 +14,59 @@ import ( "time" ) +func TestEncodeAttestationParity(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + testBackend := simulated.NewSimulatedBackend(ctx, t) + deployManager := testutil.NewDeployManager(t) + + domain := gofakeit.Uint32() + nonce := gofakeit.Uint32() + root := common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())) + + _, attesationContract := deployManager.GetAttestionHarness(ctx, testBackend) + + contractData, err := attesationContract.FormatAttestationData(&bind.CallOpts{Context: ctx}, domain, nonce, root) + Nil(t, err) + + goFormattedData, err := types.EncodeAttestation(types.NewAttestation(domain, nonce, root)) + Nil(t, err) + Equal(t, contractData, goFormattedData) +} + +func TestEncodeSignedAttestationParity(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + testBackend := simulated.NewSimulatedBackend(ctx, t) + deployManager := testutil.NewDeployManager(t) + + _, attesationContract := deployManager.GetAttestionHarness(ctx, testBackend) + + domain := gofakeit.Uint32() + nonce := gofakeit.Uint32() + root := common.BigToHash(new(big.Int).SetUint64(gofakeit.Uint64())) + + sig := types.NewSignature(new(big.Int).SetUint64(uint64(gofakeit.Uint8())), new(big.Int).SetUint64(gofakeit.Uint64()), new(big.Int).SetUint64(gofakeit.Uint64())) + + signedAttestation := types.NewSignedAttestation( + types.NewAttestation(domain, nonce, root), + sig, + ) + + encodedSignature, err := types.EncodeSignature(sig) + Nil(t, err) + + signedContractAttestation, err := attesationContract.FormatAttestation(&bind.CallOpts{Context: ctx}, domain, nonce, root, encodedSignature) + Nil(t, err) + + goData, err := types.EncodeSignedAttestation(signedAttestation) + Nil(t, err) + + Equal(t, signedContractAttestation, goData) +} + func TestMessageEncodeParity(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel()