mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 21:47:27 +00:00 
			
		
		
		
	Merge pull request #84 from 0glabs/staking-precompile
feat: staking precompile
This commit is contained in:
		
						commit
						76eebc57c1
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -49,3 +49,8 @@ go.work.sum | |||||||
| 
 | 
 | ||||||
| # runtime | # 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
	 MiniFrenchBread
						MiniFrenchBread