feat: staking precompile

This commit is contained in:
MiniFrenchBread 2024-10-24 21:23:45 +08:00
parent c80874b0ea
commit e308e44dd6
21 changed files with 7492 additions and 20 deletions

5
.gitignore vendored
View File

@ -49,3 +49,8 @@ go.work.sum
# runtime
run
# contracts
precompiles/interfaces/build
precompiles/interfaces/node_modules
precompiles/interfaces/abis

View File

@ -3,4 +3,5 @@ package common
const (
ErrGetStateDB = "get EVM StateDB failed"
ErrInvalidNumberOfArgs = "invalid number of arguments; expected %d; got: %d"
ErrSenderNotOrigin = "msg.sender is not from tx origin"
)

View File

@ -0,0 +1,18 @@
package common
import (
"math/big"
"strings"
"cosmossdk.io/math"
"github.com/ethereum/go-ethereum/common"
)
func ToLowerHexWithoutPrefix(addr common.Address) string {
return strings.ToLower(addr.Hex()[2:])
}
// BigIntToLegacyDec converts a uint number (18 decimals) to math.LegacyDec (18 decimals)
func BigIntToLegacyDec(x *big.Int) math.LegacyDec {
return math.LegacyNewDecFromBigIntWithPrec(x, math.LegacyPrecision)
}

View File

@ -139,11 +139,11 @@ func (d *DASignersPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly b
bz, err = d.RegisteredEpoch(ctx, evm, method, args)
// txs
case DASignersFunctionRegisterSigner:
bz, err = d.RegisterSigner(ctx, evm, stateDB, method, args)
bz, err = d.RegisterSigner(ctx, evm, stateDB, contract, method, args)
case DASignersFunctionRegisterNextEpoch:
bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, method, args)
bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, contract, method, args)
case DASignersFunctionUpdateSocket:
bz, err = d.UpdateSocket(ctx, evm, stateDB, method, args)
bz, err = d.UpdateSocket(ctx, evm, stateDB, contract, method, args)
}
if err != nil {

View File

@ -62,7 +62,7 @@ func (d *DASignersPrecompile) IsSigner(ctx sdk.Context, _ *vm.EVM, method *abi.M
if len(args) != 1 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
account := ToLowerHexWithoutPrefix(args[0].(common.Address))
account := precopmiles_common.ToLowerHexWithoutPrefix(args[0].(common.Address))
_, found, err := d.dasignersKeeper.GetSigner(ctx, account)
if err != nil {
return nil, err
@ -74,7 +74,7 @@ func (d *DASignersPrecompile) RegisteredEpoch(ctx sdk.Context, _ *vm.EVM, method
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
account := ToLowerHexWithoutPrefix(args[0].(common.Address))
account := precopmiles_common.ToLowerHexWithoutPrefix(args[0].(common.Address))
epoch := args[1].(*big.Int).Uint64()
_, found, err := d.dasignersKeeper.GetRegistration(ctx, epoch, account)
if err != nil {

View File

@ -7,18 +7,30 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/evmos/ethermint/x/evm/statedb"
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
)
func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) {
func (d *DASignersPrecompile) RegisterSigner(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgRegisterSigner(args)
if err != nil {
return nil, err
}
// validation
sender := ToLowerHexWithoutPrefix(evm.Origin)
sender := precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin)
if sender != msg.Signer.Account {
return nil, fmt.Errorf(ErrInvalidSender, sender, msg.Signer.Account)
}
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = d.dasignersKeeper.RegisterSigner(sdk.WrapSDKContext(ctx), msg)
if err != nil {
@ -32,11 +44,22 @@ func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, state
return method.Outputs.Pack()
}
func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) {
msg, err := NewMsgRegisterNextEpoch(args, ToLowerHexWithoutPrefix(evm.Origin))
func (d *DASignersPrecompile) RegisterNextEpoch(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgRegisterNextEpoch(args, precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = d.dasignersKeeper.RegisterNextEpoch(sdk.WrapSDKContext(ctx), msg)
if err != nil {
@ -45,11 +68,22 @@ func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, st
return method.Outputs.Pack()
}
func (d *DASignersPrecompile) UpdateSocket(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) {
msg, err := NewMsgUpdateSocket(args, ToLowerHexWithoutPrefix(evm.Origin))
func (d *DASignersPrecompile) UpdateSocket(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgUpdateSocket(args, precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = d.dasignersKeeper.UpdateSocket(sdk.WrapSDKContext(ctx), msg)
if err != nil {

View File

@ -3,7 +3,6 @@ package dasigners
import (
"fmt"
"math/big"
"strings"
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
dasignerstypes "github.com/0glabs/0g-chain/x/dasigners/v1/types"
@ -90,7 +89,7 @@ func NewQuerySignerRequest(args []interface{}) (*dasignerstypes.QuerySignerReque
Accounts: make([]string, len(accounts)),
}
for i, account := range accounts {
req.Accounts[i] = ToLowerHexWithoutPrefix(account)
req.Accounts[i] = precopmiles_common.ToLowerHexWithoutPrefix(account)
}
return &req, nil
}
@ -139,10 +138,6 @@ func NewIDASignersSignerDetail(signer *dasignerstypes.Signer) IDASignersSignerDe
}
}
func ToLowerHexWithoutPrefix(addr common.Address) string {
return strings.ToLower(addr.Hex()[2:])
}
func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
@ -151,7 +146,7 @@ func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner
signer := args[0].(IDASignersSignerDetail)
return &dasignerstypes.MsgRegisterSigner{
Signer: &dasignerstypes.Signer{
Account: ToLowerHexWithoutPrefix(signer.Signer),
Account: precopmiles_common.ToLowerHexWithoutPrefix(signer.Signer),
Socket: signer.Socket,
PubkeyG1: SerializeG1(signer.PkG1),
PubkeyG2: SerializeG2(signer.PkG2),

View File

@ -0,0 +1,18 @@
{
"extends": "solhint:recommended",
"plugins": ["prettier"],
"rules": {
"avoid-low-level-calls": "off",
"compiler-version": "off",
"gas-custom-errors": "off",
"explicit-types": ["warn", "implicit"],
"func-visibility": ["warn", { "ignoreConstructors": true }],
"max-states-count": "off",
"no-empty-blocks": "off",
"no-global-import": "off",
"no-inline-assembly": "off",
"not-rely-on-time": "off",
"prettier/prettier": "error",
"reason-string": "off"
}
}

View File

@ -0,0 +1,88 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;
library BN254 {
struct G1Point {
uint X;
uint Y;
}
// Encoding of field elements is: X[1] * i + X[0]
struct G2Point {
uint[2] X;
uint[2] Y;
}
}
interface IDASigners {
/*=== struct ===*/
struct SignerDetail {
address signer;
string socket;
BN254.G1Point pkG1;
BN254.G2Point pkG2;
}
struct Params {
uint tokensPerVote;
uint maxVotesPerSigner;
uint maxQuorums;
uint epochBlocks;
uint encodedSlices;
}
/*=== event ===*/
event NewSigner(
address indexed signer,
BN254.G1Point pkG1,
BN254.G2Point pkG2
);
event SocketUpdated(address indexed signer, string socket);
/*=== function ===*/
function params() external view returns (Params memory);
function epochNumber() external view returns (uint);
function quorumCount(uint _epoch) external view returns (uint);
function isSigner(address _account) external view returns (bool);
function getSigner(
address[] memory _account
) external view returns (SignerDetail[] memory);
function getQuorum(
uint _epoch,
uint _quorumId
) external view returns (address[] memory);
function getQuorumRow(
uint _epoch,
uint _quorumId,
uint32 _rowIndex
) external view returns (address);
function registerSigner(
SignerDetail memory _signer,
BN254.G1Point memory _signature
) external;
function updateSocket(string memory _socket) external;
function registeredEpoch(
address _account,
uint _epoch
) external view returns (bool);
function registerNextEpoch(BN254.G1Point memory _signature) external;
function getAggPkG1(
uint _epoch,
uint _quorumId,
bytes memory _quorumBitmap
)
external
view
returns (BN254.G1Point memory aggPkG1, uint total, uint hit);
}

View File

@ -0,0 +1,416 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;
/**
* @dev Description defines a validator description
*/
struct Description {
string moniker;
string identity;
string website;
string securityContact;
string details;
}
/**
* @dev CommissionRates defines the initial commission rates to be used for creating
* a validator.
*/
struct CommissionRates {
uint rate; // 18 decimals
uint maxRate; // 18 decimals
uint maxChangeRate; // 18 decimals
}
/**
* @dev Commission defines the commission parameters.
*/
struct Commission {
CommissionRates commissionRates;
uint updateTime;
}
/**
* @dev Validator defines a validator.
*/
struct Validator {
string operatorAddress;
string consensusPubkey;
bool jailed;
BondStatus status;
uint tokens;
uint delegatorShares; // 18 decimals
Description description;
int64 unbondingHeight;
int64 unbondingTime;
Commission commission;
uint minSelfDelegation;
int64 unbondingOnHoldRefCount;
uint64[] unbondingIds;
}
/**
* @dev Delegation represents the bond with tokens held by an account.
*/
struct Delegation {
string delegatorAddress;
string validatorAddress;
uint shares; // 18 decimals
}
/**
* @dev RedelegationResponse is equivalent to a Redelegation except that its entries
* contain a balance in addition to shares which is more suitable for client
* responses.
*/
struct DelegationResponse {
Delegation delegation;
uint balance;
}
/**
* @dev UnbondingDelegationEntry defines an unbonding object with relevant metadata.
*/
struct UnbondingDelegationEntry {
int64 creationHeight;
int64 completionTime;
uint initialBalance;
uint balance;
uint64 unbondingId;
int64 unbondingOnHoldRefCount;
}
/**
* @dev UnbondingDelegation stores all of a single delegator's unbonding bonds
* for a single validator in an time-ordered list.
*/
struct UnbondingDelegation {
string delegatorAddress;
string validatorAddress;
UnbondingDelegationEntry[] entries;
}
/**
* @dev RedelegationResponse is equivalent to a Redelegation except that its entries
* contain a balance in addition to shares which is more suitable for client
* responses.
*/
struct RedelegationResponse {
Redelegation redelegation;
RedelegationEntryResponse[] entries;
}
/**
* @dev Redelegation contains the list of a particular delegator's redelegating bonds
* from a particular source validator to a particular destination validator.
*/
struct Redelegation {
string delegatorAddress;
string validatorSrcAddress;
string validatorDstAddress;
RedelegationEntry[] entries;
}
/**
* @dev RedelegationEntry defines a redelegation object with relevant metadata.
*/
struct RedelegationEntry {
int64 creationHeight;
int64 completionTime;
uint initialBalance;
uint sharesDst; // 18 decimals
uint64 unbondingId;
int64 unbondingOnHoldRefCount;
}
/**
* @dev RedelegationEntryResponse is equivalent to a RedelegationEntry except that it
* contains a balance in addition to shares which is more suitable for client
* responses.
*/
struct RedelegationEntryResponse {
RedelegationEntry redelegationEntry;
uint balance;
}
/**
* @dev Params defines the parameters for the x/staking module.
*/
struct Params {
int64 unbondingTime;
uint32 maxValidators;
uint32 maxEntries;
uint32 historicalEntries;
string bondDenom;
uint minCommissionRate; // 18 decimals
}
/**
* @dev BondStatus is the status of a validator.
*/
enum BondStatus {
Unspecified,
Unbonded,
Unbonding,
Bonded
}
struct NullableUint {
bool isNull;
uint value;
}
struct PageRequest {
bytes key;
uint64 offset;
uint64 limit;
bool countTotal;
bool reverse;
}
struct PageResponse {
bytes nextKey;
uint64 total;
}
interface IStaking {
/*=== cosmos tx ===*/
/**
* @dev CreateValidator defines a method for creating a new validator for tx sender.
* cosmos grpc: rpc CreateValidator(MsgCreateValidator) returns (MsgCreateValidatorResponse);
*/
function createValidator(
Description memory description,
CommissionRates memory commission,
uint minSelfDelegation,
string memory pubkey,
uint value
) external;
/**
* @dev EditValidator defines a method for editing an existing validator (tx sender).
* cosmos grpc: rpc EditValidator(MsgEditValidator) returns (MsgEditValidatorResponse);
*/
function editValidator(
Description memory description,
NullableUint memory commissionRate,
NullableUint memory minSelfDelegation
) external;
/**
* @dev Delegate defines a method for performing a delegation of coins from a delegator to a validator.abi
* The delegator is tx sender.
* cosmos grpc: rpc Delegate(MsgDelegate) returns (MsgDelegateResponse);
*/
function delegate(
string memory validatorAddress,
uint amount // in bond denom
) external returns (bool success);
/**
* @dev BeginRedelegate defines a method for performing a redelegationA
* of coins from a delegator and source validator to a destination validator.
* The delegator is tx sender.
* cosmos grpc: rpc BeginRedelegate(MsgBeginRedelegate) returns (MsgBeginRedelegateResponse);
*/
function beginRedelegate(
string memory validatorSrcAddress,
string memory validatorDstAddress,
uint amount // in bond denom
) external returns (uint completionTime);
/**
* @dev Undelegate defines a method for performing an undelegation from a
* delegate and a validator.
* The delegator is tx sender.
* cosmos grpc: rpc Undelegate(MsgUndelegate) returns (MsgUndelegateResponse);
*/
function undelegate(
string memory validatorAddress,
uint amount // in bond denom
) external returns (uint completionTime);
/**
* @dev CancelUnbondingDelegation defines a method for performing canceling the unbonding delegation
* and delegate back to previous validator.
* The delegator is tx sender.
* Since: cosmos-sdk 0.46
* cosmos grpc: rpc CancelUnbondingDelegation(MsgCancelUnbondingDelegation) returns (MsgCancelUnbondingDelegationResponse);
*/
function cancelUnbondingDelegation(
string memory validatorAddress,
uint amount, // in bond denom
uint creationHeight
) external;
/**
* @dev UpdateParams defines an operation for updating the x/staking module parameters.
* Since: cosmos-sdk 0.47
* grpc: rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
*/
// Skipped. This function is controlled by governance module.
/*=== cosmos query ===*/
/**
* @dev Validators queries all validators that match the given status.
* cosmos grpc: rpc Validators(QueryValidatorsRequest) returns (QueryValidatorsResponse);
*/
function validators(
string memory status,
PageRequest memory pagination
)
external
view
returns (
Validator[] memory validators,
PageResponse memory paginationResult
);
/**
* @dev Validator queries validator info for given validator address.
* cosmos grpc: rpc Validator(QueryValidatorRequest) returns (QueryValidatorResponse);
*/
function validator(
string memory validatorAddress
) external view returns (Validator memory validator);
/**
* @dev ValidatorDelegations queries delegate info for given validator.
* cosmos grpc: rpc ValidatorDelegations(QueryValidatorDelegationsRequest) returns (QueryValidatorDelegationsResponse);
*/
function validatorDelegations(
string memory validatorAddr,
PageRequest memory pagination
)
external
view
returns (
DelegationResponse[] memory delegationResponses,
PageResponse memory paginationResult
);
/**
* @dev ValidatorUnbondingDelegations queries unbonding delegations of a validator.
* cosmos grpc: rpc ValidatorUnbondingDelegations(QueryValidatorUnbondingDelegationsRequest) returns (QueryValidatorUnbondingDelegationsResponse);
*/
//
function validatorUnbondingDelegations(
string memory validatorAddr,
PageRequest memory pagination
)
external
view
returns (
UnbondingDelegation[] memory unbondingResponses,
PageResponse memory paginationResult
);
/**
* @dev Delegation queries delegate info for given validator delegator pair.
* cosmos grpc: rpc Delegation(QueryDelegationRequest) returns (QueryDelegationResponse);
*/
function delegation(
string memory delegatorAddr,
string memory validatorAddr
) external view returns (Delegation memory delegation, uint balance);
/**
* @dev UnbondingDelegation queries unbonding info for given validator delegator pair.
* cosmos grpc: rpc UnbondingDelegation(QueryUnbondingDelegationRequest) returns (QueryUnbondingDelegationResponse);
*/
function unbondingDelegation(
string memory delegatorAddr,
string memory validatorAddr
) external view returns (UnbondingDelegation memory unbond);
/**
* @dev DelegatorDelegations queries all delegations of a given delegator address.
*
* cosmos grpc: rpc DelegatorDelegations(QueryDelegatorDelegationsRequest) returns (QueryDelegatorDelegationsResponse);
*/
function delegatorDelegations(
string memory delegatorAddr,
PageRequest memory pagination
)
external
view
returns (
DelegationResponse[] memory delegationResponses,
PageResponse memory paginationResult
);
/**
* @dev DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address.
* cosmos grpc: rpc DelegatorUnbondingDelegations(QueryDelegatorUnbondingDelegationsRequest)
*/
function delegatorUnbondingDelegations(
string memory delegatorAddr,
PageRequest memory pagination
)
external
view
returns (
UnbondingDelegation[] memory unbondingResponses,
PageResponse memory paginationResult
);
/**
* @dev Redelegations queries redelegations of given address.
*
* grpc: rpc Redelegations(QueryRedelegationsRequest) returns (QueryRedelegationsResponse);
*/
function redelegations(
string memory delegatorAddress,
string memory srcValidatorAddress,
string memory dstValidatorAddress,
PageRequest calldata pageRequest
)
external
view
returns (
RedelegationResponse[] calldata redelegationResponses,
PageResponse calldata paginationResult
);
/**
* @dev DelegatorValidators queries all validators info for given delegator address.
* cosmos grpc: rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse);
*/
function delegatorValidators(
string memory delegatorAddr,
PageRequest memory pagination
)
external
view
returns (
Validator[] memory validators,
PageResponse memory paginationResult
);
/**
* @dev DelegatorValidator queries validator info for given delegator validator pair.
* cosmos grpc: rpc DelegatorValidator(QueryDelegatorValidatorRequest) returns (QueryDelegatorValidatorResponse);
*/
function delegatorValidator(
string memory delegatorAddr,
string memory validatorAddr
) external view returns (Validator memory validator);
/**
* @dev Pool queries the pool info.
* cosmos grpc: rpc Pool(QueryPoolRequest) returns (QueryPoolResponse);
*/
function pool()
external
view
returns (uint notBondedTokens, uint bondedTokens);
/**
* @dev Parameters queries the staking parameters.
* cosmos grpc: rpc Params(QueryParamsRequest) returns (QueryParamsResponse);
*/
function params() external view returns (Params memory params);
}

View File

@ -0,0 +1,33 @@
import "hardhat-abi-exporter";
import { HardhatUserConfig } from "hardhat/types";
const config: HardhatUserConfig = {
paths: {
artifacts: "build/artifacts",
cache: "build/cache",
sources: "contracts",
},
solidity: {
compilers: [
{
version: "0.8.20",
settings: {
evmVersion: "london",
optimizer: {
enabled: true,
runs: 200,
},
},
},
],
},
abiExporter: {
path: "./abis",
runOnCompile: true,
clear: true,
flat: true,
format: "json",
},
};
export default config;

View File

@ -0,0 +1,27 @@
{
"name": "precompile-contracts",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"build": "hardhat compile",
"fmt:sol": "prettier 'contracts/**/*.sol' -w"
},
"devDependencies": {
"@nomicfoundation/hardhat-ethers": "^3.0.5",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"eslint": "8.34.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-no-only-tests": "3.1.0",
"eslint-plugin-prettier": "4.2.1",
"hardhat": "^2.22.2",
"hardhat-abi-exporter": "^2.10.1",
"prettier": "2.8.4",
"prettier-plugin-organize-imports": "3.2.4",
"prettier-plugin-solidity": "1.1.2",
"solhint": "^4.5.4",
"solhint-plugin-prettier": "0.0.5",
"ts-node": "^10.9.2",
"typescript": "4.9.5"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
package staking
const (
ErrPubKeyInvalidLength = "public key with invalid length"
)

View File

@ -0,0 +1,223 @@
package staking
import (
sdk "github.com/cosmos/cosmos-sdk/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/vm"
)
func (s *StakingPrecompile) Validators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Validators(ctx, req)
if err != nil {
return nil, err
}
validators := make([]Validator, len(response.Validators))
for i, v := range response.Validators {
validators[i] = convertValidator(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(validators, paginationResult)
}
func (s *StakingPrecompile) Validator(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Validator(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertValidator(response.Validator))
}
func (s *StakingPrecompile) ValidatorDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorDelegationsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.ValidatorDelegations(ctx, req)
if err != nil {
return nil, err
}
delegationResponses := make([]DelegationResponse, len(response.DelegationResponses))
for i, v := range response.DelegationResponses {
delegationResponses[i] = convertDelegationResponse(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(delegationResponses, paginationResult)
}
func (s *StakingPrecompile) ValidatorUnbondingDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryValidatorUnbondingDelegationsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.ValidatorUnbondingDelegations(ctx, req)
if err != nil {
return nil, err
}
unbondingResponses := make([]UnbondingDelegation, len(response.UnbondingResponses))
for i, v := range response.UnbondingResponses {
unbondingResponses[i] = convertUnbondingDelegation(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(unbondingResponses, paginationResult)
}
func (s *StakingPrecompile) Delegation(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegationRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Delegation(ctx, req)
if err != nil {
return nil, err
}
delegation := convertDelegation(response.DelegationResponse.Delegation)
balance := response.DelegationResponse.Balance.Amount.BigInt()
return method.Outputs.Pack(delegation, balance)
}
func (s *StakingPrecompile) UnbondingDelegation(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryUnbondingDelegationRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.UnbondingDelegation(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertUnbondingDelegation(response.Unbond))
}
func (s *StakingPrecompile) DelegatorDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegatorDelegationsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorDelegations(ctx, req)
if err != nil {
return nil, err
}
delegationResponses := make([]DelegationResponse, len(response.DelegationResponses))
for i, v := range response.DelegationResponses {
delegationResponses[i] = convertDelegationResponse(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(delegationResponses, paginationResult)
}
func (s *StakingPrecompile) DelegatorUnbondingDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegatorUnbondingDelegationsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorUnbondingDelegations(ctx, req)
if err != nil {
return nil, err
}
unbondingResponses := make([]UnbondingDelegation, len(response.UnbondingResponses))
for i, v := range response.UnbondingResponses {
unbondingResponses[i] = convertUnbondingDelegation(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(unbondingResponses, paginationResult)
}
func (s *StakingPrecompile) Redelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryRedelegationsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Redelegations(ctx, req)
if err != nil {
return nil, err
}
redelegationResponses := make([]RedelegationResponse, len(response.RedelegationResponses))
for i, v := range response.RedelegationResponses {
redelegationResponses[i] = convertRedelegationResponse(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(redelegationResponses, paginationResult)
}
func (s *StakingPrecompile) DelegatorValidators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegatorValidatorsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorValidators(ctx, req)
if err != nil {
return nil, err
}
validators := make([]Validator, len(response.Validators))
for i, v := range response.Validators {
validators[i] = convertValidator(v)
}
paginationResult := convertPageResponse(response.Pagination)
return method.Outputs.Pack(validators, paginationResult)
}
func (s *StakingPrecompile) DelegatorValidator(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryDelegatorValidatorRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorValidator(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertValidator(response.Validator))
}
func (s *StakingPrecompile) Pool(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryPoolRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Pool(ctx, req)
if err != nil {
return nil, err
}
notBondedTokens := response.Pool.NotBondedTokens.BigInt()
bondedTokens := response.Pool.BondedTokens.BigInt()
return method.Outputs.Pack(notBondedTokens, bondedTokens)
}
func (s *StakingPrecompile) Params(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
req, err := NewQueryParamsRequest(args)
if err != nil {
return nil, err
}
response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Params(ctx, req)
if err != nil {
return nil, err
}
return method.Outputs.Pack(convertParams(response.Params))
}

View File

@ -0,0 +1,148 @@
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
}
// 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
}
// 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
}

162
precompiles/staking/tx.go Normal file
View File

@ -0,0 +1,162 @@
package staking
import (
"fmt"
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
sdk "github.com/cosmos/cosmos-sdk/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/evmos/ethermint/x/evm/statedb"
)
func (s *StakingPrecompile) CreateValidator(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgCreateValidator(args, evm.Origin, s.stakingKeeper.BondDenom(ctx))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).CreateValidator(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
}
func (s *StakingPrecompile) EditValidator(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgEditValidator(args, evm.Origin)
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).EditValidator(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
}
func (s *StakingPrecompile) Delegate(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgDelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Delegate(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
}
func (s *StakingPrecompile) BeginRedelegate(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgBeginRedelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).BeginRedelegate(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
}
func (s *StakingPrecompile) Undelegate(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgUndelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Undelegate(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
}
func (s *StakingPrecompile) CancelUnbondingDelegation(
ctx sdk.Context,
evm *vm.EVM,
stateDB *statedb.StateDB,
contract *vm.Contract,
method *abi.Method,
args []interface{},
) ([]byte, error) {
msg, err := NewMsgCancelUnbondingDelegation(args, evm.Origin, s.stakingKeeper.BondDenom(ctx))
if err != nil {
return nil, err
}
// validation
if contract.CallerAddress != evm.Origin {
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).CancelUnbondingDelegation(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
}

View File

@ -0,0 +1,590 @@
package staking
import (
"encoding/base64"
"errors"
"fmt"
"math/big"
"cosmossdk.io/math"
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
query "github.com/cosmos/cosmos-sdk/types/query"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/common"
)
type Commission struct {
CommissionRates CommissionRates `json:"commissionRates"`
UpdateTime *big.Int `json:"updateTime"`
}
type CommissionRates struct {
Rate *big.Int `json:"rate"`
MaxRate *big.Int `json:"maxRate"`
MaxChangeRate *big.Int `json:"maxChangeRate"`
}
type Delegation struct {
DelegatorAddress string `json:"delegatorAddress"`
ValidatorAddress string `json:"validatorAddress"`
Shares *big.Int `json:"shares"`
}
type DelegationResponse struct {
Delegation Delegation `json:"delegation"`
Balance *big.Int `json:"balance"`
}
type Description struct {
Moniker string `json:"moniker"`
Identity string `json:"identity"`
Website string `json:"website"`
SecurityContact string `json:"securityContact"`
Details string `json:"details"`
}
type NullableUint struct {
IsNull bool `json:"isNull"`
Value *big.Int `json:"value"`
}
type PageRequest struct {
Key []byte `json:"key"`
Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"`
CountTotal bool `json:"countTotal"`
Reverse bool `json:"reverse"`
}
type PageResponse struct {
NextKey []byte `json:"nextKey"`
Total uint64 `json:"total"`
}
type Params struct {
UnbondingTime int64 `json:"unbondingTime"`
MaxValidators uint32 `json:"maxValidators"`
MaxEntries uint32 `json:"maxEntries"`
HistoricalEntries uint32 `json:"historicalEntries"`
BondDenom string `json:"bondDenom"`
MinCommissionRate *big.Int `json:"minCommissionRate"`
}
type Redelegation struct {
DelegatorAddress string `json:"delegatorAddress"`
ValidatorSrcAddress string `json:"validatorSrcAddress"`
ValidatorDstAddress string `json:"validatorDstAddress"`
Entries []RedelegationEntry `json:"entries"`
}
type RedelegationEntry struct {
CreationHeight int64 `json:"creationHeight"`
CompletionTime int64 `json:"completionTime"`
InitialBalance *big.Int `json:"initialBalance"`
SharesDst *big.Int `json:"sharesDst"`
UnbondingId uint64 `json:"unbondingId"`
UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"`
}
type RedelegationEntryResponse struct {
RedelegationEntry RedelegationEntry `json:"redelegationEntry"`
Balance *big.Int `json:"balance"`
}
type RedelegationResponse struct {
Redelegation Redelegation `json:"redelegation"`
Entries []RedelegationEntryResponse `json:"entries"`
}
type UnbondingDelegation struct {
DelegatorAddress string `json:"delegatorAddress"`
ValidatorAddress string `json:"validatorAddress"`
Entries []UnbondingDelegationEntry `json:"entries"`
}
type UnbondingDelegationEntry struct {
CreationHeight int64 `json:"creationHeight"`
CompletionTime int64 `json:"completionTime"`
InitialBalance *big.Int `json:"initialBalance"`
Balance *big.Int `json:"balance"`
UnbondingId uint64 `json:"unbondingId"`
UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"`
}
type Validator struct {
OperatorAddress string `json:"operatorAddress"`
ConsensusPubkey string `json:"consensusPubkey"`
Jailed bool `json:"jailed"`
Status uint8 `json:"status"`
Tokens *big.Int `json:"tokens"`
DelegatorShares *big.Int `json:"delegatorShares"`
Description Description `json:"description"`
UnbondingHeight int64 `json:"unbondingHeight"`
UnbondingTime int64 `json:"unbondingTime"`
Commission Commission `json:"commission"`
MinSelfDelegation *big.Int `json:"minSelfDelegation"`
UnbondingOnHoldRefCount int64 `json:"unbondingOnHoldRefCount"`
UnbondingIds []uint64 `json:"unbondingIds"`
}
func convertValidator(v stakingtypes.Validator) Validator {
validator := Validator{}
operatorAddress, err := sdk.ValAddressFromBech32(v.OperatorAddress)
if err != nil {
validator.OperatorAddress = v.OperatorAddress
} else {
validator.OperatorAddress = common.BytesToAddress(operatorAddress.Bytes()).String()
}
ed25519pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey)
if !ok {
validator.ConsensusPubkey = v.ConsensusPubkey.String()
} else {
validator.ConsensusPubkey = base64.StdEncoding.EncodeToString(ed25519pk.Bytes())
}
validator.Jailed = v.Jailed
validator.Status = uint8(v.Status)
validator.Tokens = v.Tokens.BigInt()
validator.DelegatorShares = v.DelegatorShares.BigInt()
validator.Description = Description{
Moniker: v.Description.Moniker,
Identity: v.Description.Identity,
Website: v.Description.Website,
SecurityContact: v.Description.SecurityContact,
Details: v.Description.Details,
}
validator.UnbondingHeight = v.UnbondingHeight
validator.UnbondingTime = v.UnbondingTime.UTC().Unix()
validator.Commission = Commission{
CommissionRates: convertCommissionRates(v.Commission.CommissionRates),
UpdateTime: big.NewInt(v.Commission.UpdateTime.UTC().Unix()),
}
validator.MinSelfDelegation = v.MinSelfDelegation.BigInt()
validator.UnbondingOnHoldRefCount = v.UnbondingOnHoldRefCount
validator.UnbondingIds = v.UnbondingIds
return validator
}
func convertQueryPageRequest(pagination PageRequest) *query.PageRequest {
return &query.PageRequest{
Key: pagination.Key,
Offset: pagination.Offset,
Limit: pagination.Limit,
CountTotal: pagination.CountTotal,
Reverse: pagination.Reverse,
}
}
func convertPageResponse(pagination *query.PageResponse) PageResponse {
return PageResponse{
NextKey: pagination.NextKey,
Total: pagination.Total,
}
}
func convertStakingDescription(description Description) stakingtypes.Description {
return stakingtypes.Description{
Moniker: description.Moniker,
Identity: description.Identity,
Website: description.Website,
SecurityContact: description.SecurityContact,
Details: description.Details,
}
}
func convertStakingCommissionRates(commission CommissionRates) stakingtypes.CommissionRates {
return stakingtypes.CommissionRates{
Rate: precopmiles_common.BigIntToLegacyDec(commission.Rate),
MaxRate: precopmiles_common.BigIntToLegacyDec(commission.MaxRate),
MaxChangeRate: precopmiles_common.BigIntToLegacyDec(commission.MaxChangeRate),
}
}
func convertCommissionRates(commission stakingtypes.CommissionRates) CommissionRates {
return CommissionRates{
Rate: commission.Rate.BigInt(),
MaxRate: commission.MaxRate.BigInt(),
MaxChangeRate: commission.MaxChangeRate.BigInt(),
}
}
func convertDelegation(delegation stakingtypes.Delegation) Delegation {
return Delegation{
DelegatorAddress: delegation.DelegatorAddress,
ValidatorAddress: delegation.ValidatorAddress,
Shares: delegation.Shares.BigInt(),
}
}
func convertDelegationResponse(response stakingtypes.DelegationResponse) DelegationResponse {
return DelegationResponse{
Delegation: convertDelegation(response.Delegation),
Balance: response.Balance.Amount.BigInt(),
}
}
func convertUnbondingDelegationEntry(entry stakingtypes.UnbondingDelegationEntry) UnbondingDelegationEntry {
return UnbondingDelegationEntry{
CreationHeight: entry.CreationHeight,
CompletionTime: entry.CompletionTime.UTC().Unix(),
InitialBalance: entry.InitialBalance.BigInt(),
Balance: entry.Balance.BigInt(),
UnbondingId: entry.UnbondingId,
UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount,
}
}
func convertUnbondingDelegation(response stakingtypes.UnbondingDelegation) UnbondingDelegation {
entries := make([]UnbondingDelegationEntry, len(response.Entries))
for i, v := range response.Entries {
entries[i] = convertUnbondingDelegationEntry(v)
}
return UnbondingDelegation{
DelegatorAddress: response.DelegatorAddress,
ValidatorAddress: response.ValidatorAddress,
Entries: entries,
}
}
func convertRedelegationEntry(entry stakingtypes.RedelegationEntry) RedelegationEntry {
return RedelegationEntry{
CreationHeight: entry.CreationHeight,
CompletionTime: entry.CompletionTime.UTC().Unix(),
InitialBalance: entry.InitialBalance.BigInt(),
SharesDst: entry.SharesDst.BigInt(),
UnbondingId: entry.UnbondingId,
UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount,
}
}
func convertRedelegation(redelegation stakingtypes.Redelegation) Redelegation {
entries := make([]RedelegationEntry, len(redelegation.Entries))
for i, v := range redelegation.Entries {
entries[i] = convertRedelegationEntry(v)
}
return Redelegation{
DelegatorAddress: redelegation.DelegatorAddress,
ValidatorSrcAddress: redelegation.ValidatorSrcAddress,
ValidatorDstAddress: redelegation.ValidatorDstAddress,
Entries: entries,
}
}
func convertRedelegationEntryResponse(response stakingtypes.RedelegationEntryResponse) RedelegationEntryResponse {
return RedelegationEntryResponse{
RedelegationEntry: convertRedelegationEntry(response.RedelegationEntry),
Balance: response.Balance.BigInt(),
}
}
func convertRedelegationResponse(response stakingtypes.RedelegationResponse) RedelegationResponse {
entries := make([]RedelegationEntryResponse, len(response.Entries))
for i, v := range response.Entries {
entries[i] = convertRedelegationEntryResponse(v)
}
return RedelegationResponse{
Redelegation: convertRedelegation(response.Redelegation),
Entries: entries,
}
}
func convertParams(params stakingtypes.Params) Params {
return Params{
UnbondingTime: int64(params.UnbondingTime.Seconds()),
MaxValidators: params.MaxValidators,
MaxEntries: params.MaxEntries,
HistoricalEntries: params.HistoricalEntries,
BondDenom: params.BondDenom,
MinCommissionRate: params.MinCommissionRate.BigInt(),
}
}
func NewMsgCreateValidator(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCreateValidator, error) {
if len(args) != 5 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 5, len(args))
}
description := args[0].(Description)
commission := args[1].(CommissionRates)
minSelfDelegation := args[2].(*big.Int)
pkstr := args[3].(string)
bz, err := base64.StdEncoding.DecodeString(pkstr)
if err != nil {
return nil, err
}
var pk cryptotypes.PubKey
if len(bz) == ed25519.PubKeySize {
pk = &ed25519.PubKey{Key: bz}
} else {
return nil, errors.New(ErrPubKeyInvalidLength)
}
pkAny, err := codectypes.NewAnyWithValue(pk)
if err != nil {
return nil, err
}
value := args[4].(*big.Int)
return &stakingtypes.MsgCreateValidator{
Description: convertStakingDescription(description),
Commission: convertStakingCommissionRates(commission),
MinSelfDelegation: math.NewIntFromBigInt(minSelfDelegation),
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(),
Pubkey: pkAny,
Value: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(value)},
}, nil
}
func NewMsgEditValidator(args []interface{}, sender common.Address) (*stakingtypes.MsgEditValidator, error) {
if len(args) != 3 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args))
}
description := args[0].(Description)
commissionRateNullable := args[1].(NullableUint)
var commissionRate *sdk.Dec
if !commissionRateNullable.IsNull {
value := precopmiles_common.BigIntToLegacyDec(commissionRateNullable.Value)
commissionRate = &value
}
minSelfDelegationNullable := args[2].(NullableUint)
var minSelfDelegation *sdk.Int
if !minSelfDelegationNullable.IsNull {
value := math.NewIntFromBigInt(minSelfDelegationNullable.Value)
minSelfDelegation = &value
}
return &stakingtypes.MsgEditValidator{
Description: convertStakingDescription(description),
CommissionRate: commissionRate,
ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(),
MinSelfDelegation: minSelfDelegation,
}, nil
}
func NewMsgDelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgDelegate, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
validatorAddress := args[0].(string)
amount := args[1].(*big.Int)
return &stakingtypes.MsgDelegate{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: validatorAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
}, nil
}
func NewMsgBeginRedelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgBeginRedelegate, error) {
if len(args) != 3 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args))
}
validatorSrcAddress := args[0].(string)
validatorDstAddress := args[1].(string)
amount := args[2].(*big.Int)
return &stakingtypes.MsgBeginRedelegate{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorSrcAddress: validatorSrcAddress,
ValidatorDstAddress: validatorDstAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
}, nil
}
func NewMsgUndelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgUndelegate, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
validatorAddress := args[0].(string)
amount := args[1].(*big.Int)
return &stakingtypes.MsgUndelegate{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: validatorAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
}, nil
}
func NewMsgCancelUnbondingDelegation(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCancelUnbondingDelegation, error) {
if len(args) != 3 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args))
}
validatorAddress := args[0].(string)
amount := args[1].(*big.Int)
creationHeight := args[2].(*big.Int)
return &stakingtypes.MsgCancelUnbondingDelegation{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: validatorAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
CreationHeight: creationHeight.Int64(),
}, nil
}
func NewQueryValidatorsRequest(args []interface{}) (*stakingtypes.QueryValidatorsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
status := args[0].(string)
pagination := args[1].(PageRequest)
return &stakingtypes.QueryValidatorsRequest{
Status: status,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryValidatorRequest(args []interface{}) (*stakingtypes.QueryValidatorRequest, error) {
if len(args) != 1 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args))
}
validatorAddress := args[0].(string)
return &stakingtypes.QueryValidatorRequest{
ValidatorAddr: validatorAddress,
}, nil
}
func NewQueryValidatorDelegationsRequest(args []interface{}) (*stakingtypes.QueryValidatorDelegationsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
validatorAddr := args[0].(string)
pagination := args[1].(PageRequest)
return &stakingtypes.QueryValidatorDelegationsRequest{
ValidatorAddr: validatorAddr,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryValidatorUnbondingDelegationsRequest(args []interface{}) (*stakingtypes.QueryValidatorUnbondingDelegationsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
validatorAddr := args[0].(string)
pagination := args[1].(PageRequest)
return &stakingtypes.QueryValidatorUnbondingDelegationsRequest{
ValidatorAddr: validatorAddr,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryDelegationRequest(args []interface{}) (*stakingtypes.QueryDelegationRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegatorAddr := args[0].(string)
validatorAddr := args[1].(string)
return &stakingtypes.QueryDelegationRequest{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}, nil
}
func NewQueryUnbondingDelegationRequest(args []interface{}) (*stakingtypes.QueryUnbondingDelegationRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegatorAddr := args[0].(string)
validatorAddr := args[1].(string)
return &stakingtypes.QueryUnbondingDelegationRequest{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}, nil
}
func NewQueryDelegatorDelegationsRequest(args []interface{}) (*stakingtypes.QueryDelegatorDelegationsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegatorAddr := args[0].(string)
pagination := args[1].(PageRequest)
return &stakingtypes.QueryDelegatorDelegationsRequest{
DelegatorAddr: delegatorAddr,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryDelegatorUnbondingDelegationsRequest(args []interface{}) (*stakingtypes.QueryDelegatorUnbondingDelegationsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegatorAddr := args[0].(string)
pagination := args[1].(PageRequest)
return &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{
DelegatorAddr: delegatorAddr,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryRedelegationsRequest(args []interface{}) (*stakingtypes.QueryRedelegationsRequest, error) {
if len(args) != 4 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 4, len(args))
}
delegatorAddress := args[0].(string)
validatorSrcAddress := args[1].(string)
validatorDstAddress := args[2].(string)
pagination := args[3].(PageRequest)
return &stakingtypes.QueryRedelegationsRequest{
DelegatorAddr: delegatorAddress,
SrcValidatorAddr: validatorSrcAddress,
DstValidatorAddr: validatorDstAddress,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryDelegatorValidatorsRequest(args []interface{}) (*stakingtypes.QueryDelegatorValidatorsRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegatorAddr := args[0].(string)
pagination := args[1].(PageRequest)
return &stakingtypes.QueryDelegatorValidatorsRequest{
DelegatorAddr: delegatorAddr,
Pagination: convertQueryPageRequest(pagination),
}, nil
}
func NewQueryDelegatorValidatorRequest(args []interface{}) (*stakingtypes.QueryDelegatorValidatorRequest, error) {
if len(args) != 2 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
}
delegatorAddr := args[0].(string)
validatorAddr := args[1].(string)
return &stakingtypes.QueryDelegatorValidatorRequest{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}, nil
}
func NewQueryPoolRequest(args []interface{}) (*stakingtypes.QueryPoolRequest, error) {
if len(args) != 0 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 0, len(args))
}
return &stakingtypes.QueryPoolRequest{}, nil
}
func NewQueryParamsRequest(args []interface{}) (*stakingtypes.QueryParamsRequest, error) {
if len(args) != 0 {
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 0, len(args))
}
return &stakingtypes.QueryParamsRequest{}, nil
}

View File

@ -5,7 +5,7 @@ import (
"github.com/0glabs/0g-chain/app"
"github.com/0glabs/0g-chain/chaincfg"
dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners"
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
"github.com/0glabs/0g-chain/x/bep3/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/ethereum/go-ethereum/common"
@ -51,7 +51,7 @@ func GenSigner() *TestSigner {
addr, priv := emtests.NewAddrKey()
s.PrivKey = priv
s.Addr = addr
s.HexAddr = dasignersprecompile.ToLowerHexWithoutPrefix(s.Addr)
s.HexAddr = precopmiles_common.ToLowerHexWithoutPrefix(s.Addr)
s.Signer = emtests.NewSigner(priv)
return &s
}