From 18fbd2a814a001f48d9b7a5f7d4ac19e9218de08 Mon Sep 17 00:00:00 2001 From: MiniFrenchBread <103425574+MiniFrenchBread@users.noreply.github.com> Date: Wed, 2 Apr 2025 17:30:59 +0800 Subject: [PATCH] feat: wrapped a0gi base precompile --- core/tracing/hooks.go | 3 + core/vm/dasigners.go | 18 +- .../precompiles/wrapped_a0gi_base/contract.go | 291 ++++++++++++++++++ .../precompiles/wrapped_a0gi_base/errors.go | 9 + .../vm/precompiles/wrapped_a0gi_base/types.go | 14 + core/vm/wrapped_a0gi_base.go | 237 ++++++++++++++ 6 files changed, 563 insertions(+), 9 deletions(-) create mode 100644 core/vm/precompiles/wrapped_a0gi_base/contract.go create mode 100644 core/vm/precompiles/wrapped_a0gi_base/errors.go create mode 100644 core/vm/precompiles/wrapped_a0gi_base/types.go create mode 100644 core/vm/wrapped_a0gi_base.go diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index 0485f7a3eb..c55aea4b7a 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -270,6 +270,9 @@ const ( // BalanceChangeRevert is emitted when the balance is reverted back to a previous value due to call failure. // It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal). BalanceChangeRevert BalanceChangeReason = 15 + + // BalanceIncreaseWA0GIMint is emitted when mint happened in wrapped a0gi base precompile + BalanceIncreaseWA0GIMint BalanceChangeReason = 16 ) // GasChangeReason is used to indicate the reason for a gas change, useful diff --git a/core/vm/dasigners.go b/core/vm/dasigners.go index 8fb8712a59..8423c4def0 100644 --- a/core/vm/dasigners.go +++ b/core/vm/dasigners.go @@ -18,7 +18,7 @@ import ( ) const ( - requiredGasMax uint64 = 1000_000_000 + DASignersRequiredGasMax uint64 = 1000_000_000 DASignersFunctionParams = "params" DASignersFunctionEpochNumber = "epochNumber" @@ -35,7 +35,7 @@ const ( DASignersFunctionMakeEpoch = "makeEpoch" ) -var RequiredGasBasic = map[string]uint64{ +var DASignersRequiredGasBasic = map[string]uint64{ DASignersFunctionParams: 1_000, DASignersFunctionEpochNumber: 1_000, DASignersFunctionQuorumCount: 1_000, @@ -52,8 +52,8 @@ var RequiredGasBasic = map[string]uint64{ } const ( - NewSignerEvent = "NewSigner" - SocketUpdatedEvent = "SocketUpdated" + DASignersNewSignerEvent = "NewSigner" + DASignersSocketUpdatedEvent = "SocketUpdated" ) var _ StatefulPrecompiledContract = &DASignersPrecompile{} @@ -81,12 +81,12 @@ func (d *DASignersPrecompile) Address() common.Address { func (d *DASignersPrecompile) RequiredGas(input []byte) uint64 { method, err := d.abi.MethodById(input[:4]) if err != nil { - return requiredGasMax + return DASignersRequiredGasMax } - if gas, ok := RequiredGasBasic[method.Name]; ok { + if gas, ok := DASignersRequiredGasBasic[method.Name]; ok { return gas } - return requiredGasMax + return DASignersRequiredGasMax } func (d *DASignersPrecompile) IsTx(method string) bool { @@ -151,7 +151,7 @@ func (d *DASignersPrecompile) Run(evm *EVM, contract *Contract, readonly bool) ( } func (d *DASignersPrecompile) EmitNewSignerEvent(evm *EVM, signer dasigners.IDASignersSignerDetail) error { - event := d.abi.Events[NewSignerEvent] + event := d.abi.Events[DASignersNewSignerEvent] quries := make([]interface{}, 2) quries[0] = event.ID quries[1] = signer.Signer @@ -174,7 +174,7 @@ func (d *DASignersPrecompile) EmitNewSignerEvent(evm *EVM, signer dasigners.IDAS } func (d *DASignersPrecompile) EmitSocketUpdatedEvent(evm *EVM, signer common.Address, socket string) error { - event := d.abi.Events[SocketUpdatedEvent] + event := d.abi.Events[DASignersSocketUpdatedEvent] quries := make([]interface{}, 2) quries[0] = event.ID quries[1] = signer diff --git a/core/vm/precompiles/wrapped_a0gi_base/contract.go b/core/vm/precompiles/wrapped_a0gi_base/contract.go new file mode 100644 index 0000000000..176842bd3d --- /dev/null +++ b/core/vm/precompiles/wrapped_a0gi_base/contract.go @@ -0,0 +1,291 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package wrappeda0gibase + +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 +) + +// Supply is an auto generated low-level Go binding around an user-defined struct. +type Supply struct { + Cap *big.Int + InitialSupply *big.Int + Supply *big.Int +} + +// Wrappeda0gibaseMetaData contains all meta data concerning the Wrappeda0gibase contract. +var Wrappeda0gibaseMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWA0GI\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"minterSupply\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"cap\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"internalType\":\"structSupply\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// Wrappeda0gibaseABI is the input ABI used to generate the binding from. +// Deprecated: Use Wrappeda0gibaseMetaData.ABI instead. +var Wrappeda0gibaseABI = Wrappeda0gibaseMetaData.ABI + +// Wrappeda0gibase is an auto generated Go binding around an Ethereum contract. +type Wrappeda0gibase struct { + Wrappeda0gibaseCaller // Read-only binding to the contract + Wrappeda0gibaseTransactor // Write-only binding to the contract + Wrappeda0gibaseFilterer // Log filterer for contract events +} + +// Wrappeda0gibaseCaller is an auto generated read-only Go binding around an Ethereum contract. +type Wrappeda0gibaseCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Wrappeda0gibaseTransactor is an auto generated write-only Go binding around an Ethereum contract. +type Wrappeda0gibaseTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Wrappeda0gibaseFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Wrappeda0gibaseFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Wrappeda0gibaseSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Wrappeda0gibaseSession struct { + Contract *Wrappeda0gibase // 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 +} + +// Wrappeda0gibaseCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Wrappeda0gibaseCallerSession struct { + Contract *Wrappeda0gibaseCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Wrappeda0gibaseTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Wrappeda0gibaseTransactorSession struct { + Contract *Wrappeda0gibaseTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Wrappeda0gibaseRaw is an auto generated low-level Go binding around an Ethereum contract. +type Wrappeda0gibaseRaw struct { + Contract *Wrappeda0gibase // Generic contract binding to access the raw methods on +} + +// Wrappeda0gibaseCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Wrappeda0gibaseCallerRaw struct { + Contract *Wrappeda0gibaseCaller // Generic read-only contract binding to access the raw methods on +} + +// Wrappeda0gibaseTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Wrappeda0gibaseTransactorRaw struct { + Contract *Wrappeda0gibaseTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewWrappeda0gibase creates a new instance of Wrappeda0gibase, bound to a specific deployed contract. +func NewWrappeda0gibase(address common.Address, backend bind.ContractBackend) (*Wrappeda0gibase, error) { + contract, err := bindWrappeda0gibase(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Wrappeda0gibase{Wrappeda0gibaseCaller: Wrappeda0gibaseCaller{contract: contract}, Wrappeda0gibaseTransactor: Wrappeda0gibaseTransactor{contract: contract}, Wrappeda0gibaseFilterer: Wrappeda0gibaseFilterer{contract: contract}}, nil +} + +// NewWrappeda0gibaseCaller creates a new read-only instance of Wrappeda0gibase, bound to a specific deployed contract. +func NewWrappeda0gibaseCaller(address common.Address, caller bind.ContractCaller) (*Wrappeda0gibaseCaller, error) { + contract, err := bindWrappeda0gibase(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Wrappeda0gibaseCaller{contract: contract}, nil +} + +// NewWrappeda0gibaseTransactor creates a new write-only instance of Wrappeda0gibase, bound to a specific deployed contract. +func NewWrappeda0gibaseTransactor(address common.Address, transactor bind.ContractTransactor) (*Wrappeda0gibaseTransactor, error) { + contract, err := bindWrappeda0gibase(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Wrappeda0gibaseTransactor{contract: contract}, nil +} + +// NewWrappeda0gibaseFilterer creates a new log filterer instance of Wrappeda0gibase, bound to a specific deployed contract. +func NewWrappeda0gibaseFilterer(address common.Address, filterer bind.ContractFilterer) (*Wrappeda0gibaseFilterer, error) { + contract, err := bindWrappeda0gibase(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Wrappeda0gibaseFilterer{contract: contract}, nil +} + +// bindWrappeda0gibase binds a generic wrapper to an already deployed contract. +func bindWrappeda0gibase(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(Wrappeda0gibaseABI)) + 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 (_Wrappeda0gibase *Wrappeda0gibaseRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Wrappeda0gibase.Contract.Wrappeda0gibaseCaller.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 (_Wrappeda0gibase *Wrappeda0gibaseRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.Wrappeda0gibaseTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Wrappeda0gibase *Wrappeda0gibaseRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.Wrappeda0gibaseTransactor.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 (_Wrappeda0gibase *Wrappeda0gibaseCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Wrappeda0gibase.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 (_Wrappeda0gibase *Wrappeda0gibaseTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Wrappeda0gibase *Wrappeda0gibaseTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.contract.Transact(opts, method, params...) +} + +// GetWA0GI is a free data retrieval call binding the contract method 0xa9283a7a. +// +// Solidity: function getWA0GI() view returns(address) +func (_Wrappeda0gibase *Wrappeda0gibaseCaller) GetWA0GI(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Wrappeda0gibase.contract.Call(opts, &out, "getWA0GI") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetWA0GI is a free data retrieval call binding the contract method 0xa9283a7a. +// +// Solidity: function getWA0GI() view returns(address) +func (_Wrappeda0gibase *Wrappeda0gibaseSession) GetWA0GI() (common.Address, error) { + return _Wrappeda0gibase.Contract.GetWA0GI(&_Wrappeda0gibase.CallOpts) +} + +// GetWA0GI is a free data retrieval call binding the contract method 0xa9283a7a. +// +// Solidity: function getWA0GI() view returns(address) +func (_Wrappeda0gibase *Wrappeda0gibaseCallerSession) GetWA0GI() (common.Address, error) { + return _Wrappeda0gibase.Contract.GetWA0GI(&_Wrappeda0gibase.CallOpts) +} + +// MinterSupply is a free data retrieval call binding the contract method 0x95609212. +// +// Solidity: function minterSupply(address minter) view returns((uint256,uint256,uint256)) +func (_Wrappeda0gibase *Wrappeda0gibaseCaller) MinterSupply(opts *bind.CallOpts, minter common.Address) (Supply, error) { + var out []interface{} + err := _Wrappeda0gibase.contract.Call(opts, &out, "minterSupply", minter) + + if err != nil { + return *new(Supply), err + } + + out0 := *abi.ConvertType(out[0], new(Supply)).(*Supply) + + return out0, err + +} + +// MinterSupply is a free data retrieval call binding the contract method 0x95609212. +// +// Solidity: function minterSupply(address minter) view returns((uint256,uint256,uint256)) +func (_Wrappeda0gibase *Wrappeda0gibaseSession) MinterSupply(minter common.Address) (Supply, error) { + return _Wrappeda0gibase.Contract.MinterSupply(&_Wrappeda0gibase.CallOpts, minter) +} + +// MinterSupply is a free data retrieval call binding the contract method 0x95609212. +// +// Solidity: function minterSupply(address minter) view returns((uint256,uint256,uint256)) +func (_Wrappeda0gibase *Wrappeda0gibaseCallerSession) MinterSupply(minter common.Address) (Supply, error) { + return _Wrappeda0gibase.Contract.MinterSupply(&_Wrappeda0gibase.CallOpts, minter) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address minter, uint256 amount) returns() +func (_Wrappeda0gibase *Wrappeda0gibaseTransactor) Burn(opts *bind.TransactOpts, minter common.Address, amount *big.Int) (*types.Transaction, error) { + return _Wrappeda0gibase.contract.Transact(opts, "burn", minter, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address minter, uint256 amount) returns() +func (_Wrappeda0gibase *Wrappeda0gibaseSession) Burn(minter common.Address, amount *big.Int) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.Burn(&_Wrappeda0gibase.TransactOpts, minter, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. +// +// Solidity: function burn(address minter, uint256 amount) returns() +func (_Wrappeda0gibase *Wrappeda0gibaseTransactorSession) Burn(minter common.Address, amount *big.Int) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.Burn(&_Wrappeda0gibase.TransactOpts, minter, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address minter, uint256 amount) returns() +func (_Wrappeda0gibase *Wrappeda0gibaseTransactor) Mint(opts *bind.TransactOpts, minter common.Address, amount *big.Int) (*types.Transaction, error) { + return _Wrappeda0gibase.contract.Transact(opts, "mint", minter, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address minter, uint256 amount) returns() +func (_Wrappeda0gibase *Wrappeda0gibaseSession) Mint(minter common.Address, amount *big.Int) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.Mint(&_Wrappeda0gibase.TransactOpts, minter, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address minter, uint256 amount) returns() +func (_Wrappeda0gibase *Wrappeda0gibaseTransactorSession) Mint(minter common.Address, amount *big.Int) (*types.Transaction, error) { + return _Wrappeda0gibase.Contract.Mint(&_Wrappeda0gibase.TransactOpts, minter, amount) +} diff --git a/core/vm/precompiles/wrapped_a0gi_base/errors.go b/core/vm/precompiles/wrapped_a0gi_base/errors.go new file mode 100644 index 0000000000..833d92e157 --- /dev/null +++ b/core/vm/precompiles/wrapped_a0gi_base/errors.go @@ -0,0 +1,9 @@ +package wrappeda0gibase + +import "errors" + +var ( + ErrSenderNotWA0GI = errors.New("sender is not WA0GI") + ErrInsufficientMintCap = errors.New("insufficient mint cap") + ErrInsufficientMintSupply = errors.New("insufficient mint supply") +) diff --git a/core/vm/precompiles/wrapped_a0gi_base/types.go b/core/vm/precompiles/wrapped_a0gi_base/types.go new file mode 100644 index 0000000000..f49a84696f --- /dev/null +++ b/core/vm/precompiles/wrapped_a0gi_base/types.go @@ -0,0 +1,14 @@ +package wrappeda0gibase + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +var ( + supplyKey = []byte{0x00} +) + +func SupplyKey(account common.Address) common.Hash { + return crypto.Keccak256Hash(append(supplyKey, account.Bytes()...)) +} diff --git a/core/vm/wrapped_a0gi_base.go b/core/vm/wrapped_a0gi_base.go new file mode 100644 index 0000000000..ed4f124617 --- /dev/null +++ b/core/vm/wrapped_a0gi_base.go @@ -0,0 +1,237 @@ +package vm + +import ( + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + wrappeda0gibase "github.com/ethereum/go-ethereum/core/vm/precompiles/wrapped_a0gi_base" + "github.com/holiman/uint256" + "github.com/vmihailenco/msgpack/v5" +) + +const ( + WrappedA0GIBaseRequiredGasMax uint64 = 1000_000_000 + + // txs + WrappedA0GIBaseFunctionMint = "mint" + WrappedA0GIBaseFunctionBurn = "burn" + // queries + WrappedA0GIBaseFunctionGetWA0GI = "getWA0GI" + WrappedA0GIBaseFunctionMinterSupply = "minterSupply" +) + +var WrappedA0GIBaseRequiredGasBasic = map[string]uint64{ + WrappedA0GIBaseFunctionMint: 100_000, + WrappedA0GIBaseFunctionBurn: 100_000, + WrappedA0GIBaseFunctionGetWA0GI: 5_000, + WrappedA0GIBaseFunctionMinterSupply: 10_000, +} + +var _ StatefulPrecompiledContract = &WrappedA0giBasePrecompile{} + +type WrappedA0giBasePrecompile struct { + abi abi.ABI +} + +// Abi implements common.PrecompileCommon. +func (w *WrappedA0giBasePrecompile) Abi() *abi.ABI { + return &w.abi +} + +// IsTx implements common.PrecompileCommon. +func (w *WrappedA0giBasePrecompile) IsTx(method string) bool { + switch method { + case WrappedA0GIBaseFunctionMint, + WrappedA0GIBaseFunctionBurn: + return true + default: + return false + } +} + +func (w *WrappedA0giBasePrecompile) Address() common.Address { + return common.HexToAddress("0x0000000000000000000000000000000000001002") +} + +// RequiredGas implements vm.PrecompiledContract. +func (w *WrappedA0giBasePrecompile) RequiredGas(input []byte) uint64 { + method, err := w.abi.MethodById(input[:4]) + if err != nil { + return WrappedA0GIBaseRequiredGasMax + } + if gas, ok := WrappedA0GIBaseRequiredGasBasic[method.Name]; ok { + return gas + } + return WrappedA0GIBaseRequiredGasMax +} + +func NewWrappedA0giBasePrecompile() (*WrappedA0giBasePrecompile, error) { + abi, err := abi.JSON(strings.NewReader(wrappeda0gibase.Wrappeda0gibaseABI)) + if err != nil { + return nil, err + } + return &WrappedA0giBasePrecompile{ + abi: abi, + }, nil +} + +// Run implements vm.PrecompiledContract. +func (w *WrappedA0giBasePrecompile) Run(evm *EVM, contract *Contract, readonly bool) ([]byte, error) { + method, args, err := InitializeStatefulPrecompileCall(w, evm, contract, readonly) + if err != nil { + return nil, err + } + + var bz []byte + switch method.Name { + // queries + case WrappedA0GIBaseFunctionGetWA0GI: + bz, err = w.GetWA0GI(evm, method, args) + case WrappedA0GIBaseFunctionMinterSupply: + bz, err = w.MinterSupply(evm, method, args) + // txs + case WrappedA0GIBaseFunctionMint: + bz, err = w.Mint(evm, contract, method, args) + case WrappedA0GIBaseFunctionBurn: + bz, err = w.Burn(evm, contract, method, args) + } + + if err != nil { + return nil, err + } + + return bz, nil +} + +func (w *WrappedA0giBasePrecompile) getWA0GI() common.Address { + // This is a Wrapped A0GI contract deployed by a raw transaction: + // raw tx params: + // from: 0x873cd27b6833e6394c34a00c37b260aca5abc0b6 + // nonce: 0 + // gasPrice: 100 Gwei + // gasLimit: 1000000 + // The sender is an ephemeral account, nobody holds its private key and this is the only transaction it signed. + // This transaction is a legacy transaction without chain ID so it can be deployed at any EVM chain which supports pre-EIP155 transactions. + // raw tx: 0xf90f568085174876e800830f42408080b90f0360c0604052600c60809081526b57726170706564204130474960a01b60a0526000906200002d908262000128565b50604080518082019091526005815264574130474960d81b602082015260019062000059908262000128565b50600280546001600160a81b031916621002121790553480156200007c57600080fd5b50620001f4565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000ae57607f821691505b602082108103620000cf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200012357600081815260208120601f850160051c81016020861015620000fe5750805b601f850160051c820191505b818110156200011f578281556001016200010a565b5050505b505050565b81516001600160401b0381111562000144576200014462000083565b6200015c8162000155845462000099565b84620000d5565b602080601f8311600181146200019457600084156200017b5750858301515b600019600386901b1c1916600185901b1785556200011f565b600085815260208120601f198616915b82811015620001c557888601518255948401946001909101908401620001a4565b5085821015620001e45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610cff80620002046000396000f3fe6080604052600436106100f75760003560e01c806370a082311161008a578063a9059cbb11610059578063a9059cbb14610291578063c8dd1a26146102b1578063d0e30db0146102ee578063dd62ed3e146102f657600080fd5b806370a082311461022f57806379cc67901461025c57806395d89b411461027c5780639dc29fac1461025c57600080fd5b80632e1a7d4d116100c65780632e1a7d4d146101a3578063313ce567146101c357806340c10f19146101ef57806342966c681461020f57600080fd5b806306fdde031461010b578063095ea7b31461013657806318160ddd1461016657806323b872dd1461018357600080fd5b366101065761010461032e565b005b600080fd5b34801561011757600080fd5b50610120610389565b60405161012d9190610b1b565b60405180910390f35b34801561014257600080fd5b50610156610151366004610b6a565b610417565b604051901515815260200161012d565b34801561017257600080fd5b50475b60405190815260200161012d565b34801561018f57600080fd5b5061015661019e366004610b94565b610484565b3480156101af57600080fd5b506101046101be366004610bd0565b61068c565b3480156101cf57600080fd5b506002546101dd9060ff1681565b60405160ff909116815260200161012d565b3480156101fb57600080fd5b5061010461020a366004610b6a565b610716565b34801561021b57600080fd5b5061010461022a366004610bd0565b610879565b34801561023b57600080fd5b5061017561024a366004610be9565b60036020526000908152604090205481565b34801561026857600080fd5b50610104610277366004610b6a565b610886565b34801561028857600080fd5b50610120610894565b34801561029d57600080fd5b506101566102ac366004610b6a565b6108a1565b3480156102bd57600080fd5b506002546102d69061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161012d565b61010461032e565b34801561030257600080fd5b50610175610311366004610c04565b600460209081526000928352604080842090915290825290205481565b336000908152600360205260408120805434929061034d908490610c4d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b6000805461039690610c60565b80601f01602080910402602001604051908101604052809291908181526020018280546103c290610c60565b801561040f5780601f106103e45761010080835404028352916020019161040f565b820191906000526020600020905b8154815290600101906020018083116103f257829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906104729086815260200190565b60405180910390a35060015b92915050565b6001600160a01b0383166000908152600360205260408120548211156104f15760405162461bcd60e51b815260206004820152601860248201527f73726320696e73756666696369656e742062616c616e6365000000000000000060448201526064015b60405180910390fd5b6001600160a01b038416331480159061052f57506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b156105d9576001600160a01b03841660009081526004602090815260408083203384529091529020548211156105a05760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b60448201526064016104e8565b6001600160a01b0384166000908152600460209081526040808320338452909152812080548492906105d3908490610c9a565b90915550505b6001600160a01b03841660009081526003602052604081208054849290610601908490610c9a565b90915550506001600160a01b0383166000908152600360205260408120805484929061062e908490610c4d565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161067a91815260200190565b60405180910390a35060019392505050565b33600090815260036020526040812080548392906106ab908490610c9a565b9091555050604051339082156108fc029083906000818181858888f193505050501580156106dd573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b6002546040513360248201526044810183905260009161010090046001600160a01b03169060640160408051601f198184030181529181526020820180516001600160e01b03166340c10f1960e01b179052516107739190610cad565b6000604051808303816000865af19150503d80600081146107b0576040519150601f19603f3d011682016040523d82523d6000602084013e6107b5565b606091505b50509050806108065760405162461bcd60e51b815260206004820152601d60248201527f7772617070656420613067692062617365206d696e74206661696c656400000060448201526064016104e8565b6001600160a01b0383166000908152600360205260408120805484929061082e908490610c4d565b90915550506040518281526001600160a01b0384169033907fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8906020015b60405180910390a3505050565b61088333826108b5565b50565b61089082826108b5565b5050565b6001805461039690610c60565b60006108ae338484610484565b9392505050565b6002546040513360248201526044810183905260009161010090046001600160a01b03169060640160408051601f198184030181529181526020820180516001600160e01b0316632770a7eb60e21b179052516109129190610cad565b6000604051808303816000865af19150503d806000811461094f576040519150601f19603f3d011682016040523d82523d6000602084013e610954565b606091505b50509050806109a55760405162461bcd60e51b815260206004820152601d60248201527f7772617070656420613067692062617365206275726e206661696c656400000060448201526064016104e8565b6001600160a01b03831633148015906109e357506001600160a01b038316600090815260046020908152604080832033845290915290205460001914155b15610a8d576001600160a01b0383166000908152600460209081526040808320338452909152902054821115610a545760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b60448201526064016104e8565b6001600160a01b038316600090815260046020908152604080832033845290915281208054849290610a87908490610c9a565b90915550505b6001600160a01b03831660009081526003602052604081208054849290610ab5908490610c9a565b90915550506040518281526001600160a01b0384169033907fbac40739b0d4ca32fa2d82fc91630465ba3eddd1598da6fca393b26fb63b94539060200161086c565b60005b83811015610b12578181015183820152602001610afa565b50506000910152565b6020815260008251806020840152610b3a816040850160208701610af7565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114610b6557600080fd5b919050565b60008060408385031215610b7d57600080fd5b610b8683610b4e565b946020939093013593505050565b600080600060608486031215610ba957600080fd5b610bb284610b4e565b9250610bc060208501610b4e565b9150604084013590509250925092565b600060208284031215610be257600080fd5b5035919050565b600060208284031215610bfb57600080fd5b6108ae82610b4e565b60008060408385031215610c1757600080fd5b610c2083610b4e565b9150610c2e60208401610b4e565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561047e5761047e610c37565b600181811c90821680610c7457607f821691505b602082108103610c9457634e487b7160e01b600052602260045260246000fd5b50919050565b8181038181111561047e5761047e610c37565b60008251610cbf818460208701610af7565b919091019291505056fea2646970667358221220e46d4016267b105c34d4679646e09d6fb451927a4dd464e4ebe1563577af02a664736f6c634300081400331ba0fbd8c503ac7ff82ea302cdc5d6a7195281eaa99017a6a363e36fba073028ba42a037a49fedf5460e3d33776233d88dfb242ddaf9bb5d4cb6688aa290ead65a93c7 + return common.HexToAddress("0x1cd0690ff9a693f5ef2dd976660a8dafc81a109c") +} + +func (w *WrappedA0giBasePrecompile) GetWA0GI(_ *EVM, method *abi.Method, args []interface{}) ([]byte, error) { + if len(args) != 0 { + return nil, ErrExecutionReverted + } + + return method.Outputs.Pack(w.getWA0GI()) +} + +func (w *WrappedA0giBasePrecompile) setMinterSupply(evm *EVM, account common.Address, supply wrappeda0gibase.Supply) error { + b, err := msgpack.Marshal(supply) + if err != nil { + return err + } + StoreBytes(evm.StateDB, w.Address(), wrappeda0gibase.SupplyKey(account), b) + return nil +} + +func (w *WrappedA0giBasePrecompile) getMinterSupply(evm *EVM, account common.Address) (wrappeda0gibase.Supply, error) { + b := LoadBytes(evm.StateDB, w.Address(), wrappeda0gibase.SupplyKey(account)) + if len(b) == 0 { + return wrappeda0gibase.Supply{ + Cap: big.NewInt(0), + Supply: big.NewInt(0), + InitialSupply: big.NewInt(0), + }, nil + } + + var supply wrappeda0gibase.Supply + err := msgpack.Unmarshal(b, &supply) + if err != nil { + return wrappeda0gibase.Supply{}, err + } + return supply, nil +} + +func (w *WrappedA0giBasePrecompile) MinterSupply(evm *EVM, method *abi.Method, args []interface{}) ([]byte, error) { + if len(args) != 1 { + return nil, ErrExecutionReverted + } + account := args[0].(common.Address) + supply, err := w.getMinterSupply(evm, account) + if err != nil { + return nil, err + } + return method.Outputs.Pack(supply) +} + +func (w *WrappedA0giBasePrecompile) Mint( + evm *EVM, + contract *Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + if len(args) != 2 { + return nil, ErrExecutionReverted + } + minter := args[0].(common.Address) + amount := args[1].(*big.Int) + // validation + wa0gi := w.getWA0GI() + if contract.caller != wa0gi { + return nil, wrappeda0gibase.ErrSenderNotWA0GI + } + // execute + supply, err := w.getMinterSupply(evm, minter) + if err != nil { + return nil, err + } + // check & update mint supply + supply.Supply.Add(supply.Supply, amount) + if supply.Supply.Cmp(supply.Cap) > 0 { + return nil, wrappeda0gibase.ErrInsufficientMintCap + } + // mint & transfer to wa0gi contract address + evm.StateDB.AddBalance(wa0gi, uint256.MustFromBig(amount), tracing.BalanceIncreaseWA0GIMint) + // update supply + if err = w.setMinterSupply(evm, minter, supply); err != nil { + return nil, err + } + return method.Outputs.Pack() +} + +func (w *WrappedA0giBasePrecompile) Burn( + evm *EVM, + contract *Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + if len(args) != 2 { + return nil, ErrExecutionReverted + } + minter := args[0].(common.Address) + amount := args[1].(*big.Int) + // validation + wa0gi := w.getWA0GI() + if contract.caller != wa0gi { + return nil, wrappeda0gibase.ErrSenderNotWA0GI + } + // execute + supply, err := w.getMinterSupply(evm, minter) + if err != nil { + return nil, err + } + // check & update mint supply + supply.Supply.Sub(supply.Supply, amount) + if supply.Supply.Cmp(big.NewInt(0)) < 0 { + return nil, wrappeda0gibase.ErrInsufficientMintSupply + } + // transfer from wa0gi contract address & burn + evm.StateDB.SubBalance(wa0gi, uint256.MustFromBig(amount), tracing.BalanceIncreaseWA0GIMint) + // update supply + if err = w.setMinterSupply(evm, minter, supply); err != nil { + return nil, err + } + return method.Outputs.Pack() +}