feat: precompile initialization

This commit is contained in:
MiniFrenchBread 2024-12-28 00:58:15 +08:00
parent 6bca51e34c
commit 9bc8d568df
3 changed files with 72 additions and 60 deletions

View File

@ -0,0 +1,60 @@
package common
import (
"fmt"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/evmos/ethermint/x/evm/statedb"
)
type PrecompileCommon interface {
Abi() *abi.ABI
IsTx(string) bool
}
func InitializePrecompileCall(
p PrecompileCommon,
evm *vm.EVM,
contract *vm.Contract,
readonly bool,
) (
ctx sdk.Context,
stateDB *statedb.StateDB,
method *abi.Method,
initialGas storetypes.Gas,
args []interface{},
err error,
) {
// parse input
if len(contract.Input) < 4 {
return sdk.Context{}, nil, nil, uint64(0), nil, vm.ErrExecutionReverted
}
method, err = p.Abi().MethodById(contract.Input[:4])
if err != nil {
return sdk.Context{}, nil, nil, uint64(0), nil, vm.ErrExecutionReverted
}
args, err = method.Inputs.Unpack(contract.Input[4:])
if err != nil {
return sdk.Context{}, nil, nil, uint64(0), nil, err
}
// readonly check
if readonly && p.IsTx(method.Name) {
return sdk.Context{}, nil, nil, uint64(0), nil, fmt.Errorf(ErrWriteOnReadOnly)
}
// get state db and context
stateDB, ok := evm.StateDB.(*statedb.StateDB)
if !ok {
return sdk.Context{}, nil, nil, uint64(0), nil, fmt.Errorf(ErrGetStateDB)
}
ctx, err = stateDB.GetCachedContextForPrecompile()
if err != nil {
return sdk.Context{}, nil, nil, uint64(0), nil, err
}
// initial gas
initialGas = ctx.GasMeter().GasConsumed()
return ctx, stateDB, method, initialGas, args, nil
}

View File

@ -1,16 +1,13 @@
package dasigners
import (
"fmt"
"strings"
precompiles_common "github.com/0glabs/0g-chain/precompiles/common"
dasignerskeeper "github.com/0glabs/0g-chain/x/dasigners/v1/keeper"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/evmos/ethermint/x/evm/statedb"
)
const (
@ -47,17 +44,8 @@ var RequiredGasBasic = map[string]uint64{
DASignersFunctionRegisteredEpoch: 10000,
}
var KVGasConfig storetypes.GasConfig = storetypes.GasConfig{
HasCost: 0,
DeleteCost: 0,
ReadCostFlat: 0,
ReadCostPerByte: 0,
WriteCostFlat: 0,
WriteCostPerByte: 0,
IterNextCostFlat: 0,
}
var _ vm.PrecompiledContract = &DASignersPrecompile{}
var _ precompiles_common.PrecompileCommon = &DASignersPrecompile{}
type DASignersPrecompile struct {
abi abi.ABI
@ -103,33 +91,16 @@ func (d *DASignersPrecompile) IsTx(method string) bool {
}
}
func (d *DASignersPrecompile) Abi() *abi.ABI {
return &d.abi
}
// Run implements vm.PrecompiledContract.
func (d *DASignersPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
// parse input
if len(contract.Input) < 4 {
return nil, vm.ErrExecutionReverted
}
method, err := d.abi.MethodById(contract.Input[:4])
if err != nil {
return nil, vm.ErrExecutionReverted
}
args, err := method.Inputs.Unpack(contract.Input[4:])
ctx, stateDB, method, initialGas, args, err := precompiles_common.InitializePrecompileCall(d, evm, contract, readonly)
if err != nil {
return nil, err
}
// readonly check
if readonly && d.IsTx(method.Name) {
return nil, fmt.Errorf(precopmiles_common.ErrWriteOnReadOnly)
}
// get state db and context
stateDB, ok := evm.StateDB.(*statedb.StateDB)
if !ok {
return nil, fmt.Errorf(precompiles_common.ErrGetStateDB)
}
ctx := stateDB.GetContext()
// reset gas config
ctx = ctx.WithKVGasConfig(KVGasConfig)
initialGas := ctx.GasMeter().GasConsumed()
var bz []byte
switch method.Name {

View File

@ -1,16 +1,13 @@
package staking
import (
"fmt"
"strings"
precompiles_common "github.com/0glabs/0g-chain/precompiles/common"
"github.com/cosmos/cosmos-sdk/store/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/evmos/ethermint/x/evm/statedb"
)
const (
@ -40,6 +37,7 @@ const (
)
var _ vm.PrecompiledContract = &StakingPrecompile{}
var _ precompiles_common.PrecompileCommon = &StakingPrecompile{}
type StakingPrecompile struct {
abi abi.ABI
@ -67,6 +65,10 @@ func (s *StakingPrecompile) RequiredGas(input []byte) uint64 {
return 0
}
func (s *StakingPrecompile) Abi() *abi.ABI {
return &s.abi
}
func (s *StakingPrecompile) IsTx(method string) bool {
switch method {
case StakingFunctionCreateValidator,
@ -83,31 +85,10 @@ func (s *StakingPrecompile) IsTx(method string) bool {
// Run implements vm.PrecompiledContract.
func (s *StakingPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
// parse input
if len(contract.Input) < 4 {
return nil, vm.ErrExecutionReverted
}
method, err := s.abi.MethodById(contract.Input[:4])
if err != nil {
return nil, vm.ErrExecutionReverted
}
args, err := method.Inputs.Unpack(contract.Input[4:])
ctx, stateDB, method, initialGas, args, err := precompiles_common.InitializePrecompileCall(s, evm, contract, readonly)
if err != nil {
return nil, err
}
// readonly check
if readonly && s.IsTx(method.Name) {
return nil, fmt.Errorf(precopmiles_common.ErrWriteOnReadOnly)
}
// get state db and context
stateDB, ok := evm.StateDB.(*statedb.StateDB)
if !ok {
return nil, fmt.Errorf(precompiles_common.ErrGetStateDB)
}
ctx := stateDB.GetContext()
// reset gas config
ctx = ctx.WithKVGasConfig(types.KVGasConfig())
initialGas := ctx.GasMeter().GasConsumed()
var bz []byte
switch method.Name {