mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-27 00:35:18 +00:00
Compare commits
6 Commits
f2abb98d6c
...
76eebc57c1
Author | SHA1 | Date | |
---|---|---|---|
|
76eebc57c1 | ||
|
100bad3471 | ||
|
605a71e826 | ||
|
1602c96a40 | ||
|
759d08a6eb | ||
|
e308e44dd6 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -49,3 +49,8 @@ go.work.sum
|
|||||||
|
|
||||||
# runtime
|
# runtime
|
||||||
run
|
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"
|
chainparams "github.com/0glabs/0g-chain/app/params"
|
||||||
"github.com/0glabs/0g-chain/chaincfg"
|
"github.com/0glabs/0g-chain/chaincfg"
|
||||||
dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners"
|
dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners"
|
||||||
|
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
|
||||||
|
|
||||||
"github.com/0glabs/0g-chain/x/bep3"
|
"github.com/0glabs/0g-chain/x/bep3"
|
||||||
bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper"
|
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)
|
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
|
||||||
// precopmiles
|
// precopmiles
|
||||||
precompiles := make(map[common.Address]vm.PrecompiledContract)
|
precompiles := make(map[common.Address]vm.PrecompiledContract)
|
||||||
|
// dasigners
|
||||||
daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper)
|
daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("initialize precompile failed")
|
panic(fmt.Sprintf("initialize dasigners precompile failed: %v", err))
|
||||||
}
|
}
|
||||||
precompiles[daSignersPrecompile.Address()] = daSignersPrecompile
|
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(
|
app.evmKeeper = evmkeeper.NewKeeper(
|
||||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
|
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
|
||||||
|
@ -3,4 +3,5 @@ package common
|
|||||||
const (
|
const (
|
||||||
ErrGetStateDB = "get EVM StateDB failed"
|
ErrGetStateDB = "get EVM StateDB failed"
|
||||||
ErrInvalidNumberOfArgs = "invalid number of arguments; expected %d; got: %d"
|
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)
|
bz, err = d.RegisteredEpoch(ctx, evm, method, args)
|
||||||
// txs
|
// txs
|
||||||
case DASignersFunctionRegisterSigner:
|
case DASignersFunctionRegisterSigner:
|
||||||
bz, err = d.RegisterSigner(ctx, evm, stateDB, method, args)
|
bz, err = d.RegisterSigner(ctx, evm, stateDB, contract, method, args)
|
||||||
case DASignersFunctionRegisterNextEpoch:
|
case DASignersFunctionRegisterNextEpoch:
|
||||||
bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, method, args)
|
bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, contract, method, args)
|
||||||
case DASignersFunctionUpdateSocket:
|
case DASignersFunctionUpdateSocket:
|
||||||
bz, err = d.UpdateSocket(ctx, evm, stateDB, method, args)
|
bz, err = d.UpdateSocket(ctx, evm, stateDB, contract, method, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/0glabs/0g-chain/x/dasigners/v1/types"
|
"github.com/0glabs/0g-chain/x/dasigners/v1/types"
|
||||||
abci "github.com/cometbft/cometbft/abci/types"
|
abci "github.com/cometbft/cometbft/abci/types"
|
||||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -23,7 +24,6 @@ import (
|
|||||||
"cosmossdk.io/math"
|
"cosmossdk.io/math"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DASignersTestSuite struct {
|
type DASignersTestSuite struct {
|
||||||
@ -44,8 +44,7 @@ func (suite *DASignersTestSuite) AddDelegation(from string, to string, amount ma
|
|||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr)
|
validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr)
|
||||||
if !found {
|
if !found {
|
||||||
consPriv, err := ethsecp256k1.GenerateKey()
|
consPriv := ed25519.GenPrivKey()
|
||||||
suite.Require().NoError(err)
|
|
||||||
newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
|
newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{})
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
validator = newValidator
|
validator = newValidator
|
||||||
@ -73,8 +72,8 @@ func (suite *DASignersTestSuite) SetupTest() {
|
|||||||
suite.Assert().EqualValues(ok, true)
|
suite.Assert().EqualValues(ok, true)
|
||||||
suite.dasigners = precompile.(*dasignersprecompile.DASignersPrecompile)
|
suite.dasigners = precompile.(*dasignersprecompile.DASignersPrecompile)
|
||||||
|
|
||||||
suite.signerOne = testutil.GenSigner()
|
suite.signerOne = suite.GenSigner()
|
||||||
suite.signerTwo = testutil.GenSigner()
|
suite.signerTwo = suite.GenSigner()
|
||||||
abi, err := abi.JSON(strings.NewReader(dasignersprecompile.DASignersABI))
|
abi, err := abi.JSON(strings.NewReader(dasignersprecompile.DASignersABI))
|
||||||
suite.Assert().NoError(err)
|
suite.Assert().NoError(err)
|
||||||
suite.abi = abi
|
suite.abi = abi
|
||||||
|
@ -62,7 +62,7 @@ func (d *DASignersPrecompile) IsSigner(ctx sdk.Context, _ *vm.EVM, method *abi.M
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args))
|
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)
|
_, found, err := d.dasignersKeeper.GetSigner(ctx, account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -74,7 +74,7 @@ func (d *DASignersPrecompile) RegisteredEpoch(ctx sdk.Context, _ *vm.EVM, method
|
|||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
|
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()
|
epoch := args[1].(*big.Int).Uint64()
|
||||||
_, found, err := d.dasignersKeeper.GetRegistration(ctx, epoch, account)
|
_, found, err := d.dasignersKeeper.GetRegistration(ctx, epoch, account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,18 +7,30 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/evmos/ethermint/x/evm/statedb"
|
"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)
|
msg, err := NewMsgRegisterSigner(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// validation
|
// validation
|
||||||
sender := ToLowerHexWithoutPrefix(evm.Origin)
|
sender := precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin)
|
||||||
if sender != msg.Signer.Account {
|
if sender != msg.Signer.Account {
|
||||||
return nil, fmt.Errorf(ErrInvalidSender, 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
|
// execute
|
||||||
_, err = d.dasignersKeeper.RegisterSigner(sdk.WrapSDKContext(ctx), msg)
|
_, err = d.dasignersKeeper.RegisterSigner(sdk.WrapSDKContext(ctx), msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -32,11 +44,22 @@ func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, state
|
|||||||
return method.Outputs.Pack()
|
return method.Outputs.Pack()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) {
|
func (d *DASignersPrecompile) RegisterNextEpoch(
|
||||||
msg, err := NewMsgRegisterNextEpoch(args, ToLowerHexWithoutPrefix(evm.Origin))
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// validation
|
||||||
|
if contract.CallerAddress != evm.Origin {
|
||||||
|
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
|
||||||
|
}
|
||||||
// execute
|
// execute
|
||||||
_, err = d.dasignersKeeper.RegisterNextEpoch(sdk.WrapSDKContext(ctx), msg)
|
_, err = d.dasignersKeeper.RegisterNextEpoch(sdk.WrapSDKContext(ctx), msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -45,11 +68,22 @@ func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, st
|
|||||||
return method.Outputs.Pack()
|
return method.Outputs.Pack()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DASignersPrecompile) UpdateSocket(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) {
|
func (d *DASignersPrecompile) UpdateSocket(
|
||||||
msg, err := NewMsgUpdateSocket(args, ToLowerHexWithoutPrefix(evm.Origin))
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// validation
|
||||||
|
if contract.CallerAddress != evm.Origin {
|
||||||
|
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
|
||||||
|
}
|
||||||
// execute
|
// execute
|
||||||
_, err = d.dasignersKeeper.UpdateSocket(sdk.WrapSDKContext(ctx), msg)
|
_, err = d.dasignersKeeper.UpdateSocket(sdk.WrapSDKContext(ctx), msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,7 +3,6 @@ package dasigners
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
|
||||||
|
|
||||||
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
|
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
|
||||||
dasignerstypes "github.com/0glabs/0g-chain/x/dasigners/v1/types"
|
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)),
|
Accounts: make([]string, len(accounts)),
|
||||||
}
|
}
|
||||||
for i, account := range accounts {
|
for i, account := range accounts {
|
||||||
req.Accounts[i] = ToLowerHexWithoutPrefix(account)
|
req.Accounts[i] = precopmiles_common.ToLowerHexWithoutPrefix(account)
|
||||||
}
|
}
|
||||||
return &req, nil
|
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) {
|
func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner, error) {
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
|
return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args))
|
||||||
@ -151,7 +146,7 @@ func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner
|
|||||||
signer := args[0].(IDASignersSignerDetail)
|
signer := args[0].(IDASignersSignerDetail)
|
||||||
return &dasignerstypes.MsgRegisterSigner{
|
return &dasignerstypes.MsgRegisterSigner{
|
||||||
Signer: &dasignerstypes.Signer{
|
Signer: &dasignerstypes.Signer{
|
||||||
Account: ToLowerHexWithoutPrefix(signer.Signer),
|
Account: precopmiles_common.ToLowerHexWithoutPrefix(signer.Signer),
|
||||||
Socket: signer.Socket,
|
Socket: signer.Socket,
|
||||||
PubkeyG1: SerializeG1(signer.PkG1),
|
PubkeyG1: SerializeG1(signer.PkG1),
|
||||||
PubkeyG2: SerializeG2(signer.PkG2),
|
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
|
package testutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/0glabs/0g-chain/app"
|
"github.com/0glabs/0g-chain/app"
|
||||||
"github.com/0glabs/0g-chain/chaincfg"
|
"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/0glabs/0g-chain/x/bep3/types"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -44,15 +46,25 @@ type TestSigner struct {
|
|||||||
HexAddr string
|
HexAddr string
|
||||||
PrivKey cryptotypes.PrivKey
|
PrivKey cryptotypes.PrivKey
|
||||||
Signer keyring.Signer
|
Signer keyring.Signer
|
||||||
|
ValAddr sdk.ValAddress
|
||||||
|
AccAddr sdk.AccAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenSigner() *TestSigner {
|
func (suite *PrecompileTestSuite) GenSigner() *TestSigner {
|
||||||
var s TestSigner
|
var s TestSigner
|
||||||
addr, priv := emtests.NewAddrKey()
|
addr, priv := emtests.NewAddrKey()
|
||||||
s.PrivKey = priv
|
s.PrivKey = priv
|
||||||
s.Addr = addr
|
s.Addr = addr
|
||||||
s.HexAddr = dasignersprecompile.ToLowerHexWithoutPrefix(s.Addr)
|
s.HexAddr = precopmiles_common.ToLowerHexWithoutPrefix(s.Addr)
|
||||||
s.Signer = emtests.NewSigner(priv)
|
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
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +82,7 @@ func (suite *PrecompileTestSuite) SetupTest() {
|
|||||||
hexAddr := strings.ToLower(crypto.PubkeyToAddress(key.PublicKey).Hex()[2:])
|
hexAddr := strings.ToLower(crypto.PubkeyToAddress(key.PublicKey).Hex()[2:])
|
||||||
valAddr, err := sdk.ValAddressFromHex(hexAddr)
|
valAddr, err := sdk.ValAddressFromHex(hexAddr)
|
||||||
suite.Assert().NoError(err)
|
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{})
|
newValidator, err := stakingtypes.NewValidator(valAddr, privkey.PubKey(), stakingtypes.Description{})
|
||||||
suite.Assert().NoError(err)
|
suite.Assert().NoError(err)
|
||||||
err = suite.StakingKeeper.SetValidatorByConsAddr(suite.Ctx, newValidator)
|
err = suite.StakingKeeper.SetValidatorByConsAddr(suite.Ctx, newValidator)
|
||||||
|
Loading…
Reference in New Issue
Block a user