diff --git a/.gitignore b/.gitignore index e9e5e07..9120c09 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ gnoshcontracts/ shopcontracts/ out/ .tool-versions +.env diff --git a/bindings/shutterregistry/shutterregistry.go b/bindings/shutterregistry/shutterregistry.go new file mode 100644 index 0000000..b8fbe26 --- /dev/null +++ b/bindings/shutterregistry/shutterregistry.go @@ -0,0 +1,609 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package shutterregistry + +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 +) + +// ShutterregistryMetaData contains all meta data concerning the Shutterregistry contract. +var ShutterregistryMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"register\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registrations\",\"inputs\":[{\"name\":\"identity\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"IdentityRegistered\",\"inputs\":[{\"name\":\"eon\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"identityPrefix\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"timestamp\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyRegistered\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidIdentityPrefix\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TimestampInThePast\",\"inputs\":[]}]", +} + +// ShutterregistryABI is the input ABI used to generate the binding from. +// Deprecated: Use ShutterregistryMetaData.ABI instead. +var ShutterregistryABI = ShutterregistryMetaData.ABI + +// Shutterregistry is an auto generated Go binding around an Ethereum contract. +type Shutterregistry struct { + ShutterregistryCaller // Read-only binding to the contract + ShutterregistryTransactor // Write-only binding to the contract + ShutterregistryFilterer // Log filterer for contract events +} + +// ShutterregistryCaller is an auto generated read-only Go binding around an Ethereum contract. +type ShutterregistryCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ShutterregistryTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ShutterregistryTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ShutterregistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ShutterregistryFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ShutterregistrySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ShutterregistrySession struct { + Contract *Shutterregistry // 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 +} + +// ShutterregistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ShutterregistryCallerSession struct { + Contract *ShutterregistryCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ShutterregistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ShutterregistryTransactorSession struct { + Contract *ShutterregistryTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ShutterregistryRaw is an auto generated low-level Go binding around an Ethereum contract. +type ShutterregistryRaw struct { + Contract *Shutterregistry // Generic contract binding to access the raw methods on +} + +// ShutterregistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ShutterregistryCallerRaw struct { + Contract *ShutterregistryCaller // Generic read-only contract binding to access the raw methods on +} + +// ShutterregistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ShutterregistryTransactorRaw struct { + Contract *ShutterregistryTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewShutterregistry creates a new instance of Shutterregistry, bound to a specific deployed contract. +func NewShutterregistry(address common.Address, backend bind.ContractBackend) (*Shutterregistry, error) { + contract, err := bindShutterregistry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Shutterregistry{ShutterregistryCaller: ShutterregistryCaller{contract: contract}, ShutterregistryTransactor: ShutterregistryTransactor{contract: contract}, ShutterregistryFilterer: ShutterregistryFilterer{contract: contract}}, nil +} + +// NewShutterregistryCaller creates a new read-only instance of Shutterregistry, bound to a specific deployed contract. +func NewShutterregistryCaller(address common.Address, caller bind.ContractCaller) (*ShutterregistryCaller, error) { + contract, err := bindShutterregistry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ShutterregistryCaller{contract: contract}, nil +} + +// NewShutterregistryTransactor creates a new write-only instance of Shutterregistry, bound to a specific deployed contract. +func NewShutterregistryTransactor(address common.Address, transactor bind.ContractTransactor) (*ShutterregistryTransactor, error) { + contract, err := bindShutterregistry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ShutterregistryTransactor{contract: contract}, nil +} + +// NewShutterregistryFilterer creates a new log filterer instance of Shutterregistry, bound to a specific deployed contract. +func NewShutterregistryFilterer(address common.Address, filterer bind.ContractFilterer) (*ShutterregistryFilterer, error) { + contract, err := bindShutterregistry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ShutterregistryFilterer{contract: contract}, nil +} + +// bindShutterregistry binds a generic wrapper to an already deployed contract. +func bindShutterregistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ShutterregistryABI)) + 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 (_Shutterregistry *ShutterregistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Shutterregistry.Contract.ShutterregistryCaller.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 (_Shutterregistry *ShutterregistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Shutterregistry.Contract.ShutterregistryTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Shutterregistry *ShutterregistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Shutterregistry.Contract.ShutterregistryTransactor.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 (_Shutterregistry *ShutterregistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Shutterregistry.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 (_Shutterregistry *ShutterregistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Shutterregistry.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Shutterregistry *ShutterregistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Shutterregistry.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 (_Shutterregistry *ShutterregistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Shutterregistry.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 (_Shutterregistry *ShutterregistrySession) Owner() (common.Address, error) { + return _Shutterregistry.Contract.Owner(&_Shutterregistry.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Shutterregistry *ShutterregistryCallerSession) Owner() (common.Address, error) { + return _Shutterregistry.Contract.Owner(&_Shutterregistry.CallOpts) +} + +// Registrations is a free data retrieval call binding the contract method 0xda7c6a42. +// +// Solidity: function registrations(bytes32 identity) view returns(uint64 eon, uint64 timestamp) +func (_Shutterregistry *ShutterregistryCaller) Registrations(opts *bind.CallOpts, identity [32]byte) (struct { + Eon uint64 + Timestamp uint64 +}, error) { + var out []interface{} + err := _Shutterregistry.contract.Call(opts, &out, "registrations", identity) + + outstruct := new(struct { + Eon uint64 + Timestamp uint64 + }) + if err != nil { + return *outstruct, err + } + + outstruct.Eon = *abi.ConvertType(out[0], new(uint64)).(*uint64) + outstruct.Timestamp = *abi.ConvertType(out[1], new(uint64)).(*uint64) + + return *outstruct, err + +} + +// Registrations is a free data retrieval call binding the contract method 0xda7c6a42. +// +// Solidity: function registrations(bytes32 identity) view returns(uint64 eon, uint64 timestamp) +func (_Shutterregistry *ShutterregistrySession) Registrations(identity [32]byte) (struct { + Eon uint64 + Timestamp uint64 +}, error) { + return _Shutterregistry.Contract.Registrations(&_Shutterregistry.CallOpts, identity) +} + +// Registrations is a free data retrieval call binding the contract method 0xda7c6a42. +// +// Solidity: function registrations(bytes32 identity) view returns(uint64 eon, uint64 timestamp) +func (_Shutterregistry *ShutterregistryCallerSession) Registrations(identity [32]byte) (struct { + Eon uint64 + Timestamp uint64 +}, error) { + return _Shutterregistry.Contract.Registrations(&_Shutterregistry.CallOpts, identity) +} + +// Register is a paid mutator transaction binding the contract method 0xeaac3573. +// +// Solidity: function register(uint64 eon, bytes32 identityPrefix, uint64 timestamp) returns() +func (_Shutterregistry *ShutterregistryTransactor) Register(opts *bind.TransactOpts, eon uint64, identityPrefix [32]byte, timestamp uint64) (*types.Transaction, error) { + return _Shutterregistry.contract.Transact(opts, "register", eon, identityPrefix, timestamp) +} + +// Register is a paid mutator transaction binding the contract method 0xeaac3573. +// +// Solidity: function register(uint64 eon, bytes32 identityPrefix, uint64 timestamp) returns() +func (_Shutterregistry *ShutterregistrySession) Register(eon uint64, identityPrefix [32]byte, timestamp uint64) (*types.Transaction, error) { + return _Shutterregistry.Contract.Register(&_Shutterregistry.TransactOpts, eon, identityPrefix, timestamp) +} + +// Register is a paid mutator transaction binding the contract method 0xeaac3573. +// +// Solidity: function register(uint64 eon, bytes32 identityPrefix, uint64 timestamp) returns() +func (_Shutterregistry *ShutterregistryTransactorSession) Register(eon uint64, identityPrefix [32]byte, timestamp uint64) (*types.Transaction, error) { + return _Shutterregistry.Contract.Register(&_Shutterregistry.TransactOpts, eon, identityPrefix, timestamp) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Shutterregistry *ShutterregistryTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Shutterregistry.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Shutterregistry *ShutterregistrySession) RenounceOwnership() (*types.Transaction, error) { + return _Shutterregistry.Contract.RenounceOwnership(&_Shutterregistry.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Shutterregistry *ShutterregistryTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Shutterregistry.Contract.RenounceOwnership(&_Shutterregistry.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Shutterregistry *ShutterregistryTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Shutterregistry.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Shutterregistry *ShutterregistrySession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Shutterregistry.Contract.TransferOwnership(&_Shutterregistry.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Shutterregistry *ShutterregistryTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Shutterregistry.Contract.TransferOwnership(&_Shutterregistry.TransactOpts, newOwner) +} + +// ShutterregistryIdentityRegisteredIterator is returned from FilterIdentityRegistered and is used to iterate over the raw logs and unpacked data for IdentityRegistered events raised by the Shutterregistry contract. +type ShutterregistryIdentityRegisteredIterator struct { + Event *ShutterregistryIdentityRegistered // 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 *ShutterregistryIdentityRegisteredIterator) 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(ShutterregistryIdentityRegistered) + 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(ShutterregistryIdentityRegistered) + 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 *ShutterregistryIdentityRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ShutterregistryIdentityRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ShutterregistryIdentityRegistered represents a IdentityRegistered event raised by the Shutterregistry contract. +type ShutterregistryIdentityRegistered struct { + Eon uint64 + IdentityPrefix [32]byte + Sender common.Address + Timestamp uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterIdentityRegistered is a free log retrieval operation binding the contract event 0xa254e5a8078a79959db8c7203cbd84a28d6e1b9750d0c4fd743a1a069c21b05b. +// +// Solidity: event IdentityRegistered(uint64 eon, bytes32 identityPrefix, address sender, uint64 timestamp) +func (_Shutterregistry *ShutterregistryFilterer) FilterIdentityRegistered(opts *bind.FilterOpts) (*ShutterregistryIdentityRegisteredIterator, error) { + + logs, sub, err := _Shutterregistry.contract.FilterLogs(opts, "IdentityRegistered") + if err != nil { + return nil, err + } + return &ShutterregistryIdentityRegisteredIterator{contract: _Shutterregistry.contract, event: "IdentityRegistered", logs: logs, sub: sub}, nil +} + +// WatchIdentityRegistered is a free log subscription operation binding the contract event 0xa254e5a8078a79959db8c7203cbd84a28d6e1b9750d0c4fd743a1a069c21b05b. +// +// Solidity: event IdentityRegistered(uint64 eon, bytes32 identityPrefix, address sender, uint64 timestamp) +func (_Shutterregistry *ShutterregistryFilterer) WatchIdentityRegistered(opts *bind.WatchOpts, sink chan<- *ShutterregistryIdentityRegistered) (event.Subscription, error) { + + logs, sub, err := _Shutterregistry.contract.WatchLogs(opts, "IdentityRegistered") + 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(ShutterregistryIdentityRegistered) + if err := _Shutterregistry.contract.UnpackLog(event, "IdentityRegistered", 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 +} + +// ParseIdentityRegistered is a log parse operation binding the contract event 0xa254e5a8078a79959db8c7203cbd84a28d6e1b9750d0c4fd743a1a069c21b05b. +// +// Solidity: event IdentityRegistered(uint64 eon, bytes32 identityPrefix, address sender, uint64 timestamp) +func (_Shutterregistry *ShutterregistryFilterer) ParseIdentityRegistered(log types.Log) (*ShutterregistryIdentityRegistered, error) { + event := new(ShutterregistryIdentityRegistered) + if err := _Shutterregistry.contract.UnpackLog(event, "IdentityRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ShutterregistryOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Shutterregistry contract. +type ShutterregistryOwnershipTransferredIterator struct { + Event *ShutterregistryOwnershipTransferred // 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 *ShutterregistryOwnershipTransferredIterator) 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(ShutterregistryOwnershipTransferred) + 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(ShutterregistryOwnershipTransferred) + 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 *ShutterregistryOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ShutterregistryOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ShutterregistryOwnershipTransferred represents a OwnershipTransferred event raised by the Shutterregistry contract. +type ShutterregistryOwnershipTransferred 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 (_Shutterregistry *ShutterregistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*ShutterregistryOwnershipTransferredIterator, 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 := _Shutterregistry.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &ShutterregistryOwnershipTransferredIterator{contract: _Shutterregistry.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 (_Shutterregistry *ShutterregistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ShutterregistryOwnershipTransferred, 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 := _Shutterregistry.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(ShutterregistryOwnershipTransferred) + if err := _Shutterregistry.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 (_Shutterregistry *ShutterregistryFilterer) ParseOwnershipTransferred(log types.Log) (*ShutterregistryOwnershipTransferred, error) { + event := new(ShutterregistryOwnershipTransferred) + if err := _Shutterregistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/foundry.toml b/foundry.toml index 121e417..3cf092a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ src = "src" out = "out" libs = ["lib"] -solc = "0.8.22" +solc = "0.8.28" extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] bytecode_hash = 'none' diff --git a/gen_bindings.sh b/gen_bindings.sh index 8c37ba6..f017c4c 100755 --- a/gen_bindings.sh +++ b/gen_bindings.sh @@ -8,6 +8,7 @@ CONTRACTS=( "EonKeyPublish" "KeyBroadcastContract" "Inbox" + "ShutterRegistry" ) OUTPUT_DIR="bindings" PACKAGE_NAME="bindings" diff --git a/script/Deploy.service.s.sol b/script/Deploy.service.s.sol new file mode 100644 index 0000000..4534d2e --- /dev/null +++ b/script/Deploy.service.s.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "../src/common/KeyBroadcastContract.sol"; +import "../src/common/KeyperSet.sol"; +import "../src/common/KeyperSetManager.sol"; +import "../src/shutter-service/ShutterRegistry.sol"; + +contract Deploy is Script { + function deployKeyperSetManager( + address deployerAddress + ) public returns (KeyperSetManager) { + KeyperSetManager ksm = new KeyperSetManager(deployerAddress); + ksm.initialize(deployerAddress, deployerAddress); + console.log("keyper set manager initialised"); + + // add bootstrap keyper set + KeyperSet fakeKeyperset = new KeyperSet(); + fakeKeyperset.setFinalized(); + ksm.addKeyperSet(0, address(fakeKeyperset)); + + console.log("KeyperSetManager:", address(ksm)); + return ksm; + } + + function deployKeyBroadcastContract( + KeyperSetManager ksm + ) public returns (KeyBroadcastContract) { + KeyBroadcastContract kbc = new KeyBroadcastContract(address(ksm)); + console.log("KeyBroadcastContract:", address(kbc)); + return kbc; + } + + function deployRegistry() public returns (ShutterRegistry) { + ShutterRegistry s = new ShutterRegistry(); + console.log("Registry:", address(s)); + return s; + } + + function run() external { + uint256 deployKey = vm.envUint("DEPLOY_KEY"); + address deployerAddress = vm.addr(deployKey); + console.log("Deployer:", deployerAddress); + vm.startBroadcast(deployKey); + + KeyperSetManager ksm = deployKeyperSetManager(deployerAddress); + deployKeyBroadcastContract(ksm); + deployRegistry(); + + vm.stopBroadcast(); + } +} diff --git a/script/DeployRegistry.service.s.sol b/script/DeployRegistry.service.s.sol new file mode 100644 index 0000000..85b6945 --- /dev/null +++ b/script/DeployRegistry.service.s.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "../src/shutter-service/ShutterRegistry.sol"; + +contract Deploy is Script { + function run() external { + uint256 deployKey = vm.envUint("DEPLOY_KEY"); + address deployerAddress = vm.addr(deployKey); + console.log("Deployer:", deployerAddress); + vm.startBroadcast(deployKey); + deploySequencer(); + vm.stopBroadcast(); + } + + function deploySequencer() public returns (ShutterRegistry) { + ShutterRegistry s = new ShutterRegistry(); + console.log("ShutterRegistry:", address(s)); + return s; + } +} diff --git a/script/SubmitTransaction.service.s.sol b/script/SubmitTransaction.service.s.sol new file mode 100644 index 0000000..7be93a7 --- /dev/null +++ b/script/SubmitTransaction.service.s.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import {ShutterRegistry} from "src/shutter-service/ShutterRegistry.sol"; + +contract SubmitTransaction is Script { + function run() external { + uint256 privateKey = vm.envUint("TX_SENDER_KEY"); + ShutterRegistry registry = ShutterRegistry( + vm.envAddress("REGISTRY_ADDRESS") + ); + uint64 eon = uint64(vm.envUint("EON")); + bytes32 identityPrefix = vm.envBytes32("IDENTITY_PREFIX"); + uint64 ts = uint64(vm.envUint("TIMESTAMP")); + + vm.startBroadcast(privateKey); + registry.register(eon, identityPrefix, ts); + vm.stopBroadcast(); + } +} diff --git a/src/shutter-service/ShutterRegistry.sol b/src/shutter-service/ShutterRegistry.sol new file mode 100644 index 0000000..4aa8f37 --- /dev/null +++ b/src/shutter-service/ShutterRegistry.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import "openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title ShutterRegistry + * @dev A contract for managing the registration of identities with timestamps, ensuring unique and future-dated registrations. + * Inherits from OpenZeppelin's Ownable contract to enable ownership-based access control. + */ +contract ShutterRegistry is Ownable { + // Custom error for when an identity is already registered. + error AlreadyRegistered(); + + // Custom error for when a provided timestamp is in the past. + error TimestampInThePast(); + + // Custom error for when a identityPrefix provided is empty. + error InvalidIdentityPrefix(); + + struct RegistrationData { + uint64 eon; + uint64 timestamp; + } + /** + * @dev Mapping to store registration data for each identity. + * The identity is represented as a `bytes32` hash and mapped to struct RegistrationData. + */ + mapping(bytes32 identity => RegistrationData) public registrations; + + /** + * @dev Emitted when a new identity is successfully registered. + * @param eon The eon associated with the identity. + * @param identityPrefix The raw prefix input used to derive the registered identity hash. + * @param sender The address of the account that performed the registration. + * @param timestamp The timestamp associated with the registered identity. + */ + event IdentityRegistered( + uint64 eon, + bytes32 identityPrefix, + address sender, + uint64 timestamp + ); + + /** + * @dev Initializes the contract and assigns ownership to the deployer. + */ + constructor() Ownable(msg.sender) {} + + /** + * @notice Registers a new identity with a specified timestamp and eon. + * @dev The identity is derived by hashing the provided `identityPrefix` concatenated with the sender's address. + * @param eon The eon associated with the identity. + * @param identityPrefix The input used to derive the identity hash. + * @param timestamp The future timestamp to be associated with the identity. + * @custom:requirements + * - The identity must not already be registered. + * - The provided timestamp must not be in the past. + */ + function register( + uint64 eon, + bytes32 identityPrefix, + uint64 timestamp + ) external { + // Ensure the timestamp is not in the past. + require(timestamp >= block.timestamp, TimestampInThePast()); + + // Ensure identityPrefix passed in correct. + require(identityPrefix != bytes32(0), InvalidIdentityPrefix()); + + // Generate the identity hash from the provided prefix and the sender's address. + bytes32 identity = keccak256( + abi.encodePacked(identityPrefix, msg.sender) + ); + RegistrationData storage registrationData = registrations[identity]; + // Ensure the identity is not already registered. + require(registrationData.timestamp == 0, AlreadyRegistered()); + + // Store the registration timestamp. + registrationData.eon = eon; + registrationData.timestamp = timestamp; + + // Emit the IdentityRegistered event. + emit IdentityRegistered(eon, identityPrefix, msg.sender, timestamp); + } +} diff --git a/test/ShutterRegistry.t.sol b/test/ShutterRegistry.t.sol new file mode 100644 index 0000000..efa0acf --- /dev/null +++ b/test/ShutterRegistry.t.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Test.sol"; +import "../src/shutter-service/ShutterRegistry.sol"; + +contract ShutterRegistryTest is Test { + ShutterRegistry public shutterRegistry; + + function setUp() public { + shutterRegistry = new ShutterRegistry(); + } + + function testIdentityRegistration() public { + uint64 eon = 5; + bytes32 identityPrefix = hex"001122"; + uint64 timestamp = uint64(block.timestamp) + 100; + address sender = makeAddr("sender"); + + vm.expectEmit(address(shutterRegistry)); + emit ShutterRegistry.IdentityRegistered( + eon, + identityPrefix, + sender, + timestamp + ); + + hoax(sender); + shutterRegistry.register(eon, identityPrefix, timestamp); + + bytes32 identity = keccak256(abi.encodePacked(identityPrefix, sender)); + (uint64 registeredEon, uint64 registeredTimestamp) = shutterRegistry + .registrations(identity); + + //verifying registered timestamp + assertEqUint(registeredEon, eon); + assertEqUint(registeredTimestamp, timestamp); + } + + function testDuplicateRegistration() public { + uint64 eon = 5; + bytes32 identityPrefix = hex"001122"; + uint64 timestamp = uint64(block.timestamp) + 100; + address sender = makeAddr("sender"); + + vm.expectEmit(address(shutterRegistry)); + emit ShutterRegistry.IdentityRegistered( + eon, + identityPrefix, + sender, + timestamp + ); + + hoax(sender); + shutterRegistry.register(eon, identityPrefix, timestamp); + + uint64 newTimestamp = uint64(block.timestamp) + 200; + vm.expectRevert(ShutterRegistry.AlreadyRegistered.selector); + hoax(sender); + shutterRegistry.register(eon, identityPrefix, newTimestamp); + + //verifying registered timestamp + bytes32 identity = keccak256(abi.encodePacked(identityPrefix, sender)); + (, uint64 registeredTimestamp) = shutterRegistry.registrations( + identity + ); + assertEqUint(registeredTimestamp, timestamp); + } + + function testInvalidTimestamp() public { + uint64 eon = 5; + bytes32 identityPrefix = hex"001122"; + uint64 timestamp = uint64(block.timestamp) - 1; + address sender = makeAddr("sender"); + + vm.expectRevert(ShutterRegistry.TimestampInThePast.selector); + hoax(sender); + shutterRegistry.register(eon, identityPrefix, timestamp); + } + + function testMissingIdentity() public { + uint64 eon = 5; + // zero bytes for identity prefix should fail + bytes32 identityPrefix = hex"00"; + uint64 timestamp = uint64(block.timestamp) + 100; + address sender = makeAddr("sender"); + + vm.expectRevert(ShutterRegistry.InvalidIdentityPrefix.selector); + hoax(sender); + shutterRegistry.register(eon, identityPrefix, timestamp); + } +}