mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 15:25:18 +00:00
Merge pull request #84 from 0glabs/staking-precompile
feat: staking precompile
This commit is contained in:
commit
76eebc57c1
5
.gitignore
vendored
5
.gitignore
vendored
@ -49,3 +49,8 @@ go.work.sum
|
||||
|
||||
# runtime
|
||||
run
|
||||
|
||||
# contracts
|
||||
precompiles/interfaces/build
|
||||
precompiles/interfaces/node_modules
|
||||
precompiles/interfaces/abis
|
10
app/app.go
10
app/app.go
@ -110,6 +110,7 @@ import (
|
||||
chainparams "github.com/0glabs/0g-chain/app/params"
|
||||
"github.com/0glabs/0g-chain/chaincfg"
|
||||
dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners"
|
||||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/bep3"
|
||||
bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper"
|
||||
@ -499,11 +500,18 @@ func NewApp(
|
||||
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
|
||||
// precopmiles
|
||||
precompiles := make(map[common.Address]vm.PrecompiledContract)
|
||||
// dasigners
|
||||
daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper)
|
||||
if err != nil {
|
||||
panic("initialize precompile failed")
|
||||
panic(fmt.Sprintf("initialize dasigners precompile failed: %v", err))
|
||||
}
|
||||
precompiles[daSignersPrecompile.Address()] = daSignersPrecompile
|
||||
// staking
|
||||
stakingPrecompile, err := stakingprecompile.NewStakingPrecompile(app.stakingKeeper)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("initialize staking precompile failed: %v", err))
|
||||
}
|
||||
precompiles[stakingPrecompile.Address()] = stakingPrecompile
|
||||
|
||||
app.evmKeeper = evmkeeper.NewKeeper(
|
||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
|
||||
|
@ -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"
|
||||
)
|
||||
|
18
precompiles/common/utils.go
Normal file
18
precompiles/common/utils.go
Normal 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)
|
||||
}
|
@ -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 {
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/0glabs/0g-chain/x/dasigners/v1/types"
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -23,7 +24,6 @@ import (
|
||||
"cosmossdk.io/math"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||
)
|
||||
|
||||
type DASignersTestSuite struct {
|
||||
@ -44,8 +44,7 @@ func (suite *DASignersTestSuite) AddDelegation(from string, to string, amount ma
|
||||
suite.Require().NoError(err)
|
||||
validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr)
|
||||
if !found {
|
||||
consPriv, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
consPriv := ed25519.GenPrivKey()
|
||||
newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
|
||||
suite.Require().NoError(err)
|
||||
validator = newValidator
|
||||
@ -73,8 +72,8 @@ func (suite *DASignersTestSuite) SetupTest() {
|
||||
suite.Assert().EqualValues(ok, true)
|
||||
suite.dasigners = precompile.(*dasignersprecompile.DASignersPrecompile)
|
||||
|
||||
suite.signerOne = testutil.GenSigner()
|
||||
suite.signerTwo = testutil.GenSigner()
|
||||
suite.signerOne = suite.GenSigner()
|
||||
suite.signerTwo = suite.GenSigner()
|
||||
abi, err := abi.JSON(strings.NewReader(dasignersprecompile.DASignersABI))
|
||||
suite.Assert().NoError(err)
|
||||
suite.abi = abi
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
18
precompiles/interfaces/.solhint.json
Normal file
18
precompiles/interfaces/.solhint.json
Normal 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"
|
||||
}
|
||||
}
|
88
precompiles/interfaces/contracts/IDASigners.sol
Normal file
88
precompiles/interfaces/contracts/IDASigners.sol
Normal 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);
|
||||
}
|
415
precompiles/interfaces/contracts/IStaking.sol
Normal file
415
precompiles/interfaces/contracts/IStaking.sol
Normal file
@ -0,0 +1,415 @@
|
||||
// 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, // 0gchaind tendermint show-validator
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
33
precompiles/interfaces/hardhat.config.ts
Normal file
33
precompiles/interfaces/hardhat.config.ts
Normal 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: "istanbul",
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
abiExporter: {
|
||||
path: "./abis",
|
||||
runOnCompile: true,
|
||||
clear: true,
|
||||
flat: true,
|
||||
format: "json",
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
27
precompiles/interfaces/package.json
Normal file
27
precompiles/interfaces/package.json
Normal 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"
|
||||
}
|
||||
}
|
3152
precompiles/interfaces/yarn.lock
Normal file
3152
precompiles/interfaces/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
1716
precompiles/staking/IStaking.abi
Normal file
1716
precompiles/staking/IStaking.abi
Normal file
File diff suppressed because it is too large
Load Diff
835
precompiles/staking/contract.go
Normal file
835
precompiles/staking/contract.go
Normal file
File diff suppressed because one or more lines are too long
5
precompiles/staking/errors.go
Normal file
5
precompiles/staking/errors.go
Normal file
@ -0,0 +1,5 @@
|
||||
package staking
|
||||
|
||||
const (
|
||||
ErrPubKeyInvalidLength = "public key with invalid length"
|
||||
)
|
223
precompiles/staking/query.go
Normal file
223
precompiles/staking/query.go
Normal 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))
|
||||
}
|
801
precompiles/staking/query_test.go
Normal file
801
precompiles/staking/query_test.go
Normal file
@ -0,0 +1,801 @@
|
||||
package staking_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
query "github.com/cosmos/cosmos-sdk/types/query"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func (s *StakingTestSuite) TestValidators() {
|
||||
method := stakingprecompile.StakingFunctionValidators
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func() []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
"",
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
validators := out[0].([]stakingprecompile.Validator)
|
||||
paginationResult := out[1].(stakingprecompile.PageResponse)
|
||||
s.Assert().EqualValues(3, len(validators))
|
||||
s.Assert().EqualValues(3, paginationResult.Total)
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
s.AddDelegation(s.signerOne.HexAddr, s.signerTwo.HexAddr, sdk.NewIntFromUint64(1000000))
|
||||
|
||||
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestValidator() {
|
||||
method := stakingprecompile.StakingFunctionValidator
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(operatorAddress string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(operatorAddress string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
operatorAddress,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
validator := out[0].(stakingprecompile.Validator)
|
||||
s.Require().EqualValues(common.HexToAddress(validator.OperatorAddress), common.BytesToAddress(operatorAddress.Bytes()))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestValidatorDelegations() {
|
||||
method := stakingprecompile.StakingFunctionValidatorDelegations
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(operatorAddress string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(operatorAddress string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
operatorAddress,
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
delegations := out[0].([]stakingprecompile.DelegationResponse)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
s.Require().EqualValues(len(delegations), len(d))
|
||||
// jsonData, _ := json.MarshalIndent(delegations, "", " ")
|
||||
// fmt.Printf("delegations: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestValidatorUnbondingDelegations() {
|
||||
method := stakingprecompile.StakingFunctionValidatorUnbondingDelegations
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(operatorAddress string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(operatorAddress string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
operatorAddress,
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
unbonding := out[0].([]stakingprecompile.UnbondingDelegation)
|
||||
s.Require().EqualValues(len(unbonding), 1)
|
||||
// jsonData, _ := json.MarshalIndent(unbonding, "", " ")
|
||||
// fmt.Printf("delegations: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1))
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestDelegation() {
|
||||
method := stakingprecompile.StakingFunctionDelegation
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr, valAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr, valAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
valAddr,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
d := out[0].(stakingprecompile.Delegation)
|
||||
b := out[1].(*big.Int)
|
||||
_ = d
|
||||
_ = b
|
||||
/*
|
||||
jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
fmt.Printf("delegation: %s\n", string(jsonData))
|
||||
fmt.Printf("balance: %v\n", b)
|
||||
*/
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestUnbondingDelegation() {
|
||||
method := stakingprecompile.StakingFunctionUnbondingDelegation
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr, valAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr, valAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
valAddr,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
u := out[0].(stakingprecompile.UnbondingDelegation)
|
||||
_ = u
|
||||
// jsonData, _ := json.MarshalIndent(u, "", " ")
|
||||
// fmt.Printf("delegation: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1))
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestDelegatorDelegations() {
|
||||
method := stakingprecompile.StakingFunctionDelegatorDelegations
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
d := out[0].([]stakingprecompile.DelegationResponse)
|
||||
paginationResult := out[1].(stakingprecompile.PageResponse)
|
||||
s.Assert().EqualValues(1, len(d))
|
||||
s.Assert().EqualValues(1, paginationResult.Total)
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("delegation: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestDelegatorUnbondingDelegations() {
|
||||
method := stakingprecompile.StakingFunctionDelegatorUnbondingDelegations
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
d := out[0].([]stakingprecompile.UnbondingDelegation)
|
||||
paginationResult := out[1].(stakingprecompile.PageResponse)
|
||||
s.Assert().EqualValues(1, len(d))
|
||||
s.Assert().EqualValues(1, paginationResult.Total)
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("delegation: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1))
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestRedelegations() {
|
||||
method := stakingprecompile.StakingFunctionRedelegations
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr, srcValAddr, dstValAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr, srcValAddr, dstValAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
srcValAddr,
|
||||
dstValAddr,
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
d := out[0].([]stakingprecompile.RedelegationResponse)
|
||||
paginationResult := out[1].(stakingprecompile.PageResponse)
|
||||
s.Assert().EqualValues(1, len(d))
|
||||
s.Assert().EqualValues(1, paginationResult.Total)
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("redelegations: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
// setup redelegations
|
||||
s.setupValidator(s.signerOne)
|
||||
_, err = s.stakingKeeper.BeginRedelegation(s.Ctx, delAddr, operatorAddress, s.signerOne.ValAddr, sdk.NewDec(1))
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String(), s.signerOne.ValAddr.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestDelegatorValidators() {
|
||||
method := stakingprecompile.StakingFunctionDelegatorValidators
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
query.PageRequest{
|
||||
Limit: 10,
|
||||
CountTotal: true,
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
v := out[0].([]stakingprecompile.Validator)
|
||||
paginationResult := out[1].(stakingprecompile.PageResponse)
|
||||
s.Assert().EqualValues(1, len(v))
|
||||
s.Assert().EqualValues(1, paginationResult.Total)
|
||||
// jsonData, _ := json.MarshalIndent(v, "", " ")
|
||||
// fmt.Printf("validators: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestDelegatorValidator() {
|
||||
method := stakingprecompile.StakingFunctionDelegatorValidator
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(delAddr, valAddr string) []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(delAddr, valAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
delAddr,
|
||||
valAddr,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
v := out[0].(stakingprecompile.Validator)
|
||||
_ = v
|
||||
// jsonData, _ := json.MarshalIndent(v, "", " ")
|
||||
// fmt.Printf("validators: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress)
|
||||
delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestPool() {
|
||||
method := stakingprecompile.StakingFunctionPool
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func() []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
bonded := out[0].(*big.Int)
|
||||
unbonded := out[0].(*big.Int)
|
||||
s.Assert().Equal(bonded.Int64(), int64(0))
|
||||
s.Assert().Equal(unbonded.Int64(), int64(0))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
|
||||
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestParams() {
|
||||
method := stakingprecompile.StakingFunctionParams
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() []byte
|
||||
postCheck func(bz []byte)
|
||||
gas uint64
|
||||
expErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func() []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
func(data []byte) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
params := out[0].(stakingprecompile.Params)
|
||||
_ = params
|
||||
// jsonData, _ := json.MarshalIndent(params, "", " ")
|
||||
// fmt.Printf("params: %s\n", string(jsonData))
|
||||
},
|
||||
100000,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
|
||||
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.errContains)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(bz)
|
||||
tc.postCheck(bz)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
148
precompiles/staking/staking.go
Normal file
148
precompiles/staking/staking.go
Normal 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
|
||||
}
|
145
precompiles/staking/staking_test.go
Normal file
145
precompiles/staking/staking_test.go
Normal file
@ -0,0 +1,145 @@
|
||||
package staking_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
|
||||
"github.com/0glabs/0g-chain/precompiles/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type StakingTestSuite struct {
|
||||
testutil.PrecompileTestSuite
|
||||
|
||||
abi abi.ABI
|
||||
addr common.Address
|
||||
staking *stakingprecompile.StakingPrecompile
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
signerOne *testutil.TestSigner
|
||||
signerTwo *testutil.TestSigner
|
||||
}
|
||||
|
||||
func (suite *StakingTestSuite) SetupTest() {
|
||||
suite.PrecompileTestSuite.SetupTest()
|
||||
|
||||
suite.stakingKeeper = suite.App.GetStakingKeeper()
|
||||
|
||||
suite.addr = common.HexToAddress(stakingprecompile.PrecompileAddress)
|
||||
|
||||
precompiles := suite.EvmKeeper.GetPrecompiles()
|
||||
precompile, ok := precompiles[suite.addr]
|
||||
suite.Assert().EqualValues(ok, true)
|
||||
|
||||
suite.staking = precompile.(*stakingprecompile.StakingPrecompile)
|
||||
|
||||
suite.signerOne = suite.GenSigner()
|
||||
suite.signerTwo = suite.GenSigner()
|
||||
|
||||
abi, err := abi.JSON(strings.NewReader(stakingprecompile.StakingABI))
|
||||
suite.Assert().NoError(err)
|
||||
suite.abi = abi
|
||||
}
|
||||
|
||||
func (suite *StakingTestSuite) AddDelegation(from string, to string, amount math.Int) {
|
||||
accAddr, err := sdk.AccAddressFromHexUnsafe(from)
|
||||
suite.Require().NoError(err)
|
||||
valAddr, err := sdk.ValAddressFromHex(to)
|
||||
suite.Require().NoError(err)
|
||||
validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr)
|
||||
if !found {
|
||||
consPriv := ed25519.GenPrivKey()
|
||||
newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
|
||||
suite.Require().NoError(err)
|
||||
validator = newValidator
|
||||
}
|
||||
validator.Tokens = validator.Tokens.Add(amount)
|
||||
validator.DelegatorShares = validator.DelegatorShares.Add(amount.ToLegacyDec())
|
||||
suite.StakingKeeper.SetValidator(suite.Ctx, validator)
|
||||
bonded := suite.stakingKeeper.GetDelegatorBonded(suite.Ctx, accAddr)
|
||||
suite.StakingKeeper.SetDelegation(suite.Ctx, stakingtypes.Delegation{
|
||||
DelegatorAddress: accAddr.String(),
|
||||
ValidatorAddress: valAddr.String(),
|
||||
Shares: bonded.Add(amount).ToLegacyDec(),
|
||||
})
|
||||
}
|
||||
|
||||
func (suite *StakingTestSuite) setupValidator(signer *testutil.TestSigner) {
|
||||
method := stakingprecompile.StakingFunctionCreateValidator
|
||||
description := stakingprecompile.Description{
|
||||
Moniker: "test node",
|
||||
Identity: "test node identity",
|
||||
Website: "http://test.node.com",
|
||||
SecurityContact: "test node security contract",
|
||||
Details: "test node details",
|
||||
}
|
||||
commission := stakingprecompile.CommissionRates{
|
||||
Rate: math.LegacyOneDec().BigInt(),
|
||||
MaxRate: math.LegacyOneDec().BigInt(),
|
||||
MaxChangeRate: math.LegacyOneDec().BigInt(),
|
||||
}
|
||||
minSelfDelegation := big.NewInt(1)
|
||||
pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g="
|
||||
value := big.NewInt(100000000)
|
||||
input, err := suite.abi.Pack(
|
||||
method,
|
||||
description,
|
||||
commission,
|
||||
minSelfDelegation,
|
||||
pubkey,
|
||||
value,
|
||||
)
|
||||
suite.Assert().NoError(err)
|
||||
_, err = suite.runTx(input, signer, 10000000)
|
||||
suite.Assert().NoError(err)
|
||||
_, err = suite.stakingKeeper.ApplyAndReturnValidatorSetUpdates(suite.Ctx)
|
||||
suite.Assert().NoError(err)
|
||||
}
|
||||
|
||||
func (suite *StakingTestSuite) firstBondedValidator() (sdk.ValAddress, error) {
|
||||
validators := suite.stakingKeeper.GetValidators(suite.Ctx, 10)
|
||||
for _, v := range validators {
|
||||
if v.IsBonded() {
|
||||
return sdk.ValAddressFromBech32(v.OperatorAddress)
|
||||
}
|
||||
}
|
||||
return nil, errors.New("no bonded validator")
|
||||
}
|
||||
|
||||
func (suite *StakingTestSuite) runTx(input []byte, signer *testutil.TestSigner, gas uint64) ([]byte, error) {
|
||||
contract := vm.NewPrecompile(vm.AccountRef(signer.Addr), vm.AccountRef(suite.addr), big.NewInt(0), gas)
|
||||
contract.Input = input
|
||||
|
||||
msgEthereumTx := evmtypes.NewTx(suite.EvmKeeper.ChainID(), 0, &suite.addr, big.NewInt(0), gas, big.NewInt(0), big.NewInt(0), big.NewInt(0), input, nil)
|
||||
msgEthereumTx.From = signer.HexAddr
|
||||
err := msgEthereumTx.Sign(suite.EthSigner, signer.Signer)
|
||||
suite.Assert().NoError(err, "failed to sign Ethereum message")
|
||||
|
||||
proposerAddress := suite.Ctx.BlockHeader().ProposerAddress
|
||||
cfg, err := suite.EvmKeeper.EVMConfig(suite.Ctx, proposerAddress, suite.EvmKeeper.ChainID())
|
||||
suite.Assert().NoError(err, "failed to instantiate EVM config")
|
||||
|
||||
msg, err := msgEthereumTx.AsMessage(suite.EthSigner, big.NewInt(0))
|
||||
suite.Assert().NoError(err, "failed to instantiate Ethereum message")
|
||||
|
||||
evm := suite.EvmKeeper.NewEVM(suite.Ctx, msg, cfg, nil, suite.Statedb)
|
||||
precompiles := suite.EvmKeeper.GetPrecompiles()
|
||||
evm.WithPrecompiles(precompiles, []common.Address{suite.addr})
|
||||
|
||||
return suite.staking.Run(evm, contract, false)
|
||||
}
|
||||
|
||||
func TestKeeperSuite(t *testing.T) {
|
||||
suite.Run(t, new(StakingTestSuite))
|
||||
}
|
163
precompiles/staking/tx.go
Normal file
163
precompiles/staking/tx.go
Normal file
@ -0,0 +1,163 @@
|
||||
package staking
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
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
|
||||
response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).BeginRedelegate(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// emit events
|
||||
return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix()))
|
||||
}
|
||||
|
||||
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
|
||||
response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Undelegate(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// emit events
|
||||
return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix()))
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
485
precompiles/staking/tx_test.go
Normal file
485
precompiles/staking/tx_test.go
Normal file
@ -0,0 +1,485 @@
|
||||
package staking_test
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/evmos/ethermint/x/evm/statedb"
|
||||
)
|
||||
|
||||
func (s *StakingTestSuite) TestCreateValidator() {
|
||||
method := stakingprecompile.StakingFunctionCreateValidator
|
||||
description := stakingprecompile.Description{
|
||||
Moniker: "test node",
|
||||
Identity: "test node identity",
|
||||
Website: "http://test.node.com",
|
||||
SecurityContact: "test node security contract",
|
||||
Details: "test node details",
|
||||
}
|
||||
commission := stakingprecompile.CommissionRates{
|
||||
Rate: math.LegacyOneDec().BigInt(),
|
||||
MaxRate: math.LegacyOneDec().BigInt(),
|
||||
MaxChangeRate: math.LegacyOneDec().BigInt(),
|
||||
}
|
||||
minSelfDelegation := big.NewInt(1)
|
||||
pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g="
|
||||
value := big.NewInt(100000000)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() []byte
|
||||
gas uint64
|
||||
callerAddress *common.Address
|
||||
postCheck func(data []byte)
|
||||
expError bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"fail - ErrPubKeyInvalidLength",
|
||||
func() []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
description,
|
||||
commission,
|
||||
minSelfDelegation,
|
||||
s.signerOne.HexAddr,
|
||||
value,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func([]byte) {},
|
||||
true,
|
||||
stakingprecompile.ErrPubKeyInvalidLength,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
description,
|
||||
commission,
|
||||
minSelfDelegation,
|
||||
pubkey,
|
||||
value,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func(data []byte) {},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
|
||||
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
|
||||
s.stakingKeeper.ApplyAndReturnValidatorSetUpdates(s.Ctx)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().ErrorContains(err, tc.errContains)
|
||||
s.Require().Empty(bz)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
// query the validator in the staking keeper
|
||||
validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NotNil(validator, "expected validator not to be nil")
|
||||
tc.postCheck(bz)
|
||||
|
||||
isBonded := validator.IsBonded()
|
||||
s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", true, isBonded)
|
||||
|
||||
consPubKey, err := validator.ConsPubKey()
|
||||
s.Require().NoError(err)
|
||||
consPubKeyBase64 := base64.StdEncoding.EncodeToString(consPubKey.Bytes())
|
||||
s.Require().Equal(pubkey, consPubKeyBase64, "expected validator pubkey to be %s; got %s", pubkey, consPubKeyBase64)
|
||||
|
||||
operator := validator.GetOperator()
|
||||
s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator)
|
||||
|
||||
commissionRate := validator.GetCommission()
|
||||
s.Require().Equal(commission.Rate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", commission.Rate.String(), commissionRate.String())
|
||||
|
||||
valMinSelfDelegation := validator.GetMinSelfDelegation()
|
||||
s.Require().Equal(minSelfDelegation.String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String())
|
||||
|
||||
moniker := validator.GetMoniker()
|
||||
s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker)
|
||||
|
||||
jailed := validator.IsJailed()
|
||||
s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestEditValidator() {
|
||||
method := stakingprecompile.StakingFunctionEditValidator
|
||||
description := stakingprecompile.Description{
|
||||
Moniker: "test node",
|
||||
Identity: "test node identity",
|
||||
Website: "http://test.node.com",
|
||||
SecurityContact: "test node security contract",
|
||||
Details: "test node details",
|
||||
}
|
||||
newRate := math.LegacyOneDec().BigInt()
|
||||
newRate.Div(newRate, big.NewInt(2))
|
||||
minSelfDelegation := big.NewInt(2)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() []byte
|
||||
gas uint64
|
||||
callerAddress *common.Address
|
||||
postCheck func(data []byte)
|
||||
expError bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func() []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
description,
|
||||
stakingprecompile.NullableUint{
|
||||
IsNull: false,
|
||||
Value: newRate,
|
||||
},
|
||||
stakingprecompile.NullableUint{
|
||||
IsNull: true,
|
||||
Value: math.LegacyOneDec().BigInt(),
|
||||
},
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func(data []byte) {},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
s.setupValidator(s.signerOne)
|
||||
// move block time forward
|
||||
s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100))
|
||||
s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes())))
|
||||
|
||||
bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().ErrorContains(err, tc.errContains)
|
||||
s.Require().Empty(bz)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
// query the validator in the staking keeper
|
||||
validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NotNil(validator, "expected validator not to be nil")
|
||||
tc.postCheck(bz)
|
||||
|
||||
isBonded := validator.IsBonded()
|
||||
s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", false, isBonded)
|
||||
|
||||
operator := validator.GetOperator()
|
||||
s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator)
|
||||
|
||||
commissionRate := validator.GetCommission()
|
||||
s.Require().Equal(newRate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", newRate.String(), commissionRate.String())
|
||||
|
||||
valMinSelfDelegation := validator.GetMinSelfDelegation()
|
||||
s.Require().Equal(big.NewInt(1).String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String())
|
||||
|
||||
moniker := validator.GetMoniker()
|
||||
s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker)
|
||||
|
||||
jailed := validator.IsJailed()
|
||||
s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestDelegate() {
|
||||
method := stakingprecompile.StakingFunctionDelegate
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(valAddr string) []byte
|
||||
gas uint64
|
||||
callerAddress *common.Address
|
||||
postCheck func(valAddr sdk.ValAddress)
|
||||
expError bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(valAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
valAddr,
|
||||
big.NewInt(1000000),
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func(valAddr sdk.ValAddress) {
|
||||
d, found := s.stakingKeeper.GetDelegation(s.Ctx, s.signerOne.AccAddr, valAddr)
|
||||
s.Assert().EqualValues(found, true)
|
||||
s.Assert().EqualValues(d.ValidatorAddress, valAddr.String())
|
||||
s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String())
|
||||
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("delegation: %s\n", string(jsonData))
|
||||
},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().ErrorContains(err, tc.errContains)
|
||||
s.Require().Empty(bz)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
tc.postCheck(operatorAddress)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestBeginRedelegate() {
|
||||
method := stakingprecompile.StakingFunctionBeginRedelegate
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(srcAddr, dstAddr string) []byte
|
||||
gas uint64
|
||||
callerAddress *common.Address
|
||||
postCheck func(data []byte, srcAddr, dstAddr sdk.ValAddress)
|
||||
expError bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(srcAddr, dstAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
srcAddr,
|
||||
dstAddr,
|
||||
big.NewInt(1000000),
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func(data []byte, srcAddr, dstAddr sdk.ValAddress) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
|
||||
d, found := s.stakingKeeper.GetRedelegation(s.Ctx, s.signerOne.AccAddr, srcAddr, dstAddr)
|
||||
s.Assert().EqualValues(found, true)
|
||||
s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String())
|
||||
s.Assert().EqualValues(d.ValidatorSrcAddress, srcAddr.String())
|
||||
s.Assert().EqualValues(d.ValidatorDstAddress, dstAddr.String())
|
||||
|
||||
completionTime := out[0].(*big.Int)
|
||||
params := s.stakingKeeper.GetParams(s.Ctx)
|
||||
s.Assert().EqualValues(completionTime.Int64(), s.Ctx.BlockHeader().Time.Add(params.UnbondingTime).UTC().Unix())
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("redelegation: %s\n", string(jsonData))
|
||||
},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
operatorAddress, err := s.firstBondedValidator()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// move block time forward
|
||||
s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100))
|
||||
s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes())))
|
||||
|
||||
s.setupValidator(s.signerOne)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String(), operatorAddress.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().ErrorContains(err, tc.errContains)
|
||||
s.Require().Empty(bz)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
tc.postCheck(bz, s.signerOne.ValAddr, operatorAddress)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestUndelegate() {
|
||||
method := stakingprecompile.StakingFunctionUndelegate
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(valAddr string) []byte
|
||||
gas uint64
|
||||
callerAddress *common.Address
|
||||
postCheck func(data []byte, valAddr sdk.ValAddress)
|
||||
expError bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(valAddr string) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
valAddr,
|
||||
big.NewInt(1000000),
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func(data []byte, valAddr sdk.ValAddress) {
|
||||
out, err := s.abi.Methods[method].Outputs.Unpack(data)
|
||||
s.Require().NoError(err, "failed to unpack output")
|
||||
|
||||
d, found := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, valAddr)
|
||||
s.Assert().EqualValues(found, true)
|
||||
s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String())
|
||||
s.Assert().EqualValues(d.ValidatorAddress, valAddr.String())
|
||||
|
||||
completionTime := out[0].(*big.Int)
|
||||
params := s.stakingKeeper.GetParams(s.Ctx)
|
||||
s.Assert().EqualValues(completionTime.Int64(), s.Ctx.BlockHeader().Time.Add(params.UnbondingTime).UTC().Unix())
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("redelegation: %s\n", string(jsonData))
|
||||
},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
|
||||
// move block time forward
|
||||
s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100))
|
||||
s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes())))
|
||||
|
||||
s.setupValidator(s.signerOne)
|
||||
|
||||
bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String()), s.signerOne, 10000000)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().ErrorContains(err, tc.errContains)
|
||||
s.Require().Empty(bz)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
tc.postCheck(bz, s.signerOne.ValAddr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StakingTestSuite) TestCancelUnbondingDelegation() {
|
||||
method := stakingprecompile.StakingFunctionCancelUnbondingDelegation
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func(valAddr string, height *big.Int) []byte
|
||||
gas uint64
|
||||
callerAddress *common.Address
|
||||
postCheck func(valAddr sdk.ValAddress)
|
||||
expError bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
"success",
|
||||
func(valAddr string, height *big.Int) []byte {
|
||||
input, err := s.abi.Pack(
|
||||
method,
|
||||
valAddr,
|
||||
big.NewInt(1),
|
||||
height,
|
||||
)
|
||||
s.Assert().NoError(err)
|
||||
return input
|
||||
},
|
||||
200000,
|
||||
nil,
|
||||
func(valAddr sdk.ValAddress) {
|
||||
_, found := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, valAddr)
|
||||
s.Assert().EqualValues(found, false)
|
||||
// jsonData, _ := json.MarshalIndent(d, "", " ")
|
||||
// fmt.Printf("redelegation: %s\n", string(jsonData))
|
||||
},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.Run(tc.name, func() {
|
||||
s.SetupTest()
|
||||
|
||||
// move block time forward
|
||||
s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100))
|
||||
s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes())))
|
||||
|
||||
s.setupValidator(s.signerOne)
|
||||
// unbond
|
||||
_, err := s.stakingKeeper.Undelegate(s.Ctx, s.signerOne.AccAddr, s.signerOne.ValAddr, sdk.NewDec(1))
|
||||
s.Require().NoError(err)
|
||||
|
||||
u, _ := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, s.signerOne.ValAddr)
|
||||
height := u.Entries[0].CreationHeight
|
||||
|
||||
bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String(), big.NewInt(height)), s.signerOne, 10000000)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().ErrorContains(err, tc.errContains)
|
||||
s.Require().Empty(bz)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
tc.postCheck(s.signerOne.ValAddr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
602
precompiles/staking/types.go
Normal file
602
precompiles/staking/types.go
Normal file
@ -0,0 +1,602 @@
|
||||
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 {
|
||||
if pagination == nil {
|
||||
return PageResponse{
|
||||
NextKey: make([]byte, 0),
|
||||
Total: 1,
|
||||
}
|
||||
}
|
||||
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)
|
||||
msg := &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)},
|
||||
}
|
||||
return msg, msg.ValidateBasic()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
msg := &stakingtypes.MsgEditValidator{
|
||||
Description: convertStakingDescription(description),
|
||||
CommissionRate: commissionRate,
|
||||
ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(),
|
||||
MinSelfDelegation: minSelfDelegation,
|
||||
}
|
||||
return msg, msg.ValidateBasic()
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
msg := &stakingtypes.MsgDelegate{
|
||||
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
|
||||
ValidatorAddress: validatorAddress,
|
||||
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
|
||||
}
|
||||
return msg, msg.ValidateBasic()
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
msg := &stakingtypes.MsgBeginRedelegate{
|
||||
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
|
||||
ValidatorSrcAddress: validatorSrcAddress,
|
||||
ValidatorDstAddress: validatorDstAddress,
|
||||
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
|
||||
}
|
||||
return msg, msg.ValidateBasic()
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
msg := &stakingtypes.MsgUndelegate{
|
||||
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
|
||||
ValidatorAddress: validatorAddress,
|
||||
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
|
||||
}
|
||||
return msg, msg.ValidateBasic()
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
msg := &stakingtypes.MsgCancelUnbondingDelegation{
|
||||
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
|
||||
ValidatorAddress: validatorAddress,
|
||||
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
|
||||
CreationHeight: creationHeight.Int64(),
|
||||
}
|
||||
return msg, msg.ValidateBasic()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
@ -44,15 +46,25 @@ type TestSigner struct {
|
||||
HexAddr string
|
||||
PrivKey cryptotypes.PrivKey
|
||||
Signer keyring.Signer
|
||||
ValAddr sdk.ValAddress
|
||||
AccAddr sdk.AccAddress
|
||||
}
|
||||
|
||||
func GenSigner() *TestSigner {
|
||||
func (suite *PrecompileTestSuite) GenSigner() *TestSigner {
|
||||
var s 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)
|
||||
valAddr, _ := sdk.ValAddressFromHex(s.HexAddr)
|
||||
accAddr, _ := sdk.AccAddressFromHexUnsafe(s.HexAddr)
|
||||
s.ValAddr = valAddr
|
||||
s.AccAddr = accAddr
|
||||
|
||||
// 10000 a0gi for test
|
||||
suite.App.GetBankKeeper().MintCoins(suite.Ctx, "mint", sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000))))
|
||||
suite.App.GetBankKeeper().SendCoinsFromModuleToAccount(suite.Ctx, "mint", accAddr, sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000))))
|
||||
return &s
|
||||
}
|
||||
|
||||
@ -70,7 +82,7 @@ func (suite *PrecompileTestSuite) SetupTest() {
|
||||
hexAddr := strings.ToLower(crypto.PubkeyToAddress(key.PublicKey).Hex()[2:])
|
||||
valAddr, err := sdk.ValAddressFromHex(hexAddr)
|
||||
suite.Assert().NoError(err)
|
||||
suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress})
|
||||
suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress, Time: time.Now()})
|
||||
newValidator, err := stakingtypes.NewValidator(valAddr, privkey.PubKey(), stakingtypes.Description{})
|
||||
suite.Assert().NoError(err)
|
||||
err = suite.StakingKeeper.SetValidatorByConsAddr(suite.Ctx, newValidator)
|
||||
|
Loading…
Reference in New Issue
Block a user