0g-chain/precompiles/staking/staking.go
2024-12-14 01:52:50 +08:00

167 lines
5.6 KiB
Go

package staking
import (
"fmt"
"strings"
precopmiles_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 (
PrecompileAddress = "0x0000000000000000000000000000000000001001"
// txs
StakingFunctionCreateValidator = "createValidator"
StakingFunctionEditValidator = "editValidator"
StakingFunctionDelegate = "delegate"
StakingFunctionBeginRedelegate = "beginRedelegate"
StakingFunctionUndelegate = "undelegate"
StakingFunctionCancelUnbondingDelegation = "cancelUnbondingDelegation"
// queries
StakingFunctionValidators = "validators"
StakingFunctionValidator = "validator"
StakingFunctionValidatorDelegations = "validatorDelegations"
StakingFunctionValidatorUnbondingDelegations = "validatorUnbondingDelegations"
StakingFunctionDelegation = "delegation"
StakingFunctionUnbondingDelegation = "unbondingDelegation"
StakingFunctionDelegatorDelegations = "delegatorDelegations"
StakingFunctionDelegatorUnbondingDelegations = "delegatorUnbondingDelegations"
StakingFunctionRedelegations = "redelegations"
StakingFunctionDelegatorValidators = "delegatorValidators"
StakingFunctionDelegatorValidator = "delegatorValidator"
StakingFunctionPool = "pool"
StakingFunctionParams = "params"
)
var _ vm.PrecompiledContract = &StakingPrecompile{}
type StakingPrecompile struct {
abi abi.ABI
stakingKeeper *stakingkeeper.Keeper
}
func NewStakingPrecompile(stakingKeeper *stakingkeeper.Keeper) (*StakingPrecompile, error) {
abi, err := abi.JSON(strings.NewReader(StakingABI))
if err != nil {
return nil, err
}
return &StakingPrecompile{
abi: abi,
stakingKeeper: stakingKeeper,
}, nil
}
// Address implements vm.PrecompiledContract.
func (s *StakingPrecompile) Address() common.Address {
return common.HexToAddress(PrecompileAddress)
}
// RequiredGas implements vm.PrecompiledContract.
func (s *StakingPrecompile) RequiredGas(input []byte) uint64 {
return 0
}
func (s *StakingPrecompile) IsTx(method string) bool {
switch method {
case StakingFunctionCreateValidator,
StakingFunctionEditValidator,
StakingFunctionDelegate,
StakingFunctionBeginRedelegate,
StakingFunctionUndelegate,
StakingFunctionCancelUnbondingDelegation:
return true
default:
return false
}
}
// 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:])
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(precopmiles_common.ErrGetStateDB)
}
ctx := stateDB.GetContext()
// reset gas config
ctx = ctx.WithKVGasConfig(types.KVGasConfig())
initialGas := ctx.GasMeter().GasConsumed()
var bz []byte
switch method.Name {
// queries
case StakingFunctionValidators:
bz, err = s.Validators(ctx, evm, method, args)
case StakingFunctionValidator:
bz, err = s.Validator(ctx, evm, method, args)
case StakingFunctionValidatorDelegations:
bz, err = s.ValidatorDelegations(ctx, evm, method, args)
case StakingFunctionValidatorUnbondingDelegations:
bz, err = s.ValidatorUnbondingDelegations(ctx, evm, method, args)
case StakingFunctionDelegation:
bz, err = s.Delegation(ctx, evm, method, args)
case StakingFunctionUnbondingDelegation:
bz, err = s.UnbondingDelegation(ctx, evm, method, args)
case StakingFunctionDelegatorDelegations:
bz, err = s.DelegatorDelegations(ctx, evm, method, args)
case StakingFunctionDelegatorUnbondingDelegations:
bz, err = s.DelegatorUnbondingDelegations(ctx, evm, method, args)
case StakingFunctionRedelegations:
bz, err = s.Redelegations(ctx, evm, method, args)
case StakingFunctionDelegatorValidators:
bz, err = s.DelegatorValidators(ctx, evm, method, args)
case StakingFunctionDelegatorValidator:
bz, err = s.DelegatorValidator(ctx, evm, method, args)
case StakingFunctionPool:
bz, err = s.Pool(ctx, evm, method, args)
case StakingFunctionParams:
bz, err = s.Params(ctx, evm, method, args)
// txs
case StakingFunctionCreateValidator:
bz, err = s.CreateValidator(ctx, evm, stateDB, contract, method, args)
case StakingFunctionEditValidator:
bz, err = s.EditValidator(ctx, evm, stateDB, contract, method, args)
case StakingFunctionDelegate:
bz, err = s.Delegate(ctx, evm, stateDB, contract, method, args)
case StakingFunctionBeginRedelegate:
bz, err = s.BeginRedelegate(ctx, evm, stateDB, contract, method, args)
case StakingFunctionUndelegate:
bz, err = s.Undelegate(ctx, evm, stateDB, contract, method, args)
case StakingFunctionCancelUnbondingDelegation:
bz, err = s.CancelUnbondingDelegation(ctx, evm, stateDB, contract, method, args)
}
if err != nil {
return nil, err
}
cost := ctx.GasMeter().GasConsumed() - initialGas
if !contract.UseGas(cost) {
return nil, vm.ErrOutOfGas
}
return bz, nil
}