mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 19:30:44 +00:00
add auction and abi binding
This commit is contained in:
parent
3cac28491c
commit
e3fd4af127
15 changed files with 881 additions and 108 deletions
603
core/TicketAllocator.go
Normal file
603
core/TicketAllocator.go
Normal file
|
|
@ -0,0 +1,603 @@
|
||||||
|
// Code generated - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = strings.NewReader
|
||||||
|
_ = ethereum.NotFound
|
||||||
|
_ = bind.Bind
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = event.NewSubscription
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// TicketAllocatorMetaData contains all meta data concerning the TicketAllocator contract.
|
||||||
|
var TicketAllocatorMetaData = &bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[],\"name\":\"InvalidBlockNumber\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughTickets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotSystemContract\",\"type\":\"error\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"GetBalance\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint16[]\",\"name\":\"\",\"type\":\"uint16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"numTickets\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"bidPerTicket\",\"type\":\"uint256\"}],\"name\":\"RequestTickets\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TIMEOUT\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TOTAL_TICKETS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balance\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"head\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pendingBids\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"requestor\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"amount\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"bidPerTicket\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"queue\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"amount\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"bidPerTicket\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"requestor\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"senders\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"withdrawable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorABI is the input ABI used to generate the binding from.
|
||||||
|
// Deprecated: Use TicketAllocatorMetaData.ABI instead.
|
||||||
|
var TicketAllocatorABI = TicketAllocatorMetaData.ABI
|
||||||
|
|
||||||
|
// TicketAllocator is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type TicketAllocator struct {
|
||||||
|
TicketAllocatorCaller // Read-only binding to the contract
|
||||||
|
TicketAllocatorTransactor // Write-only binding to the contract
|
||||||
|
TicketAllocatorFilterer // Log filterer for contract events
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorCaller is an auto generated read-only Go binding around an Ethereum contract.
|
||||||
|
type TicketAllocatorCaller struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorTransactor is an auto generated write-only Go binding around an Ethereum contract.
|
||||||
|
type TicketAllocatorTransactor struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
||||||
|
type TicketAllocatorFilterer struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorSession is an auto generated Go binding around an Ethereum contract,
|
||||||
|
// with pre-set call and transact options.
|
||||||
|
type TicketAllocatorSession struct {
|
||||||
|
Contract *TicketAllocator // 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorCallerSession is an auto generated read-only Go binding around an Ethereum contract,
|
||||||
|
// with pre-set call options.
|
||||||
|
type TicketAllocatorCallerSession struct {
|
||||||
|
Contract *TicketAllocatorCaller // Generic contract caller binding to set the session for
|
||||||
|
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
|
||||||
|
// with pre-set transact options.
|
||||||
|
type TicketAllocatorTransactorSession struct {
|
||||||
|
Contract *TicketAllocatorTransactor // Generic contract transactor binding to set the session for
|
||||||
|
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorRaw is an auto generated low-level Go binding around an Ethereum contract.
|
||||||
|
type TicketAllocatorRaw struct {
|
||||||
|
Contract *TicketAllocator // Generic contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
|
||||||
|
type TicketAllocatorCallerRaw struct {
|
||||||
|
Contract *TicketAllocatorCaller // Generic read-only contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketAllocatorTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
|
||||||
|
type TicketAllocatorTransactorRaw struct {
|
||||||
|
Contract *TicketAllocatorTransactor // Generic write-only contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTicketAllocator creates a new instance of TicketAllocator, bound to a specific deployed contract.
|
||||||
|
func NewTicketAllocator(address common.Address, backend bind.ContractBackend) (*TicketAllocator, error) {
|
||||||
|
contract, err := bindTicketAllocator(address, backend, backend, backend)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TicketAllocator{TicketAllocatorCaller: TicketAllocatorCaller{contract: contract}, TicketAllocatorTransactor: TicketAllocatorTransactor{contract: contract}, TicketAllocatorFilterer: TicketAllocatorFilterer{contract: contract}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTicketAllocatorCaller creates a new read-only instance of TicketAllocator, bound to a specific deployed contract.
|
||||||
|
func NewTicketAllocatorCaller(address common.Address, caller bind.ContractCaller) (*TicketAllocatorCaller, error) {
|
||||||
|
contract, err := bindTicketAllocator(address, caller, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TicketAllocatorCaller{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTicketAllocatorTransactor creates a new write-only instance of TicketAllocator, bound to a specific deployed contract.
|
||||||
|
func NewTicketAllocatorTransactor(address common.Address, transactor bind.ContractTransactor) (*TicketAllocatorTransactor, error) {
|
||||||
|
contract, err := bindTicketAllocator(address, nil, transactor, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TicketAllocatorTransactor{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTicketAllocatorFilterer creates a new log filterer instance of TicketAllocator, bound to a specific deployed contract.
|
||||||
|
func NewTicketAllocatorFilterer(address common.Address, filterer bind.ContractFilterer) (*TicketAllocatorFilterer, error) {
|
||||||
|
contract, err := bindTicketAllocator(address, nil, nil, filterer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TicketAllocatorFilterer{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindTicketAllocator binds a generic wrapper to an already deployed contract.
|
||||||
|
func bindTicketAllocator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
||||||
|
parsed, err := TicketAllocatorMetaData.GetAbi()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call invokes the (constant) contract method with params as input values and
|
||||||
|
// sets the output to result. The result type might be a single field for simple
|
||||||
|
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||||
|
// returns.
|
||||||
|
func (_TicketAllocator *TicketAllocatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
||||||
|
return _TicketAllocator.Contract.TicketAllocatorCaller.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 (_TicketAllocator *TicketAllocatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.TicketAllocatorTransactor.contract.Transfer(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
|
func (_TicketAllocator *TicketAllocatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.TicketAllocatorTransactor.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 (_TicketAllocator *TicketAllocatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
||||||
|
return _TicketAllocator.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 (_TicketAllocator *TicketAllocatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.contract.Transfer(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.contract.Transact(opts, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBalance is a free data retrieval call binding the contract method 0xf8f8a912.
|
||||||
|
//
|
||||||
|
// Solidity: function GetBalance() view returns(address[], uint16[])
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) GetBalance(opts *bind.CallOpts) ([]common.Address, []uint16, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "GetBalance")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new([]common.Address), *new([]uint16), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address)
|
||||||
|
out1 := *abi.ConvertType(out[1], new([]uint16)).(*[]uint16)
|
||||||
|
|
||||||
|
return out0, out1, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBalance is a free data retrieval call binding the contract method 0xf8f8a912.
|
||||||
|
//
|
||||||
|
// Solidity: function GetBalance() view returns(address[], uint16[])
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) GetBalance() ([]common.Address, []uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.GetBalance(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBalance is a free data retrieval call binding the contract method 0xf8f8a912.
|
||||||
|
//
|
||||||
|
// Solidity: function GetBalance() view returns(address[], uint16[])
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) GetBalance() ([]common.Address, []uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.GetBalance(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TIMEOUT is a free data retrieval call binding the contract method 0xf56f48f2.
|
||||||
|
//
|
||||||
|
// Solidity: function TIMEOUT() view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) TIMEOUT(opts *bind.CallOpts) (uint16, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "TIMEOUT")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(uint16), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TIMEOUT is a free data retrieval call binding the contract method 0xf56f48f2.
|
||||||
|
//
|
||||||
|
// Solidity: function TIMEOUT() view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) TIMEOUT() (uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.TIMEOUT(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TIMEOUT is a free data retrieval call binding the contract method 0xf56f48f2.
|
||||||
|
//
|
||||||
|
// Solidity: function TIMEOUT() view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) TIMEOUT() (uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.TIMEOUT(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOTALTICKETS is a free data retrieval call binding the contract method 0xafbd1782.
|
||||||
|
//
|
||||||
|
// Solidity: function TOTAL_TICKETS() view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) TOTALTICKETS(opts *bind.CallOpts) (uint16, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "TOTAL_TICKETS")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(uint16), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOTALTICKETS is a free data retrieval call binding the contract method 0xafbd1782.
|
||||||
|
//
|
||||||
|
// Solidity: function TOTAL_TICKETS() view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) TOTALTICKETS() (uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.TOTALTICKETS(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOTALTICKETS is a free data retrieval call binding the contract method 0xafbd1782.
|
||||||
|
//
|
||||||
|
// Solidity: function TOTAL_TICKETS() view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) TOTALTICKETS() (uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.TOTALTICKETS(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance is a free data retrieval call binding the contract method 0xe3d670d7.
|
||||||
|
//
|
||||||
|
// Solidity: function balance(address ) view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) Balance(opts *bind.CallOpts, arg0 common.Address) (uint16, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "balance", arg0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(uint16), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance is a free data retrieval call binding the contract method 0xe3d670d7.
|
||||||
|
//
|
||||||
|
// Solidity: function balance(address ) view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Balance(arg0 common.Address) (uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.Balance(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance is a free data retrieval call binding the contract method 0xe3d670d7.
|
||||||
|
//
|
||||||
|
// Solidity: function balance(address ) view returns(uint16)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) Balance(arg0 common.Address) (uint16, error) {
|
||||||
|
return _TicketAllocator.Contract.Balance(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head is a free data retrieval call binding the contract method 0xbda4fec5.
|
||||||
|
//
|
||||||
|
// Solidity: function head(address ) view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) Head(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "head", arg0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(*big.Int), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head is a free data retrieval call binding the contract method 0xbda4fec5.
|
||||||
|
//
|
||||||
|
// Solidity: function head(address ) view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Head(arg0 common.Address) (*big.Int, error) {
|
||||||
|
return _TicketAllocator.Contract.Head(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head is a free data retrieval call binding the contract method 0xbda4fec5.
|
||||||
|
//
|
||||||
|
// Solidity: function head(address ) view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) Head(arg0 common.Address) (*big.Int, error) {
|
||||||
|
return _TicketAllocator.Contract.Head(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PendingBids is a free data retrieval call binding the contract method 0xcf8589b9.
|
||||||
|
//
|
||||||
|
// Solidity: function pendingBids(uint256 ) view returns(address sender, address requestor, uint16 amount, uint256 bidPerTicket)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) PendingBids(opts *bind.CallOpts, arg0 *big.Int) (struct {
|
||||||
|
Sender common.Address
|
||||||
|
Requestor common.Address
|
||||||
|
Amount uint16
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
}, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "pendingBids", arg0)
|
||||||
|
|
||||||
|
outstruct := new(struct {
|
||||||
|
Sender common.Address
|
||||||
|
Requestor common.Address
|
||||||
|
Amount uint16
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
|
||||||
|
outstruct.Sender = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
|
||||||
|
outstruct.Requestor = *abi.ConvertType(out[1], new(common.Address)).(*common.Address)
|
||||||
|
outstruct.Amount = *abi.ConvertType(out[2], new(uint16)).(*uint16)
|
||||||
|
outstruct.BidPerTicket = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int)
|
||||||
|
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PendingBids is a free data retrieval call binding the contract method 0xcf8589b9.
|
||||||
|
//
|
||||||
|
// Solidity: function pendingBids(uint256 ) view returns(address sender, address requestor, uint16 amount, uint256 bidPerTicket)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) PendingBids(arg0 *big.Int) (struct {
|
||||||
|
Sender common.Address
|
||||||
|
Requestor common.Address
|
||||||
|
Amount uint16
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
}, error) {
|
||||||
|
return _TicketAllocator.Contract.PendingBids(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PendingBids is a free data retrieval call binding the contract method 0xcf8589b9.
|
||||||
|
//
|
||||||
|
// Solidity: function pendingBids(uint256 ) view returns(address sender, address requestor, uint16 amount, uint256 bidPerTicket)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) PendingBids(arg0 *big.Int) (struct {
|
||||||
|
Sender common.Address
|
||||||
|
Requestor common.Address
|
||||||
|
Amount uint16
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
}, error) {
|
||||||
|
return _TicketAllocator.Contract.PendingBids(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PendingBlock is a free data retrieval call binding the contract method 0xd33d9969.
|
||||||
|
//
|
||||||
|
// Solidity: function pendingBlock() view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) PendingBlock(opts *bind.CallOpts) (*big.Int, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "pendingBlock")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(*big.Int), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PendingBlock is a free data retrieval call binding the contract method 0xd33d9969.
|
||||||
|
//
|
||||||
|
// Solidity: function pendingBlock() view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) PendingBlock() (*big.Int, error) {
|
||||||
|
return _TicketAllocator.Contract.PendingBlock(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PendingBlock is a free data retrieval call binding the contract method 0xd33d9969.
|
||||||
|
//
|
||||||
|
// Solidity: function pendingBlock() view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) PendingBlock() (*big.Int, error) {
|
||||||
|
return _TicketAllocator.Contract.PendingBlock(&_TicketAllocator.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue is a free data retrieval call binding the contract method 0x44287113.
|
||||||
|
//
|
||||||
|
// Solidity: function queue(address , uint256 ) view returns(uint16 amount, uint256 blockNumber, uint256 bidPerTicket, address requestor)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) Queue(opts *bind.CallOpts, arg0 common.Address, arg1 *big.Int) (struct {
|
||||||
|
Amount uint16
|
||||||
|
BlockNumber *big.Int
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
Requestor common.Address
|
||||||
|
}, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "queue", arg0, arg1)
|
||||||
|
|
||||||
|
outstruct := new(struct {
|
||||||
|
Amount uint16
|
||||||
|
BlockNumber *big.Int
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
Requestor common.Address
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
|
||||||
|
outstruct.Amount = *abi.ConvertType(out[0], new(uint16)).(*uint16)
|
||||||
|
outstruct.BlockNumber = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int)
|
||||||
|
outstruct.BidPerTicket = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int)
|
||||||
|
outstruct.Requestor = *abi.ConvertType(out[3], new(common.Address)).(*common.Address)
|
||||||
|
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue is a free data retrieval call binding the contract method 0x44287113.
|
||||||
|
//
|
||||||
|
// Solidity: function queue(address , uint256 ) view returns(uint16 amount, uint256 blockNumber, uint256 bidPerTicket, address requestor)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Queue(arg0 common.Address, arg1 *big.Int) (struct {
|
||||||
|
Amount uint16
|
||||||
|
BlockNumber *big.Int
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
Requestor common.Address
|
||||||
|
}, error) {
|
||||||
|
return _TicketAllocator.Contract.Queue(&_TicketAllocator.CallOpts, arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue is a free data retrieval call binding the contract method 0x44287113.
|
||||||
|
//
|
||||||
|
// Solidity: function queue(address , uint256 ) view returns(uint16 amount, uint256 blockNumber, uint256 bidPerTicket, address requestor)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) Queue(arg0 common.Address, arg1 *big.Int) (struct {
|
||||||
|
Amount uint16
|
||||||
|
BlockNumber *big.Int
|
||||||
|
BidPerTicket *big.Int
|
||||||
|
Requestor common.Address
|
||||||
|
}, error) {
|
||||||
|
return _TicketAllocator.Contract.Queue(&_TicketAllocator.CallOpts, arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Senders is a free data retrieval call binding the contract method 0x9977c78a.
|
||||||
|
//
|
||||||
|
// Solidity: function senders(uint256 ) view returns(address)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) Senders(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "senders", arg0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(common.Address), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Senders is a free data retrieval call binding the contract method 0x9977c78a.
|
||||||
|
//
|
||||||
|
// Solidity: function senders(uint256 ) view returns(address)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Senders(arg0 *big.Int) (common.Address, error) {
|
||||||
|
return _TicketAllocator.Contract.Senders(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Senders is a free data retrieval call binding the contract method 0x9977c78a.
|
||||||
|
//
|
||||||
|
// Solidity: function senders(uint256 ) view returns(address)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) Senders(arg0 *big.Int) (common.Address, error) {
|
||||||
|
return _TicketAllocator.Contract.Senders(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdrawable is a free data retrieval call binding the contract method 0xce513b6f.
|
||||||
|
//
|
||||||
|
// Solidity: function withdrawable(address ) view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCaller) Withdrawable(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _TicketAllocator.contract.Call(opts, &out, "withdrawable", arg0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *new(*big.Int), err
|
||||||
|
}
|
||||||
|
|
||||||
|
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
|
||||||
|
|
||||||
|
return out0, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdrawable is a free data retrieval call binding the contract method 0xce513b6f.
|
||||||
|
//
|
||||||
|
// Solidity: function withdrawable(address ) view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Withdrawable(arg0 common.Address) (*big.Int, error) {
|
||||||
|
return _TicketAllocator.Contract.Withdrawable(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdrawable is a free data retrieval call binding the contract method 0xce513b6f.
|
||||||
|
//
|
||||||
|
// Solidity: function withdrawable(address ) view returns(uint256)
|
||||||
|
func (_TicketAllocator *TicketAllocatorCallerSession) Withdrawable(arg0 common.Address) (*big.Int, error) {
|
||||||
|
return _TicketAllocator.Contract.Withdrawable(&_TicketAllocator.CallOpts, arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestTickets is a paid mutator transaction binding the contract method 0x91ef4c9d.
|
||||||
|
//
|
||||||
|
// Solidity: function RequestTickets(address sender, uint16 numTickets, uint256 bidPerTicket) payable returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactor) RequestTickets(opts *bind.TransactOpts, sender common.Address, numTickets uint16, bidPerTicket *big.Int) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.contract.Transact(opts, "RequestTickets", sender, numTickets, bidPerTicket)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestTickets is a paid mutator transaction binding the contract method 0x91ef4c9d.
|
||||||
|
//
|
||||||
|
// Solidity: function RequestTickets(address sender, uint16 numTickets, uint256 bidPerTicket) payable returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) RequestTickets(sender common.Address, numTickets uint16, bidPerTicket *big.Int) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.RequestTickets(&_TicketAllocator.TransactOpts, sender, numTickets, bidPerTicket)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestTickets is a paid mutator transaction binding the contract method 0x91ef4c9d.
|
||||||
|
//
|
||||||
|
// Solidity: function RequestTickets(address sender, uint16 numTickets, uint256 bidPerTicket) payable returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactorSession) RequestTickets(sender common.Address, numTickets uint16, bidPerTicket *big.Int) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.RequestTickets(&_TicketAllocator.TransactOpts, sender, numTickets, bidPerTicket)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b.
|
||||||
|
//
|
||||||
|
// Solidity: function withdraw() returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactor) Withdraw(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.contract.Transact(opts, "withdraw")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b.
|
||||||
|
//
|
||||||
|
// Solidity: function withdraw() returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Withdraw() (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.Withdraw(&_TicketAllocator.TransactOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b.
|
||||||
|
//
|
||||||
|
// Solidity: function withdraw() returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactorSession) Withdraw() (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.Withdraw(&_TicketAllocator.TransactOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
|
//
|
||||||
|
// Solidity: fallback() returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.contract.RawTransact(opts, calldata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
|
//
|
||||||
|
// Solidity: fallback() returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.Fallback(&_TicketAllocator.TransactOpts, calldata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
|
//
|
||||||
|
// Solidity: fallback() returns()
|
||||||
|
func (_TicketAllocator *TicketAllocatorTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||||
|
return _TicketAllocator.Contract.Fallback(&_TicketAllocator.TransactOpts, calldata)
|
||||||
|
}
|
||||||
|
|
@ -6,67 +6,168 @@ contract TicketAllocator {
|
||||||
|
|
||||||
error NotEnoughTickets();
|
error NotEnoughTickets();
|
||||||
error NotSystemContract();
|
error NotSystemContract();
|
||||||
|
error InvalidPayment();
|
||||||
|
|
||||||
struct Ticket {
|
struct Ticket {
|
||||||
uint16 amount;
|
uint16 amount;
|
||||||
uint256 blockNumber;
|
uint256 blockNumber;
|
||||||
|
uint256 bidPerTicket;
|
||||||
|
address requestor; // address that requested the tickets
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PendingBid {
|
||||||
|
address sender;
|
||||||
|
address requestor; // address that called RequestTickets
|
||||||
|
uint16 amount;
|
||||||
|
uint256 bidPerTicket;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping(address => Ticket[]) public queue;
|
mapping(address => Ticket[]) public queue;
|
||||||
mapping(address => uint256) public head;
|
mapping(address => uint256) public head;
|
||||||
mapping(address => uint16) public balance;
|
mapping(address => uint16) public balance;
|
||||||
|
mapping(address => uint256) public withdrawable; // amount available for withdrawal
|
||||||
|
|
||||||
address[] public senders; // list of senders with >0 balance
|
address[] public senders; // list of senders with >0 balance
|
||||||
|
|
||||||
uint16 public constant TOTAL_TICKETS = 21;
|
uint16 public constant TOTAL_TICKETS = 21;
|
||||||
uint16 public constant TIMEOUT = 2;
|
uint16 public constant TIMEOUT = 2;
|
||||||
|
|
||||||
uint256 private leftTickets;
|
|
||||||
uint256 private lastRequestBlock;
|
|
||||||
|
|
||||||
function requestTickets(address sender, uint16 numTickets) external {
|
PendingBid[] public pendingBids;
|
||||||
uint256 currentBlock = block.number;
|
uint256 public pendingBlock;
|
||||||
|
|
||||||
if (currentBlock != lastRequestBlock) {
|
function GetBalance() public view returns (address[] memory, uint16[] memory){
|
||||||
leftTickets = TOTAL_TICKETS;
|
uint16[] memory res;
|
||||||
lastRequestBlock = currentBlock;
|
res = new uint16[](senders.length);
|
||||||
|
for (uint256 i = 0; i < senders.length; i++) {
|
||||||
|
res[i] = balance[senders[i]];
|
||||||
|
}
|
||||||
|
return (senders, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _addModified(
|
||||||
|
address sender,
|
||||||
|
address[] memory modified,
|
||||||
|
uint256 modifiedCount
|
||||||
|
) private pure returns (uint256) {
|
||||||
|
for (uint256 i = 0; i < modifiedCount; i++) {
|
||||||
|
if (modified[i] == sender) {
|
||||||
|
return modifiedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modified[modifiedCount] = sender;
|
||||||
|
return modifiedCount + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RequestTickets(address sender, uint16 numTickets, uint256 bidPerTicket) external payable {
|
||||||
|
// Check payment matches the declared bid
|
||||||
|
if (msg.value != uint256(numTickets) * bidPerTicket) {
|
||||||
|
revert InvalidPayment();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numTickets > leftTickets) {
|
// Reset pending bids if we moved to a new block
|
||||||
revert NotEnoughTickets();
|
if (block.number != pendingBlock) {
|
||||||
|
delete pendingBids;
|
||||||
|
pendingBlock = block.number;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (balance[sender] == 0) {
|
pendingBids.push(PendingBid({
|
||||||
senders.push(sender);
|
sender: sender,
|
||||||
}
|
requestor: msg.sender,
|
||||||
|
|
||||||
queue[sender].push(Ticket({
|
|
||||||
amount: numTickets,
|
amount: numTickets,
|
||||||
blockNumber: currentBlock
|
bidPerTicket: bidPerTicket
|
||||||
}));
|
}));
|
||||||
|
|
||||||
balance[sender] += numTickets;
|
|
||||||
leftTickets -= numTickets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBalance(address sender) public view returns(uint) {
|
function withdraw() external {
|
||||||
return balance[sender];
|
uint256 amount = withdrawable[msg.sender];
|
||||||
|
if (amount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
withdrawable[msg.sender] = 0;
|
||||||
|
(bool success, ) = payable(msg.sender).call{value: amount}("");
|
||||||
|
require(success, "withdrawal failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// System call:
|
// System call:
|
||||||
// 1. remove expired and used tickets
|
// 1. allocate tickets for this block based on bids
|
||||||
// - for used tickets, the oldest ticket is removed first
|
// 2. process used and expired tickets, refunding bids for used tickets
|
||||||
// 3. return the overall sender balances
|
// 3. return modified addresses and their balances
|
||||||
fallback(bytes calldata input) external returns (bytes memory) {
|
fallback(bytes calldata input) external returns (bytes memory) {
|
||||||
if (msg.sender != SYSTEM_ADDRESS) revert NotSystemContract();
|
if (msg.sender != SYSTEM_ADDRESS) revert NotSystemContract();
|
||||||
|
|
||||||
address[] memory usedSenders;
|
address[] memory usedSenders;
|
||||||
uint16[] memory usedAmounts;
|
uint16[] memory usedAmounts;
|
||||||
|
|
||||||
if (input.length > 0) {
|
if (input.length > 0) {
|
||||||
(usedSenders, usedAmounts) = abi.decode(input, (address[], uint16[]));
|
(usedSenders, usedAmounts) = abi.decode(input, (address[], uint16[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track modified addresses for this system call
|
||||||
|
address[] memory modified = new address[](senders.length + pendingBids.length);
|
||||||
|
uint256 modifiedCount = 0;
|
||||||
|
|
||||||
|
// Step 1: allocate tickets for this block based on bids
|
||||||
|
if (pendingBlock == block.number && pendingBids.length > 0) {
|
||||||
|
// Sort pending bids by bidPerTicket in descending order (bubble sort on storage)
|
||||||
|
uint256 n = pendingBids.length;
|
||||||
|
for (uint256 i = 0; i < n; i++) {
|
||||||
|
for (uint256 j = i + 1; j < n; j++) {
|
||||||
|
if (pendingBids[j].bidPerTicket > pendingBids[i].bidPerTicket) {
|
||||||
|
PendingBid memory tmp = pendingBids[i];
|
||||||
|
pendingBids[i] = pendingBids[j];
|
||||||
|
pendingBids[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 remaining = TOTAL_TICKETS;
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < n; i++) {
|
||||||
|
PendingBid storage bid = pendingBids[i];
|
||||||
|
if (bid.amount == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 alloc = bid.amount;
|
||||||
|
if (alloc > remaining) {
|
||||||
|
alloc = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alloc > 0) {
|
||||||
|
// Allocate tickets and keep the payment locked until used or expired
|
||||||
|
if (balance[bid.sender] == 0) {
|
||||||
|
senders.push(bid.sender);
|
||||||
|
}
|
||||||
|
queue[bid.sender].push(Ticket({
|
||||||
|
amount: alloc,
|
||||||
|
blockNumber: block.number,
|
||||||
|
bidPerTicket: bid.bidPerTicket,
|
||||||
|
requestor: bid.requestor
|
||||||
|
}));
|
||||||
|
balance[bid.sender] += alloc;
|
||||||
|
remaining -= alloc;
|
||||||
|
|
||||||
|
// mark modified
|
||||||
|
modifiedCount = _addModified(bid.sender, modified, modifiedCount);
|
||||||
|
|
||||||
|
// Add unallocated portion to withdrawal, if any
|
||||||
|
if (bid.amount > alloc) {
|
||||||
|
uint16 unfilled = bid.amount - alloc;
|
||||||
|
uint256 refund = uint256(unfilled) * bid.bidPerTicket;
|
||||||
|
withdrawable[bid.requestor] += refund;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No tickets left, full refund to withdrawal
|
||||||
|
uint256 refundAll = uint256(bid.amount) * bid.bidPerTicket;
|
||||||
|
withdrawable[bid.requestor] += refundAll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pendingBids;
|
||||||
|
pendingBlock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: process used and expired tickets, refunding bids for used tickets
|
||||||
for (uint256 s = 0; s < senders.length; ) {
|
for (uint256 s = 0; s < senders.length; ) {
|
||||||
address sender = senders[s];
|
address sender = senders[s];
|
||||||
Ticket[] storage senderQueue = queue[sender];
|
Ticket[] storage senderQueue = queue[sender];
|
||||||
|
|
@ -89,23 +190,29 @@ contract TicketAllocator {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expired tickets: burn the funds paid for these tickets
|
||||||
if (ticket.blockNumber + TIMEOUT < block.number) {
|
if (ticket.blockNumber + TIMEOUT < block.number) {
|
||||||
// remove expired tickets (comsume used tickets if possible)
|
|
||||||
balance[sender] -= ticket.amount;
|
balance[sender] -= ticket.amount;
|
||||||
if (used > 0) {
|
|
||||||
// used = max(0, used - t.amount)
|
|
||||||
uint16 deduct = used > ticket.amount ? ticket.amount : used;
|
|
||||||
used -= deduct;
|
|
||||||
}
|
|
||||||
ticket.amount = 0;
|
ticket.amount = 0;
|
||||||
senderHead++;
|
senderHead++;
|
||||||
|
|
||||||
|
// Burn by sending to address(0)
|
||||||
|
(bool success, ) = payable(address(0)).call{value: ticket.amount * ticket.bidPerTicket}("");
|
||||||
|
require(success, "burn failed");
|
||||||
|
|
||||||
|
// mark modified
|
||||||
|
modifiedCount = _addModified(sender, modified, modifiedCount);
|
||||||
} else if (used > 0) {
|
} else if (used > 0) {
|
||||||
// remove used ticekts (for now we don't revert when the ticket amount is less than used tickets)
|
// Used tickets: add refund to withdrawal for the requestor
|
||||||
uint16 deduct = used > ticket.amount ? ticket.amount : used;
|
uint16 deduct = used > ticket.amount ? ticket.amount : used;
|
||||||
ticket.amount -= uint16(deduct);
|
ticket.amount -= deduct;
|
||||||
balance[sender] -= deduct;
|
balance[sender] -= deduct;
|
||||||
used -= deduct;
|
used -= deduct;
|
||||||
|
uint256 refund = uint256(deduct) * ticket.bidPerTicket;
|
||||||
|
withdrawable[ticket.requestor] += refund;
|
||||||
|
|
||||||
|
// mark modified
|
||||||
|
modifiedCount = _addModified(sender, modified, modifiedCount);
|
||||||
|
|
||||||
if (ticket.amount == 0) senderHead++;
|
if (ticket.amount == 0) senderHead++;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -124,15 +231,13 @@ contract TicketAllocator {
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the active senders and their balances
|
// Step 3: return modified addresses and their balances
|
||||||
address[] memory activeSenders = new address[](senders.length);
|
address[] memory modifiedAddress = new address[](modifiedCount);
|
||||||
uint16[] memory activeBalances = new uint16[](senders.length);
|
uint16[] memory modifiedTickets = new uint16[](modifiedCount);
|
||||||
|
for (uint256 i = 0; i < modifiedCount; i++) {
|
||||||
for (uint256 i = 0; i < senders.length; i++) {
|
modifiedAddress[i] = modified[i];
|
||||||
activeSenders[i] = senders[i];
|
modifiedTickets[i] = balance[modified[i]];
|
||||||
activeBalances[i] = balance[senders[i]];
|
|
||||||
}
|
}
|
||||||
|
return abi.encode(modifiedAddress, modifiedTickets);
|
||||||
return abi.encode(activeSenders, activeBalances);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2280,22 +2280,18 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ticket balances of this block and remove the parent block data
|
// Add ticket balances of this block and remove the parent block data
|
||||||
bc.tickets[block.Hash()] = res.Tickets
|
if parent, ok := bc.tickets[block.ParentHash()]; ok {
|
||||||
if _, ok := bc.ticketBlocks[block.Number()]; !ok {
|
|
||||||
bc.ticketBlocks[block.Number()] = make([]common.Hash, 0)
|
|
||||||
}
|
|
||||||
bc.ticketBlocks[block.Number()] = append(bc.ticketBlocks[block.Number()], block.Hash())
|
|
||||||
|
|
||||||
if _, ok := bc.tickets[block.ParentHash()]; ok {
|
|
||||||
delete(bc.tickets, block.ParentHash())
|
delete(bc.tickets, block.ParentHash())
|
||||||
if hashes := bc.ticketBlocks[block.Number().Sub(block.Number(), big.NewInt(1))]; len(hashes) != 0 {
|
bc.tickets[block.Hash()] = parent
|
||||||
for i, hash := range hashes {
|
for addr, value := range res.Tickets {
|
||||||
if hash.Cmp(block.ParentHash()) == 0 {
|
if value == 0 {
|
||||||
hashes[i] = hashes[len(hashes)-1]
|
delete(bc.tickets[block.Hash()], addr)
|
||||||
hashes = hashes[:len(hashes)-1]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
bc.tickets[block.Hash()][addr] = value
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
res, _ := bc.GetTicketBalance(block.Header())
|
||||||
|
bc.tickets[block.Hash()] = res
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report the collected witness statistics
|
// Report the collected witness statistics
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
|
|
@ -29,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
|
@ -354,33 +354,43 @@ func (bc *BlockChain) GetCanonicalTransaction(hash common.Hash) (*rawdb.LegacyTx
|
||||||
return lookup, tx
|
return lookup, tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *BlockChain) GetTicketBalance(hash common.Hash, statedb *state.StateDB) map[common.Address]uint16 {
|
func (bc *BlockChain) GetTicketBalance(header *types.Header) (map[common.Address]uint16, error) {
|
||||||
if bc.tickets[hash] != nil {
|
if bc.tickets[header.Hash()] != nil {
|
||||||
return bc.tickets[hash]
|
return bc.tickets[header.Hash()], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := NewEVMBlockContext(header, bc.HeaderChain(), nil)
|
||||||
|
statedb, err := bc.StateAt(header.Root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
evm := vm.NewEVM(ctx, statedb, bc.chainConfig, bc.cfg.VmConfig)
|
||||||
|
cc := contractCaller{addr: params.BlobTicketAllocationAddress, evm: evm}
|
||||||
|
caller, err := NewTicketAllocatorCaller(params.BlobTicketAllocationAddress, cc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
senders, balances, err := caller.GetBalance(&bind.CallOpts{BlockNumber: header.Number})
|
||||||
|
if err != nil {
|
||||||
|
// when the contract is not deployed, return empty map
|
||||||
|
if errors.Is(err, bind.ErrNoCode) {
|
||||||
|
result := make(map[common.Address]uint16)
|
||||||
|
bc.tickets[header.Hash()] = result
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make(map[common.Address]uint16)
|
result := make(map[common.Address]uint16)
|
||||||
|
|
||||||
senders := statedb.GetState(params.BlobTicketAllocationAddress, common.BigToHash(params.BlobTicketSenderSlot)).Big().Int64()
|
for i, sender := range senders {
|
||||||
base := crypto.Keccak256Hash(common.LeftPadBytes(params.BlobTicketSenderSlot.Bytes(), 32)).Big()
|
result[sender] = uint16(balances[i])
|
||||||
|
|
||||||
for i := range senders {
|
|
||||||
key := common.BigToHash(base.Add(base, big.NewInt(i)))
|
|
||||||
sender := common.BytesToAddress(statedb.GetState(params.BlobTicketAllocationAddress, key).Bytes())
|
|
||||||
|
|
||||||
key = crypto.Keccak256Hash(
|
|
||||||
append(
|
|
||||||
common.LeftPadBytes(sender.Bytes(), 32),
|
|
||||||
common.LeftPadBytes(params.BlobTicketBalanceSlot.Bytes(), 32)...,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
balance := statedb.GetState(params.BlobTicketAllocationAddress, key).Big().Uint64()
|
|
||||||
|
|
||||||
result[sender] = uint16(balance)
|
|
||||||
}
|
}
|
||||||
|
bc.tickets[header.Hash()] = result
|
||||||
|
|
||||||
return result
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxIndexDone returns true if the transaction indexer has finished indexing.
|
// TxIndexDone returns true if the transaction indexer has finished indexing.
|
||||||
|
|
|
||||||
|
|
@ -4211,11 +4211,12 @@ func TestBlobTickets(t *testing.T) {
|
||||||
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, bg *BlockGen) {
|
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, bg *BlockGen) {
|
||||||
switch i {
|
switch i {
|
||||||
case 0: // create ticket request
|
case 0: // create ticket request
|
||||||
selector := crypto.Keccak256([]byte("requestTickets(address,uint16)"))[:4]
|
selector := crypto.Keccak256([]byte("RequestTickets(address,uint16,uint256)"))[:4]
|
||||||
uint16Type, _ := abi.NewType("uint16", "", nil)
|
uint16Type, _ := abi.NewType("uint16", "", nil)
|
||||||
addressType, _ := abi.NewType("address", "", nil)
|
addressType, _ := abi.NewType("address", "", nil)
|
||||||
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}}
|
uint256Type, _ := abi.NewType("uint256", "", nil)
|
||||||
data, _ := args.Pack(addr1, ticketAmount)
|
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}, {Type: uint256Type}}
|
||||||
|
data, _ := args.Pack(addr1, ticketAmount, big.NewInt(1))
|
||||||
|
|
||||||
data = append(selector, data...)
|
data = append(selector, data...)
|
||||||
|
|
||||||
|
|
@ -4227,6 +4228,7 @@ func TestBlobTickets(t *testing.T) {
|
||||||
GasFeeCap: big.NewInt(875000000),
|
GasFeeCap: big.NewInt(875000000),
|
||||||
GasTipCap: big.NewInt(1),
|
GasTipCap: big.NewInt(1),
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Value: big.NewInt(int64(ticketAmount)),
|
||||||
}
|
}
|
||||||
tx := types.MustSignNewTx(key1, signer, txdata)
|
tx := types.MustSignNewTx(key1, signer, txdata)
|
||||||
|
|
||||||
|
|
@ -4297,15 +4299,13 @@ func TestBlobTickets(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// previous block ticket balance
|
// previous block ticket balance
|
||||||
state, _ := chain.StateAt(blocks[0].Root())
|
balance, _ = chain.GetTicketBalance(blocks[0].Header())
|
||||||
balance = chain.GetTicketBalance(blocks[0].Hash(), state)
|
|
||||||
amount = balance[addr1]
|
amount = balance[addr1]
|
||||||
if amount != ticketAmount {
|
if amount != ticketAmount {
|
||||||
t.Fatalf("wrong ticket amount: expected %d, got %d", ticketAmount, amount)
|
t.Fatalf("wrong ticket amount: expected %d, got %d", ticketAmount, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
state, _ = chain.StateAt(blocks[1].Root())
|
balance, _ = chain.GetTicketBalance(blocks[1].Header())
|
||||||
balance = chain.GetTicketBalance(blocks[1].Hash(), state)
|
|
||||||
amount = balance[addr1]
|
amount = balance[addr1]
|
||||||
if amount != ticketAmount-1 {
|
if amount != ticketAmount-1 {
|
||||||
t.Fatalf("wrong ticket amount: expected %d, got %d", ticketAmount-1, amount)
|
t.Fatalf("wrong ticket amount: expected %d, got %d", ticketAmount-1, amount)
|
||||||
|
|
|
||||||
45
core/contract_caller.go
Normal file
45
core/contract_caller.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
)
|
||||||
|
|
||||||
|
type contractCaller struct {
|
||||||
|
evm *vm.EVM
|
||||||
|
addr common.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c contractCaller) CodeAt(ctx context.Context, addr common.Address, blockNumber *big.Int) ([]byte, error) {
|
||||||
|
return c.evm.StateDB.GetCode(addr), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c contractCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
|
||||||
|
value := new(uint256.Int)
|
||||||
|
if call.Value != nil {
|
||||||
|
value.SetFromBig(call.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
from := call.From
|
||||||
|
if from == (common.Address{}) {
|
||||||
|
from = params.SystemAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// when gas is set to zero, it should use nearly infinite gas,
|
||||||
|
// according to the CallMsg definition
|
||||||
|
gas := call.Gas
|
||||||
|
if gas == 0 {
|
||||||
|
gas = uint64(math.MaxUint64)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, _, err := c.evm.Call(from, c.addr, call.Data, gas, value)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -384,9 +385,17 @@ func ProcessTickets(usedAddress []common.Address, usedAmount []uint16, evm *vm.E
|
||||||
}
|
}
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
|
|
||||||
res, _, _ := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
|
res, _, err := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
|
|
||||||
evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("system call failed to execute", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) == 0 {
|
||||||
|
return make(map[common.Address]uint16)
|
||||||
|
}
|
||||||
|
|
||||||
arguments := abi.Arguments{
|
arguments := abi.Arguments{
|
||||||
{Type: addressType},
|
{Type: addressType},
|
||||||
|
|
|
||||||
|
|
@ -419,7 +419,10 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
|
||||||
p.head.Store(head)
|
p.head.Store(head)
|
||||||
p.state = state
|
p.state = state
|
||||||
|
|
||||||
p.tickets = p.chain.GetTicketBalance(head.Hash(), state)
|
p.tickets, err = p.chain.GetTicketBalance(head)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Create new slotter for pre-Osaka blob configuration.
|
// Create new slotter for pre-Osaka blob configuration.
|
||||||
slotter := newSlotter(params.BlobTxMaxBlobs)
|
slotter := newSlotter(params.BlobTxMaxBlobs)
|
||||||
|
|
@ -862,8 +865,11 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
|
||||||
p.head.Store(newHead)
|
p.head.Store(newHead)
|
||||||
p.state = statedb
|
p.state = statedb
|
||||||
|
|
||||||
p.tickets = p.chain.GetTicketBalance(newHead.Hash(), p.state)
|
p.tickets, err = p.chain.GetTicketBalance(newHead)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get ticket balances", "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
// Run the reorg between the old and new head and figure out which accounts
|
// Run the reorg between the old and new head and figure out which accounts
|
||||||
// need to be rechecked and which transactions need to be readded
|
// need to be rechecked and which transactions need to be readded
|
||||||
if reinject, inclusions := p.reorg(oldHead, newHead); reinject != nil {
|
if reinject, inclusions := p.reorg(oldHead, newHead); reinject != nil {
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,8 @@ func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
|
||||||
return bc.statedb, nil
|
return bc.statedb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *testBlockChain) GetTicketBalance(common.Hash, *state.StateDB) map[common.Address]uint16 {
|
func (bc *testBlockChain) GetTicketBalance(*types.Header) (map[common.Address]uint16, error) {
|
||||||
return bc.tickets
|
return bc.tickets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// reserver is a utility struct to sanity check that accounts are
|
// reserver is a utility struct to sanity check that accounts are
|
||||||
|
|
|
||||||
|
|
@ -42,5 +42,5 @@ type BlockChain interface {
|
||||||
// StateAt returns a state database for a given root hash (generally the head).
|
// StateAt returns a state database for a given root hash (generally the head).
|
||||||
StateAt(root common.Hash) (*state.StateDB, error)
|
StateAt(root common.Hash) (*state.StateDB, error)
|
||||||
|
|
||||||
GetTicketBalance(hash common.Hash, statedb *state.StateDB) map[common.Address]uint16
|
GetTicketBalance(header *types.Header) (map[common.Address]uint16, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1916,11 +1916,12 @@ func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
|
||||||
{addr3, key3},
|
{addr3, key3},
|
||||||
}
|
}
|
||||||
for _, signer := range signers {
|
for _, signer := range signers {
|
||||||
selector := crypto.Keccak256([]byte("requestTickets(address,uint16)"))[:4]
|
selector := crypto.Keccak256([]byte("RequestTickets(address,uint16,uint256)"))[:4]
|
||||||
uint16Type, _ := abi.NewType("uint16", "", nil)
|
uint16Type, _ := abi.NewType("uint16", "", nil)
|
||||||
addressType, _ := abi.NewType("address", "", nil)
|
addressType, _ := abi.NewType("address", "", nil)
|
||||||
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}}
|
uint256Type, _ := abi.NewType("uint256", "", nil)
|
||||||
data, _ := args.Pack(signer.addr, uint16(2))
|
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}, {Type: uint256Type}}
|
||||||
|
data, _ := args.Pack(signer.addr, uint16(2), big.NewInt(1))
|
||||||
data = append(selector, data...)
|
data = append(selector, data...)
|
||||||
|
|
||||||
txdata := &types.DynamicFeeTx{
|
txdata := &types.DynamicFeeTx{
|
||||||
|
|
@ -1931,12 +1932,12 @@ func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
|
||||||
GasFeeCap: big.NewInt(params.InitialBaseFee * 2),
|
GasFeeCap: big.NewInt(params.InitialBaseFee * 2),
|
||||||
GasTipCap: big.NewInt(params.GWei),
|
GasTipCap: big.NewInt(params.GWei),
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Value: big.NewInt(2),
|
||||||
}
|
}
|
||||||
tx := types.MustSignNewTx(signer.key, types.LatestSigner(&config), txdata)
|
tx := types.MustSignNewTx(signer.key, types.LatestSigner(&config), txdata)
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
n, ethServ := startEthService(t, gspec, ticketBlocks)
|
n, ethServ := startEthService(t, gspec, ticketBlocks)
|
||||||
|
|
||||||
// fill blob txs into the pool
|
// fill blob txs into the pool
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
|
|
@ -74,8 +73,8 @@ type testChain struct {
|
||||||
*core.BlockChain
|
*core.BlockChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testChain) GetTicketBalance(hash common.Hash, statedb *state.StateDB) map[common.Address]uint16 {
|
func (c *testChain) GetTicketBalance(header *types.Header) (map[common.Address]uint16, error) {
|
||||||
return map[common.Address]uint16{testAddr: 1000}
|
return map[common.Address]uint16{testAddr: 1000}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTestBackendWithGenerator creates a chain with a number of explicitly defined blocks and
|
// newTestBackendWithGenerator creates a chain with a number of explicitly defined blocks and
|
||||||
|
|
|
||||||
|
|
@ -100,11 +100,12 @@ func allocateTickets(t *testing.T, key *ecdsa.PrivateKey, sim *Backend, nonce ui
|
||||||
chainid, _ := client.ChainID(ctx)
|
chainid, _ := client.ChainID(ctx)
|
||||||
signer := types.LatestSignerForChainID(chainid)
|
signer := types.LatestSignerForChainID(chainid)
|
||||||
|
|
||||||
selector := crypto.Keccak256([]byte("requestTickets(address,uint16)"))[:4]
|
selector := crypto.Keccak256([]byte("RequestTickets(address,uint16,uint256)"))[:4]
|
||||||
uint16Type, _ := abi.NewType("uint16", "", nil)
|
uint16Type, _ := abi.NewType("uint16", "", nil)
|
||||||
addressType, _ := abi.NewType("address", "", nil)
|
addressType, _ := abi.NewType("address", "", nil)
|
||||||
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}}
|
uint256Type, _ := abi.NewType("uint256", "", nil)
|
||||||
data, _ := args.Pack(addr, amount)
|
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}, {Type: uint256Type}}
|
||||||
|
data, _ := args.Pack(addr, amount, big.NewInt(1))
|
||||||
data = append(selector, data...)
|
data = append(selector, data...)
|
||||||
|
|
||||||
// Get current head
|
// Get current head
|
||||||
|
|
@ -118,6 +119,7 @@ func allocateTickets(t *testing.T, key *ecdsa.PrivateKey, sim *Backend, nonce ui
|
||||||
GasFeeCap: new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei)),
|
GasFeeCap: new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei)),
|
||||||
GasTipCap: big.NewInt(params.GWei),
|
GasTipCap: big.NewInt(params.GWei),
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Value: big.NewInt(int64(amount)),
|
||||||
}
|
}
|
||||||
tx := types.MustSignNewTx(key, signer, txdata)
|
tx := types.MustSignNewTx(key, signer, txdata)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,8 +169,8 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
|
||||||
if err := core.ProcessConsolidationQueue(&requests, work.evm); err != nil {
|
if err := core.ProcessConsolidationQueue(&requests, work.evm); err != nil {
|
||||||
return &newPayloadResult{err: err}
|
return &newPayloadResult{err: err}
|
||||||
}
|
}
|
||||||
|
core.ProcessTickets(work.usedAddress, work.usedAmount, work.evm)
|
||||||
}
|
}
|
||||||
core.ProcessTickets(work.usedAddress, work.usedAmount, work.evm)
|
|
||||||
|
|
||||||
if requests != nil {
|
if requests != nil {
|
||||||
reqHash := types.CalcRequestsHash(requests)
|
reqHash := types.CalcRequestsHash(requests)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue