add auction and abi binding

This commit is contained in:
healthykim 2026-02-03 01:29:22 +09:00
parent 3cac28491c
commit e3fd4af127
15 changed files with 881 additions and 108 deletions

603
core/TicketAllocator.go Normal file
View 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)
}

View file

@ -6,67 +6,168 @@ contract TicketAllocator {
error NotEnoughTickets();
error NotSystemContract();
error InvalidPayment();
struct Ticket {
uint16 amount;
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 => uint256) public head;
mapping(address => uint16) public balance;
mapping(address => uint256) public withdrawable; // amount available for withdrawal
address[] public senders; // list of senders with >0 balance
uint16 public constant TOTAL_TICKETS = 21;
uint16 public constant TIMEOUT = 2;
uint256 private leftTickets;
uint256 private lastRequestBlock;
function requestTickets(address sender, uint16 numTickets) external {
uint256 currentBlock = block.number;
PendingBid[] public pendingBids;
uint256 public pendingBlock;
if (currentBlock != lastRequestBlock) {
leftTickets = TOTAL_TICKETS;
lastRequestBlock = currentBlock;
function GetBalance() public view returns (address[] memory, uint16[] memory){
uint16[] memory res;
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) {
revert NotEnoughTickets();
// Reset pending bids if we moved to a new block
if (block.number != pendingBlock) {
delete pendingBids;
pendingBlock = block.number;
}
if (balance[sender] == 0) {
senders.push(sender);
}
queue[sender].push(Ticket({
pendingBids.push(PendingBid({
sender: sender,
requestor: msg.sender,
amount: numTickets,
blockNumber: currentBlock
bidPerTicket: bidPerTicket
}));
balance[sender] += numTickets;
leftTickets -= numTickets;
}
function checkBalance(address sender) public view returns(uint) {
return balance[sender];
function withdraw() external {
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:
// 1. remove expired and used tickets
// - for used tickets, the oldest ticket is removed first
// 3. return the overall sender balances
// 1. allocate tickets for this block based on bids
// 2. process used and expired tickets, refunding bids for used tickets
// 3. return modified addresses and their balances
fallback(bytes calldata input) external returns (bytes memory) {
if (msg.sender != SYSTEM_ADDRESS) revert NotSystemContract();
address[] memory usedSenders;
uint16[] memory usedAmounts;
if (input.length > 0) {
(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; ) {
address sender = senders[s];
Ticket[] storage senderQueue = queue[sender];
@ -89,23 +190,29 @@ contract TicketAllocator {
continue;
}
// Expired tickets: burn the funds paid for these tickets
if (ticket.blockNumber + TIMEOUT < block.number) {
// remove expired tickets (comsume used tickets if possible)
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;
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) {
// 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;
ticket.amount -= uint16(deduct);
ticket.amount -= deduct;
balance[sender] -= 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++;
} else {
@ -124,15 +231,13 @@ contract TicketAllocator {
s++;
}
// return the active senders and their balances
address[] memory activeSenders = new address[](senders.length);
uint16[] memory activeBalances = new uint16[](senders.length);
for (uint256 i = 0; i < senders.length; i++) {
activeSenders[i] = senders[i];
activeBalances[i] = balance[senders[i]];
// Step 3: return modified addresses and their balances
address[] memory modifiedAddress = new address[](modifiedCount);
uint16[] memory modifiedTickets = new uint16[](modifiedCount);
for (uint256 i = 0; i < modifiedCount; i++) {
modifiedAddress[i] = modified[i];
modifiedTickets[i] = balance[modified[i]];
}
return abi.encode(activeSenders, activeBalances);
return abi.encode(modifiedAddress, modifiedTickets);
}
}

View file

@ -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
bc.tickets[block.Hash()] = res.Tickets
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 {
if parent, ok := bc.tickets[block.ParentHash()]; ok {
delete(bc.tickets, block.ParentHash())
if hashes := bc.ticketBlocks[block.Number().Sub(block.Number(), big.NewInt(1))]; len(hashes) != 0 {
for i, hash := range hashes {
if hash.Cmp(block.ParentHash()) == 0 {
hashes[i] = hashes[len(hashes)-1]
hashes = hashes[:len(hashes)-1]
}
bc.tickets[block.Hash()] = parent
for addr, value := range res.Tickets {
if value == 0 {
delete(bc.tickets[block.Hash()], addr)
}
bc.tickets[block.Hash()][addr] = value
}
} else {
res, _ := bc.GetTicketBalance(block.Header())
bc.tickets[block.Hash()] = res
}
// Report the collected witness statistics

View file

@ -21,6 +21,7 @@ import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"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/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@ -354,33 +354,43 @@ func (bc *BlockChain) GetCanonicalTransaction(hash common.Hash) (*rawdb.LegacyTx
return lookup, tx
}
func (bc *BlockChain) GetTicketBalance(hash common.Hash, statedb *state.StateDB) map[common.Address]uint16 {
if bc.tickets[hash] != nil {
return bc.tickets[hash]
func (bc *BlockChain) GetTicketBalance(header *types.Header) (map[common.Address]uint16, error) {
if bc.tickets[header.Hash()] != nil {
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)
senders := statedb.GetState(params.BlobTicketAllocationAddress, common.BigToHash(params.BlobTicketSenderSlot)).Big().Int64()
base := crypto.Keccak256Hash(common.LeftPadBytes(params.BlobTicketSenderSlot.Bytes(), 32)).Big()
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)
for i, sender := range senders {
result[sender] = uint16(balances[i])
}
bc.tickets[header.Hash()] = result
return result
return result, nil
}
// TxIndexDone returns true if the transaction indexer has finished indexing.

View file

@ -4211,11 +4211,12 @@ func TestBlobTickets(t *testing.T) {
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, bg *BlockGen) {
switch i {
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)
addressType, _ := abi.NewType("address", "", nil)
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}}
data, _ := args.Pack(addr1, ticketAmount)
uint256Type, _ := abi.NewType("uint256", "", nil)
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}, {Type: uint256Type}}
data, _ := args.Pack(addr1, ticketAmount, big.NewInt(1))
data = append(selector, data...)
@ -4227,6 +4228,7 @@ func TestBlobTickets(t *testing.T) {
GasFeeCap: big.NewInt(875000000),
GasTipCap: big.NewInt(1),
Data: data,
Value: big.NewInt(int64(ticketAmount)),
}
tx := types.MustSignNewTx(key1, signer, txdata)
@ -4297,15 +4299,13 @@ func TestBlobTickets(t *testing.T) {
}
// previous block ticket balance
state, _ := chain.StateAt(blocks[0].Root())
balance = chain.GetTicketBalance(blocks[0].Hash(), state)
balance, _ = chain.GetTicketBalance(blocks[0].Header())
amount = balance[addr1]
if amount != ticketAmount {
t.Fatalf("wrong ticket amount: expected %d, got %d", ticketAmount, amount)
}
state, _ = chain.StateAt(blocks[1].Root())
balance = chain.GetTicketBalance(blocks[1].Hash(), state)
balance, _ = chain.GetTicketBalance(blocks[1].Header())
amount = balance[addr1]
if amount != ticketAmount-1 {
t.Fatalf("wrong ticket amount: expected %d, got %d", ticketAmount-1, amount)

45
core/contract_caller.go Normal file
View 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
}

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
@ -384,9 +385,17 @@ func ProcessTickets(usedAddress []common.Address, usedAmount []uint16, evm *vm.E
}
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)
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{
{Type: addressType},

View file

@ -419,7 +419,10 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
p.head.Store(head)
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.
slotter := newSlotter(params.BlobTxMaxBlobs)
@ -862,8 +865,11 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
p.head.Store(newHead)
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
// need to be rechecked and which transactions need to be readded
if reinject, inclusions := p.reorg(oldHead, newHead); reinject != nil {

View file

@ -186,8 +186,8 @@ func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
return bc.statedb, nil
}
func (bc *testBlockChain) GetTicketBalance(common.Hash, *state.StateDB) map[common.Address]uint16 {
return bc.tickets
func (bc *testBlockChain) GetTicketBalance(*types.Header) (map[common.Address]uint16, error) {
return bc.tickets, nil
}
// reserver is a utility struct to sanity check that accounts are

View file

@ -42,5 +42,5 @@ type BlockChain interface {
// StateAt returns a state database for a given root hash (generally the head).
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)
}

View file

@ -1916,11 +1916,12 @@ func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
{addr3, key3},
}
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)
addressType, _ := abi.NewType("address", "", nil)
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}}
data, _ := args.Pack(signer.addr, uint16(2))
uint256Type, _ := abi.NewType("uint256", "", nil)
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}, {Type: uint256Type}}
data, _ := args.Pack(signer.addr, uint16(2), big.NewInt(1))
data = append(selector, data...)
txdata := &types.DynamicFeeTx{
@ -1931,12 +1932,12 @@ func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
GasFeeCap: big.NewInt(params.InitialBaseFee * 2),
GasTipCap: big.NewInt(params.GWei),
Data: data,
Value: big.NewInt(2),
}
tx := types.MustSignNewTx(signer.key, types.LatestSigner(&config), txdata)
b.AddTx(tx)
}
})
n, ethServ := startEthService(t, gspec, ticketBlocks)
// fill blob txs into the pool

View file

@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"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/blobpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
@ -74,8 +73,8 @@ type testChain struct {
*core.BlockChain
}
func (c *testChain) GetTicketBalance(hash common.Hash, statedb *state.StateDB) map[common.Address]uint16 {
return map[common.Address]uint16{testAddr: 1000}
func (c *testChain) GetTicketBalance(header *types.Header) (map[common.Address]uint16, error) {
return map[common.Address]uint16{testAddr: 1000}, nil
}
// newTestBackendWithGenerator creates a chain with a number of explicitly defined blocks and

View file

@ -100,11 +100,12 @@ func allocateTickets(t *testing.T, key *ecdsa.PrivateKey, sim *Backend, nonce ui
chainid, _ := client.ChainID(ctx)
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)
addressType, _ := abi.NewType("address", "", nil)
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}}
data, _ := args.Pack(addr, amount)
uint256Type, _ := abi.NewType("uint256", "", nil)
args := abi.Arguments{{Type: addressType}, {Type: uint16Type}, {Type: uint256Type}}
data, _ := args.Pack(addr, amount, big.NewInt(1))
data = append(selector, data...)
// 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)),
GasTipCap: big.NewInt(params.GWei),
Data: data,
Value: big.NewInt(int64(amount)),
}
tx := types.MustSignNewTx(key, signer, txdata)

View file

@ -169,8 +169,8 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
if err := core.ProcessConsolidationQueue(&requests, work.evm); err != nil {
return &newPayloadResult{err: err}
}
core.ProcessTickets(work.usedAddress, work.usedAmount, work.evm)
}
core.ProcessTickets(work.usedAddress, work.usedAmount, work.evm)
if requests != nil {
reqHash := types.CalcRequestsHash(requests)

File diff suppressed because one or more lines are too long