mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 15:17: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 | ||||
| run | ||||
| 
 | ||||
| # contracts | ||||
| precompiles/interfaces/build | ||||
| precompiles/interfaces/node_modules | ||||
| precompiles/interfaces/abis | ||||
							
								
								
									
										10
									
								
								app/app.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								app/app.go
									
									
									
									
									
								
							| @ -110,6 +110,7 @@ import ( | ||||
| 	chainparams "github.com/0glabs/0g-chain/app/params" | ||||
| 	"github.com/0glabs/0g-chain/chaincfg" | ||||
| 	dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners" | ||||
| 	stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" | ||||
| 
 | ||||
| 	"github.com/0glabs/0g-chain/x/bep3" | ||||
| 	bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper" | ||||
| @ -499,11 +500,18 @@ func NewApp( | ||||
| 	app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr) | ||||
| 	// precopmiles
 | ||||
| 	precompiles := make(map[common.Address]vm.PrecompiledContract) | ||||
| 	// dasigners
 | ||||
| 	daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper) | ||||
| 	if err != nil { | ||||
| 		panic("initialize precompile failed") | ||||
| 		panic(fmt.Sprintf("initialize dasigners precompile failed: %v", err)) | ||||
| 	} | ||||
| 	precompiles[daSignersPrecompile.Address()] = daSignersPrecompile | ||||
| 	// staking
 | ||||
| 	stakingPrecompile, err := stakingprecompile.NewStakingPrecompile(app.stakingKeeper) | ||||
| 	if err != nil { | ||||
| 		panic(fmt.Sprintf("initialize staking precompile failed: %v", err)) | ||||
| 	} | ||||
| 	precompiles[stakingPrecompile.Address()] = stakingPrecompile | ||||
| 
 | ||||
| 	app.evmKeeper = evmkeeper.NewKeeper( | ||||
| 		appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], | ||||
|  | ||||
| @ -3,4 +3,5 @@ package common | ||||
| const ( | ||||
| 	ErrGetStateDB          = "get EVM StateDB failed" | ||||
| 	ErrInvalidNumberOfArgs = "invalid number of arguments; expected %d; got: %d" | ||||
| 	ErrSenderNotOrigin     = "msg.sender is not from tx origin" | ||||
| ) | ||||
|  | ||||
							
								
								
									
										18
									
								
								precompiles/common/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								precompiles/common/utils.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| package common | ||||
| 
 | ||||
| import ( | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"cosmossdk.io/math" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| ) | ||||
| 
 | ||||
| func ToLowerHexWithoutPrefix(addr common.Address) string { | ||||
| 	return strings.ToLower(addr.Hex()[2:]) | ||||
| } | ||||
| 
 | ||||
| // BigIntToLegacyDec converts a uint number (18 decimals) to math.LegacyDec (18 decimals)
 | ||||
| func BigIntToLegacyDec(x *big.Int) math.LegacyDec { | ||||
| 	return math.LegacyNewDecFromBigIntWithPrec(x, math.LegacyPrecision) | ||||
| } | ||||
| @ -139,11 +139,11 @@ func (d *DASignersPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly b | ||||
| 		bz, err = d.RegisteredEpoch(ctx, evm, method, args) | ||||
| 	// txs
 | ||||
| 	case DASignersFunctionRegisterSigner: | ||||
| 		bz, err = d.RegisterSigner(ctx, evm, stateDB, method, args) | ||||
| 		bz, err = d.RegisterSigner(ctx, evm, stateDB, contract, method, args) | ||||
| 	case DASignersFunctionRegisterNextEpoch: | ||||
| 		bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, method, args) | ||||
| 		bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, contract, method, args) | ||||
| 	case DASignersFunctionUpdateSocket: | ||||
| 		bz, err = d.UpdateSocket(ctx, evm, stateDB, method, args) | ||||
| 		bz, err = d.UpdateSocket(ctx, evm, stateDB, contract, method, args) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -14,6 +14,7 @@ import ( | ||||
| 	"github.com/0glabs/0g-chain/x/dasigners/v1/types" | ||||
| 	abci "github.com/cometbft/cometbft/abci/types" | ||||
| 	"github.com/consensys/gnark-crypto/ecc/bn254" | ||||
| 	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	"github.com/ethereum/go-ethereum/accounts/abi" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| @ -23,7 +24,6 @@ import ( | ||||
| 	"cosmossdk.io/math" | ||||
| 	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| 	"github.com/evmos/ethermint/crypto/ethsecp256k1" | ||||
| ) | ||||
| 
 | ||||
| type DASignersTestSuite struct { | ||||
| @ -44,8 +44,7 @@ func (suite *DASignersTestSuite) AddDelegation(from string, to string, amount ma | ||||
| 	suite.Require().NoError(err) | ||||
| 	validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr) | ||||
| 	if !found { | ||||
| 		consPriv, err := ethsecp256k1.GenerateKey() | ||||
| 		suite.Require().NoError(err) | ||||
| 		consPriv := ed25519.GenPrivKey() | ||||
| 		newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{}) | ||||
| 		suite.Require().NoError(err) | ||||
| 		validator = newValidator | ||||
| @ -73,8 +72,8 @@ func (suite *DASignersTestSuite) SetupTest() { | ||||
| 	suite.Assert().EqualValues(ok, true) | ||||
| 	suite.dasigners = precompile.(*dasignersprecompile.DASignersPrecompile) | ||||
| 
 | ||||
| 	suite.signerOne = testutil.GenSigner() | ||||
| 	suite.signerTwo = testutil.GenSigner() | ||||
| 	suite.signerOne = suite.GenSigner() | ||||
| 	suite.signerTwo = suite.GenSigner() | ||||
| 	abi, err := abi.JSON(strings.NewReader(dasignersprecompile.DASignersABI)) | ||||
| 	suite.Assert().NoError(err) | ||||
| 	suite.abi = abi | ||||
|  | ||||
| @ -62,7 +62,7 @@ func (d *DASignersPrecompile) IsSigner(ctx sdk.Context, _ *vm.EVM, method *abi.M | ||||
| 	if len(args) != 1 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args)) | ||||
| 	} | ||||
| 	account := ToLowerHexWithoutPrefix(args[0].(common.Address)) | ||||
| 	account := precopmiles_common.ToLowerHexWithoutPrefix(args[0].(common.Address)) | ||||
| 	_, found, err := d.dasignersKeeper.GetSigner(ctx, account) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @ -74,7 +74,7 @@ func (d *DASignersPrecompile) RegisteredEpoch(ctx sdk.Context, _ *vm.EVM, method | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	account := ToLowerHexWithoutPrefix(args[0].(common.Address)) | ||||
| 	account := precopmiles_common.ToLowerHexWithoutPrefix(args[0].(common.Address)) | ||||
| 	epoch := args[1].(*big.Int).Uint64() | ||||
| 	_, found, err := d.dasignersKeeper.GetRegistration(ctx, epoch, account) | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -7,18 +7,30 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/accounts/abi" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| 	"github.com/evmos/ethermint/x/evm/statedb" | ||||
| 
 | ||||
| 	precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" | ||||
| ) | ||||
| 
 | ||||
| func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| func (d *DASignersPrecompile) RegisterSigner( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgRegisterSigner(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	sender := ToLowerHexWithoutPrefix(evm.Origin) | ||||
| 	sender := precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin) | ||||
| 	if sender != msg.Signer.Account { | ||||
| 		return nil, fmt.Errorf(ErrInvalidSender, sender, msg.Signer.Account) | ||||
| 	} | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = d.dasignersKeeper.RegisterSigner(sdk.WrapSDKContext(ctx), msg) | ||||
| 	if err != nil { | ||||
| @ -32,11 +44,22 @@ func (d *DASignersPrecompile) RegisterSigner(ctx sdk.Context, evm *vm.EVM, state | ||||
| 	return method.Outputs.Pack() | ||||
| } | ||||
| 
 | ||||
| func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	msg, err := NewMsgRegisterNextEpoch(args, ToLowerHexWithoutPrefix(evm.Origin)) | ||||
| func (d *DASignersPrecompile) RegisterNextEpoch( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgRegisterNextEpoch(args, precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = d.dasignersKeeper.RegisterNextEpoch(sdk.WrapSDKContext(ctx), msg) | ||||
| 	if err != nil { | ||||
| @ -45,11 +68,22 @@ func (d *DASignersPrecompile) RegisterNextEpoch(ctx sdk.Context, evm *vm.EVM, st | ||||
| 	return method.Outputs.Pack() | ||||
| } | ||||
| 
 | ||||
| func (d *DASignersPrecompile) UpdateSocket(ctx sdk.Context, evm *vm.EVM, stateDB *statedb.StateDB, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	msg, err := NewMsgUpdateSocket(args, ToLowerHexWithoutPrefix(evm.Origin)) | ||||
| func (d *DASignersPrecompile) UpdateSocket( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgUpdateSocket(args, precopmiles_common.ToLowerHexWithoutPrefix(evm.Origin)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = d.dasignersKeeper.UpdateSocket(sdk.WrapSDKContext(ctx), msg) | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -3,7 +3,6 @@ package dasigners | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" | ||||
| 	dasignerstypes "github.com/0glabs/0g-chain/x/dasigners/v1/types" | ||||
| @ -90,7 +89,7 @@ func NewQuerySignerRequest(args []interface{}) (*dasignerstypes.QuerySignerReque | ||||
| 		Accounts: make([]string, len(accounts)), | ||||
| 	} | ||||
| 	for i, account := range accounts { | ||||
| 		req.Accounts[i] = ToLowerHexWithoutPrefix(account) | ||||
| 		req.Accounts[i] = precopmiles_common.ToLowerHexWithoutPrefix(account) | ||||
| 	} | ||||
| 	return &req, nil | ||||
| } | ||||
| @ -139,10 +138,6 @@ func NewIDASignersSignerDetail(signer *dasignerstypes.Signer) IDASignersSignerDe | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ToLowerHexWithoutPrefix(addr common.Address) string { | ||||
| 	return strings.ToLower(addr.Hex()[2:]) | ||||
| } | ||||
| 
 | ||||
| func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| @ -151,7 +146,7 @@ func NewMsgRegisterSigner(args []interface{}) (*dasignerstypes.MsgRegisterSigner | ||||
| 	signer := args[0].(IDASignersSignerDetail) | ||||
| 	return &dasignerstypes.MsgRegisterSigner{ | ||||
| 		Signer: &dasignerstypes.Signer{ | ||||
| 			Account:  ToLowerHexWithoutPrefix(signer.Signer), | ||||
| 			Account:  precopmiles_common.ToLowerHexWithoutPrefix(signer.Signer), | ||||
| 			Socket:   signer.Socket, | ||||
| 			PubkeyG1: SerializeG1(signer.PkG1), | ||||
| 			PubkeyG2: SerializeG2(signer.PkG2), | ||||
|  | ||||
							
								
								
									
										18
									
								
								precompiles/interfaces/.solhint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								precompiles/interfaces/.solhint.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| { | ||||
|     "extends": "solhint:recommended", | ||||
|     "plugins": ["prettier"], | ||||
|     "rules": { | ||||
|         "avoid-low-level-calls": "off", | ||||
|         "compiler-version": "off", | ||||
|         "gas-custom-errors": "off", | ||||
|         "explicit-types": ["warn", "implicit"], | ||||
|         "func-visibility": ["warn", { "ignoreConstructors": true }], | ||||
|         "max-states-count": "off", | ||||
|         "no-empty-blocks": "off", | ||||
|         "no-global-import": "off", | ||||
|         "no-inline-assembly": "off", | ||||
|         "not-rely-on-time": "off", | ||||
|         "prettier/prettier": "error", | ||||
|         "reason-string": "off" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										88
									
								
								precompiles/interfaces/contracts/IDASigners.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								precompiles/interfaces/contracts/IDASigners.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| // SPDX-License-Identifier: LGPL-3.0-only | ||||
| pragma solidity >=0.8.0; | ||||
| 
 | ||||
| library BN254 { | ||||
|     struct G1Point { | ||||
|         uint X; | ||||
|         uint Y; | ||||
|     } | ||||
| 
 | ||||
|     // Encoding of field elements is: X[1] * i + X[0] | ||||
|     struct G2Point { | ||||
|         uint[2] X; | ||||
|         uint[2] Y; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| interface IDASigners { | ||||
|     /*=== struct ===*/ | ||||
|     struct SignerDetail { | ||||
|         address signer; | ||||
|         string socket; | ||||
|         BN254.G1Point pkG1; | ||||
|         BN254.G2Point pkG2; | ||||
|     } | ||||
| 
 | ||||
|     struct Params { | ||||
|         uint tokensPerVote; | ||||
|         uint maxVotesPerSigner; | ||||
|         uint maxQuorums; | ||||
|         uint epochBlocks; | ||||
|         uint encodedSlices; | ||||
|     } | ||||
| 
 | ||||
|     /*=== event ===*/ | ||||
|     event NewSigner( | ||||
|         address indexed signer, | ||||
|         BN254.G1Point pkG1, | ||||
|         BN254.G2Point pkG2 | ||||
|     ); | ||||
|     event SocketUpdated(address indexed signer, string socket); | ||||
| 
 | ||||
|     /*=== function ===*/ | ||||
|     function params() external view returns (Params memory); | ||||
| 
 | ||||
|     function epochNumber() external view returns (uint); | ||||
| 
 | ||||
|     function quorumCount(uint _epoch) external view returns (uint); | ||||
| 
 | ||||
|     function isSigner(address _account) external view returns (bool); | ||||
| 
 | ||||
|     function getSigner( | ||||
|         address[] memory _account | ||||
|     ) external view returns (SignerDetail[] memory); | ||||
| 
 | ||||
|     function getQuorum( | ||||
|         uint _epoch, | ||||
|         uint _quorumId | ||||
|     ) external view returns (address[] memory); | ||||
| 
 | ||||
|     function getQuorumRow( | ||||
|         uint _epoch, | ||||
|         uint _quorumId, | ||||
|         uint32 _rowIndex | ||||
|     ) external view returns (address); | ||||
| 
 | ||||
|     function registerSigner( | ||||
|         SignerDetail memory _signer, | ||||
|         BN254.G1Point memory _signature | ||||
|     ) external; | ||||
| 
 | ||||
|     function updateSocket(string memory _socket) external; | ||||
| 
 | ||||
|     function registeredEpoch( | ||||
|         address _account, | ||||
|         uint _epoch | ||||
|     ) external view returns (bool); | ||||
| 
 | ||||
|     function registerNextEpoch(BN254.G1Point memory _signature) external; | ||||
| 
 | ||||
|     function getAggPkG1( | ||||
|         uint _epoch, | ||||
|         uint _quorumId, | ||||
|         bytes memory _quorumBitmap | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (BN254.G1Point memory aggPkG1, uint total, uint hit); | ||||
| } | ||||
							
								
								
									
										415
									
								
								precompiles/interfaces/contracts/IStaking.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								precompiles/interfaces/contracts/IStaking.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,415 @@ | ||||
| // SPDX-License-Identifier: LGPL-3.0-only | ||||
| pragma solidity >=0.8.0; | ||||
| 
 | ||||
| /** | ||||
|  * @dev Description defines a validator description | ||||
|  */ | ||||
| struct Description { | ||||
|     string moniker; | ||||
|     string identity; | ||||
|     string website; | ||||
|     string securityContact; | ||||
|     string details; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev CommissionRates defines the initial commission rates to be used for creating | ||||
|  * a validator. | ||||
|  */ | ||||
| struct CommissionRates { | ||||
|     uint rate; // 18 decimals | ||||
|     uint maxRate; // 18 decimals | ||||
|     uint maxChangeRate; // 18 decimals | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev Commission defines the commission parameters. | ||||
|  */ | ||||
| struct Commission { | ||||
|     CommissionRates commissionRates; | ||||
|     uint updateTime; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev Validator defines a validator. | ||||
|  */ | ||||
| struct Validator { | ||||
|     string operatorAddress; | ||||
|     string consensusPubkey; | ||||
|     bool jailed; | ||||
|     BondStatus status; | ||||
|     uint tokens; | ||||
|     uint delegatorShares; // 18 decimals | ||||
|     Description description; | ||||
|     int64 unbondingHeight; | ||||
|     int64 unbondingTime; | ||||
|     Commission commission; | ||||
|     uint minSelfDelegation; | ||||
|     int64 unbondingOnHoldRefCount; | ||||
|     uint64[] unbondingIds; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev Delegation represents the bond with tokens held by an account. | ||||
|  */ | ||||
| struct Delegation { | ||||
|     string delegatorAddress; | ||||
|     string validatorAddress; | ||||
|     uint shares; // 18 decimals | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev RedelegationResponse is equivalent to a Redelegation except that its entries | ||||
|  * contain a balance in addition to shares which is more suitable for client | ||||
|  * responses. | ||||
|  */ | ||||
| struct DelegationResponse { | ||||
|     Delegation delegation; | ||||
|     uint balance; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev UnbondingDelegationEntry defines an unbonding object with relevant metadata. | ||||
|  */ | ||||
| struct UnbondingDelegationEntry { | ||||
|     int64 creationHeight; | ||||
|     int64 completionTime; | ||||
|     uint initialBalance; | ||||
|     uint balance; | ||||
|     uint64 unbondingId; | ||||
|     int64 unbondingOnHoldRefCount; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev UnbondingDelegation stores all of a single delegator's unbonding bonds | ||||
|  * for a single validator in an time-ordered list. | ||||
|  */ | ||||
| struct UnbondingDelegation { | ||||
|     string delegatorAddress; | ||||
|     string validatorAddress; | ||||
|     UnbondingDelegationEntry[] entries; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev RedelegationResponse is equivalent to a Redelegation except that its entries | ||||
|  * contain a balance in addition to shares which is more suitable for client | ||||
|  * responses. | ||||
|  */ | ||||
| struct RedelegationResponse { | ||||
|     Redelegation redelegation; | ||||
|     RedelegationEntryResponse[] entries; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev Redelegation contains the list of a particular delegator's redelegating bonds | ||||
|  * from a particular source validator to a particular destination validator. | ||||
|  */ | ||||
| struct Redelegation { | ||||
|     string delegatorAddress; | ||||
|     string validatorSrcAddress; | ||||
|     string validatorDstAddress; | ||||
|     RedelegationEntry[] entries; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev RedelegationEntry defines a redelegation object with relevant metadata. | ||||
|  */ | ||||
| struct RedelegationEntry { | ||||
|     int64 creationHeight; | ||||
|     int64 completionTime; | ||||
|     uint initialBalance; | ||||
|     uint sharesDst; // 18 decimals | ||||
|     uint64 unbondingId; | ||||
|     int64 unbondingOnHoldRefCount; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev RedelegationEntryResponse is equivalent to a RedelegationEntry except that it | ||||
|  * contains a balance in addition to shares which is more suitable for client | ||||
|  * responses. | ||||
|  */ | ||||
| struct RedelegationEntryResponse { | ||||
|     RedelegationEntry redelegationEntry; | ||||
|     uint balance; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev Params defines the parameters for the x/staking module. | ||||
|  */ | ||||
| struct Params { | ||||
|     int64 unbondingTime; | ||||
|     uint32 maxValidators; | ||||
|     uint32 maxEntries; | ||||
|     uint32 historicalEntries; | ||||
|     string bondDenom; | ||||
|     uint minCommissionRate; // 18 decimals | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @dev BondStatus is the status of a validator. | ||||
|  */ | ||||
| enum BondStatus { | ||||
|     Unspecified, | ||||
|     Unbonded, | ||||
|     Unbonding, | ||||
|     Bonded | ||||
| } | ||||
| 
 | ||||
| struct NullableUint { | ||||
|     bool isNull; | ||||
|     uint value; | ||||
| } | ||||
| 
 | ||||
| struct PageRequest { | ||||
|     bytes key; | ||||
|     uint64 offset; | ||||
|     uint64 limit; | ||||
|     bool countTotal; | ||||
|     bool reverse; | ||||
| } | ||||
| 
 | ||||
| struct PageResponse { | ||||
|     bytes nextKey; | ||||
|     uint64 total; | ||||
| } | ||||
| 
 | ||||
| interface IStaking { | ||||
|     /*=== cosmos tx ===*/ | ||||
| 
 | ||||
|     /** | ||||
|      * @dev CreateValidator defines a method for creating a new validator for tx sender. | ||||
|      * cosmos grpc: rpc CreateValidator(MsgCreateValidator) returns (MsgCreateValidatorResponse); | ||||
|      */ | ||||
|     function createValidator( | ||||
|         Description memory description, | ||||
|         CommissionRates memory commission, | ||||
|         uint minSelfDelegation, | ||||
|         string memory pubkey, // 0gchaind tendermint show-validator | ||||
|         uint value | ||||
|     ) external; | ||||
| 
 | ||||
|     /** | ||||
|      * @dev EditValidator defines a method for editing an existing validator (tx sender). | ||||
|      * cosmos grpc: rpc EditValidator(MsgEditValidator) returns (MsgEditValidatorResponse); | ||||
|      */ | ||||
|     function editValidator( | ||||
|         Description memory description, | ||||
|         NullableUint memory commissionRate, | ||||
|         NullableUint memory minSelfDelegation | ||||
|     ) external; | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Delegate defines a method for performing a delegation of coins from a delegator to a validator.abi | ||||
|      * The delegator is tx sender. | ||||
|      * cosmos grpc: rpc Delegate(MsgDelegate) returns (MsgDelegateResponse); | ||||
|      */ | ||||
|     function delegate( | ||||
|         string memory validatorAddress, | ||||
|         uint amount // in bond denom | ||||
|     ) external; | ||||
| 
 | ||||
|     /** | ||||
|      * @dev BeginRedelegate defines a method for performing a redelegationA | ||||
|      * of coins from a delegator and source validator to a destination validator. | ||||
|      * The delegator is tx sender. | ||||
|      * cosmos grpc: rpc BeginRedelegate(MsgBeginRedelegate) returns (MsgBeginRedelegateResponse); | ||||
|      */ | ||||
|     function beginRedelegate( | ||||
|         string memory validatorSrcAddress, | ||||
|         string memory validatorDstAddress, | ||||
|         uint amount // in bond denom | ||||
|     ) external returns (uint completionTime); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Undelegate defines a method for performing an undelegation from a | ||||
|      * delegate and a validator. | ||||
|      * The delegator is tx sender. | ||||
|      * cosmos grpc: rpc Undelegate(MsgUndelegate) returns (MsgUndelegateResponse); | ||||
|      */ | ||||
|     function undelegate( | ||||
|         string memory validatorAddress, | ||||
|         uint amount // in bond denom | ||||
|     ) external returns (uint completionTime); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev CancelUnbondingDelegation defines a method for performing canceling the unbonding delegation | ||||
|      * and delegate back to previous validator. | ||||
|      * The delegator is tx sender. | ||||
|      * Since: cosmos-sdk 0.46 | ||||
|      * cosmos grpc: rpc CancelUnbondingDelegation(MsgCancelUnbondingDelegation) returns (MsgCancelUnbondingDelegationResponse); | ||||
|      */ | ||||
|     function cancelUnbondingDelegation( | ||||
|         string memory validatorAddress, | ||||
|         uint amount, // in bond denom | ||||
|         uint creationHeight | ||||
|     ) external; | ||||
| 
 | ||||
|     /** | ||||
|      * @dev UpdateParams defines an operation for updating the x/staking module parameters. | ||||
|      * Since: cosmos-sdk 0.47 | ||||
|      * grpc: rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); | ||||
|      */ | ||||
|     // Skipped. This function is controlled by governance module. | ||||
| 
 | ||||
|     /*=== cosmos query ===*/ | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Validators queries all validators that match the given status. | ||||
|      * cosmos grpc: rpc Validators(QueryValidatorsRequest) returns (QueryValidatorsResponse); | ||||
|      */ | ||||
|     function validators( | ||||
|         string memory status, | ||||
|         PageRequest memory pagination | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             Validator[] memory validators, | ||||
|             PageResponse memory paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Validator queries validator info for given validator address. | ||||
|      * cosmos grpc: rpc Validator(QueryValidatorRequest) returns (QueryValidatorResponse); | ||||
|      */ | ||||
|     function validator( | ||||
|         string memory validatorAddress | ||||
|     ) external view returns (Validator memory validator); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev ValidatorDelegations queries delegate info for given validator. | ||||
|      * cosmos grpc: rpc ValidatorDelegations(QueryValidatorDelegationsRequest) returns (QueryValidatorDelegationsResponse); | ||||
|      */ | ||||
|     function validatorDelegations( | ||||
|         string memory validatorAddr, | ||||
|         PageRequest memory pagination | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             DelegationResponse[] memory delegationResponses, | ||||
|             PageResponse memory paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev ValidatorUnbondingDelegations queries unbonding delegations of a validator. | ||||
|      * cosmos grpc: rpc ValidatorUnbondingDelegations(QueryValidatorUnbondingDelegationsRequest) returns (QueryValidatorUnbondingDelegationsResponse); | ||||
|      */ | ||||
|     // | ||||
|     function validatorUnbondingDelegations( | ||||
|         string memory validatorAddr, | ||||
|         PageRequest memory pagination | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             UnbondingDelegation[] memory unbondingResponses, | ||||
|             PageResponse memory paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Delegation queries delegate info for given validator delegator pair. | ||||
|      * cosmos grpc: rpc Delegation(QueryDelegationRequest) returns (QueryDelegationResponse); | ||||
|      */ | ||||
|     function delegation( | ||||
|         string memory delegatorAddr, | ||||
|         string memory validatorAddr | ||||
|     ) external view returns (Delegation memory delegation, uint balance); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev UnbondingDelegation queries unbonding info for given validator delegator pair. | ||||
|      * cosmos grpc: rpc UnbondingDelegation(QueryUnbondingDelegationRequest) returns (QueryUnbondingDelegationResponse); | ||||
|      */ | ||||
|     function unbondingDelegation( | ||||
|         string memory delegatorAddr, | ||||
|         string memory validatorAddr | ||||
|     ) external view returns (UnbondingDelegation memory unbond); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev DelegatorDelegations queries all delegations of a given delegator address. | ||||
|      * | ||||
|      * cosmos grpc: rpc DelegatorDelegations(QueryDelegatorDelegationsRequest) returns (QueryDelegatorDelegationsResponse); | ||||
|      */ | ||||
|     function delegatorDelegations( | ||||
|         string memory delegatorAddr, | ||||
|         PageRequest memory pagination | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             DelegationResponse[] memory delegationResponses, | ||||
|             PageResponse memory paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev DelegatorUnbondingDelegations queries all unbonding delegations of a given delegator address. | ||||
|      * cosmos grpc: rpc DelegatorUnbondingDelegations(QueryDelegatorUnbondingDelegationsRequest) | ||||
|      */ | ||||
|     function delegatorUnbondingDelegations( | ||||
|         string memory delegatorAddr, | ||||
|         PageRequest memory pagination | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             UnbondingDelegation[] memory unbondingResponses, | ||||
|             PageResponse memory paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Redelegations queries redelegations of given address. | ||||
|      * | ||||
|      * grpc: rpc Redelegations(QueryRedelegationsRequest) returns (QueryRedelegationsResponse); | ||||
|      */ | ||||
|     function redelegations( | ||||
|         string memory delegatorAddress, | ||||
|         string memory srcValidatorAddress, | ||||
|         string memory dstValidatorAddress, | ||||
|         PageRequest calldata pageRequest | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             RedelegationResponse[] calldata redelegationResponses, | ||||
|             PageResponse calldata paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev DelegatorValidators queries all validators info for given delegator address. | ||||
|      * cosmos grpc: rpc DelegatorValidators(QueryDelegatorValidatorsRequest) returns (QueryDelegatorValidatorsResponse); | ||||
|      */ | ||||
|     function delegatorValidators( | ||||
|         string memory delegatorAddr, | ||||
|         PageRequest memory pagination | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns ( | ||||
|             Validator[] memory validators, | ||||
|             PageResponse memory paginationResult | ||||
|         ); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev DelegatorValidator queries validator info for given delegator validator pair. | ||||
|      * cosmos grpc: rpc DelegatorValidator(QueryDelegatorValidatorRequest) returns (QueryDelegatorValidatorResponse); | ||||
|      */ | ||||
|     function delegatorValidator( | ||||
|         string memory delegatorAddr, | ||||
|         string memory validatorAddr | ||||
|     ) external view returns (Validator memory validator); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Pool queries the pool info. | ||||
|      * cosmos grpc: rpc Pool(QueryPoolRequest) returns (QueryPoolResponse); | ||||
|      */ | ||||
|     function pool() | ||||
|         external | ||||
|         view | ||||
|         returns (uint notBondedTokens, uint bondedTokens); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Parameters queries the staking parameters. | ||||
|      * cosmos grpc: rpc Params(QueryParamsRequest) returns (QueryParamsResponse); | ||||
|      */ | ||||
|     function params() external view returns (Params memory params); | ||||
| } | ||||
							
								
								
									
										33
									
								
								precompiles/interfaces/hardhat.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								precompiles/interfaces/hardhat.config.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| import "hardhat-abi-exporter"; | ||||
| import { HardhatUserConfig } from "hardhat/types"; | ||||
| 
 | ||||
| const config: HardhatUserConfig = { | ||||
|     paths: { | ||||
|         artifacts: "build/artifacts", | ||||
|         cache: "build/cache", | ||||
|         sources: "contracts", | ||||
|     }, | ||||
|     solidity: { | ||||
|         compilers: [ | ||||
|             { | ||||
|                 version: "0.8.20", | ||||
|                 settings: { | ||||
|                     evmVersion: "istanbul", | ||||
|                     optimizer: { | ||||
|                         enabled: true, | ||||
|                         runs: 200, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         ], | ||||
|     }, | ||||
|     abiExporter: { | ||||
|         path: "./abis", | ||||
|         runOnCompile: true, | ||||
|         clear: true, | ||||
|         flat: true, | ||||
|         format: "json", | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| export default config; | ||||
							
								
								
									
										27
									
								
								precompiles/interfaces/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								precompiles/interfaces/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| { | ||||
|   "name": "precompile-contracts", | ||||
|   "version": "1.0.0", | ||||
|   "license": "MIT", | ||||
|   "scripts": { | ||||
|     "build": "hardhat compile", | ||||
|     "fmt:sol": "prettier 'contracts/**/*.sol' -w" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@nomicfoundation/hardhat-ethers": "^3.0.5", | ||||
|     "@typescript-eslint/eslint-plugin": "6.21.0", | ||||
|     "@typescript-eslint/parser": "6.21.0", | ||||
|     "eslint": "8.34.0", | ||||
|     "eslint-config-prettier": "8.6.0", | ||||
|     "eslint-plugin-no-only-tests": "3.1.0", | ||||
|     "eslint-plugin-prettier": "4.2.1", | ||||
|     "hardhat": "^2.22.2", | ||||
|     "hardhat-abi-exporter": "^2.10.1", | ||||
|     "prettier": "2.8.4", | ||||
|     "prettier-plugin-organize-imports": "3.2.4", | ||||
|     "prettier-plugin-solidity": "1.1.2", | ||||
|     "solhint": "^4.5.4", | ||||
|     "solhint-plugin-prettier": "0.0.5", | ||||
|     "ts-node": "^10.9.2", | ||||
|     "typescript": "4.9.5" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										3152
									
								
								precompiles/interfaces/yarn.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3152
									
								
								precompiles/interfaces/yarn.lock
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1716
									
								
								precompiles/staking/IStaking.abi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1716
									
								
								precompiles/staking/IStaking.abi
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										835
									
								
								precompiles/staking/contract.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										835
									
								
								precompiles/staking/contract.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										5
									
								
								precompiles/staking/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								precompiles/staking/errors.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| package staking | ||||
| 
 | ||||
| const ( | ||||
| 	ErrPubKeyInvalidLength = "public key with invalid length" | ||||
| ) | ||||
							
								
								
									
										223
									
								
								precompiles/staking/query.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								precompiles/staking/query.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,223 @@ | ||||
| package staking | ||||
| 
 | ||||
| import ( | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" | ||||
| 	"github.com/ethereum/go-ethereum/accounts/abi" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| ) | ||||
| 
 | ||||
| func (s *StakingPrecompile) Validators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryValidatorsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Validators(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	validators := make([]Validator, len(response.Validators)) | ||||
| 	for i, v := range response.Validators { | ||||
| 		validators[i] = convertValidator(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(validators, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Validator(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryValidatorRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Validator(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return method.Outputs.Pack(convertValidator(response.Validator)) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) ValidatorDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryValidatorDelegationsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.ValidatorDelegations(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	delegationResponses := make([]DelegationResponse, len(response.DelegationResponses)) | ||||
| 	for i, v := range response.DelegationResponses { | ||||
| 		delegationResponses[i] = convertDelegationResponse(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(delegationResponses, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) ValidatorUnbondingDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryValidatorUnbondingDelegationsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.ValidatorUnbondingDelegations(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	unbondingResponses := make([]UnbondingDelegation, len(response.UnbondingResponses)) | ||||
| 	for i, v := range response.UnbondingResponses { | ||||
| 		unbondingResponses[i] = convertUnbondingDelegation(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(unbondingResponses, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Delegation(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryDelegationRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Delegation(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	delegation := convertDelegation(response.DelegationResponse.Delegation) | ||||
| 	balance := response.DelegationResponse.Balance.Amount.BigInt() | ||||
| 
 | ||||
| 	return method.Outputs.Pack(delegation, balance) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) UnbondingDelegation(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryUnbondingDelegationRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.UnbondingDelegation(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return method.Outputs.Pack(convertUnbondingDelegation(response.Unbond)) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) DelegatorDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryDelegatorDelegationsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorDelegations(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	delegationResponses := make([]DelegationResponse, len(response.DelegationResponses)) | ||||
| 	for i, v := range response.DelegationResponses { | ||||
| 		delegationResponses[i] = convertDelegationResponse(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(delegationResponses, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) DelegatorUnbondingDelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryDelegatorUnbondingDelegationsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorUnbondingDelegations(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	unbondingResponses := make([]UnbondingDelegation, len(response.UnbondingResponses)) | ||||
| 	for i, v := range response.UnbondingResponses { | ||||
| 		unbondingResponses[i] = convertUnbondingDelegation(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(unbondingResponses, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Redelegations(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryRedelegationsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Redelegations(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	redelegationResponses := make([]RedelegationResponse, len(response.RedelegationResponses)) | ||||
| 	for i, v := range response.RedelegationResponses { | ||||
| 		redelegationResponses[i] = convertRedelegationResponse(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(redelegationResponses, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) DelegatorValidators(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryDelegatorValidatorsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorValidators(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	validators := make([]Validator, len(response.Validators)) | ||||
| 	for i, v := range response.Validators { | ||||
| 		validators[i] = convertValidator(v) | ||||
| 	} | ||||
| 	paginationResult := convertPageResponse(response.Pagination) | ||||
| 
 | ||||
| 	return method.Outputs.Pack(validators, paginationResult) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) DelegatorValidator(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryDelegatorValidatorRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.DelegatorValidator(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return method.Outputs.Pack(convertValidator(response.Validator)) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Pool(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryPoolRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Pool(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	notBondedTokens := response.Pool.NotBondedTokens.BigInt() | ||||
| 	bondedTokens := response.Pool.BondedTokens.BigInt() | ||||
| 
 | ||||
| 	return method.Outputs.Pack(notBondedTokens, bondedTokens) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Params(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) { | ||||
| 	req, err := NewQueryParamsRequest(args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	response, err := stakingkeeper.Querier{Keeper: s.stakingKeeper}.Params(ctx, req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return method.Outputs.Pack(convertParams(response.Params)) | ||||
| } | ||||
							
								
								
									
										801
									
								
								precompiles/staking/query_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										801
									
								
								precompiles/staking/query_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,801 @@ | ||||
| package staking_test | ||||
| 
 | ||||
| import ( | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	query "github.com/cosmos/cosmos-sdk/types/query" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| ) | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestValidators() { | ||||
| 	method := stakingprecompile.StakingFunctionValidators | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func() []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func() []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					"", | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				validators := out[0].([]stakingprecompile.Validator) | ||||
| 				paginationResult := out[1].(stakingprecompile.PageResponse) | ||||
| 				s.Assert().EqualValues(3, len(validators)) | ||||
| 				s.Assert().EqualValues(3, paginationResult.Total) | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			s.AddDelegation(s.signerOne.HexAddr, s.signerTwo.HexAddr, sdk.NewIntFromUint64(1000000)) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestValidator() { | ||||
| 	method := stakingprecompile.StakingFunctionValidator | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(operatorAddress string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(operatorAddress string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					operatorAddress, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				operatorAddress, err := s.firstBondedValidator() | ||||
| 				s.Require().NoError(err) | ||||
| 				validator := out[0].(stakingprecompile.Validator) | ||||
| 				s.Require().EqualValues(common.HexToAddress(validator.OperatorAddress), common.BytesToAddress(operatorAddress.Bytes())) | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestValidatorDelegations() { | ||||
| 	method := stakingprecompile.StakingFunctionValidatorDelegations | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(operatorAddress string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(operatorAddress string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					operatorAddress, | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				operatorAddress, err := s.firstBondedValidator() | ||||
| 				s.Require().NoError(err) | ||||
| 				delegations := out[0].([]stakingprecompile.DelegationResponse) | ||||
| 				d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 				s.Require().EqualValues(len(delegations), len(d)) | ||||
| 				// jsonData, _ := json.MarshalIndent(delegations, "", "    ")
 | ||||
| 				// fmt.Printf("delegations: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestValidatorUnbondingDelegations() { | ||||
| 	method := stakingprecompile.StakingFunctionValidatorUnbondingDelegations | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(operatorAddress string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(operatorAddress string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					operatorAddress, | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				unbonding := out[0].([]stakingprecompile.UnbondingDelegation) | ||||
| 				s.Require().EqualValues(len(unbonding), 1) | ||||
| 				// jsonData, _ := json.MarshalIndent(unbonding, "", "    ")
 | ||||
| 				// fmt.Printf("delegations: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 			_, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1)) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestDelegation() { | ||||
| 	method := stakingprecompile.StakingFunctionDelegation | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr, valAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr, valAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					valAddr, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				d := out[0].(stakingprecompile.Delegation) | ||||
| 				b := out[1].(*big.Int) | ||||
| 				_ = d | ||||
| 				_ = b | ||||
| 				/* | ||||
| 					jsonData, _ := json.MarshalIndent(d, "", "    ") | ||||
| 					fmt.Printf("delegation: %s\n", string(jsonData)) | ||||
| 					fmt.Printf("balance: %v\n", b) | ||||
| 				*/ | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestUnbondingDelegation() { | ||||
| 	method := stakingprecompile.StakingFunctionUnbondingDelegation | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr, valAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr, valAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					valAddr, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				u := out[0].(stakingprecompile.UnbondingDelegation) | ||||
| 				_ = u | ||||
| 				// jsonData, _ := json.MarshalIndent(u, "", "    ")
 | ||||
| 				// fmt.Printf("delegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 			_, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1)) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestDelegatorDelegations() { | ||||
| 	method := stakingprecompile.StakingFunctionDelegatorDelegations | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				d := out[0].([]stakingprecompile.DelegationResponse) | ||||
| 				paginationResult := out[1].(stakingprecompile.PageResponse) | ||||
| 				s.Assert().EqualValues(1, len(d)) | ||||
| 				s.Assert().EqualValues(1, paginationResult.Total) | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("delegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestDelegatorUnbondingDelegations() { | ||||
| 	method := stakingprecompile.StakingFunctionDelegatorUnbondingDelegations | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				d := out[0].([]stakingprecompile.UnbondingDelegation) | ||||
| 				paginationResult := out[1].(stakingprecompile.PageResponse) | ||||
| 				s.Assert().EqualValues(1, len(d)) | ||||
| 				s.Assert().EqualValues(1, paginationResult.Total) | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("delegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 			_, err = s.stakingKeeper.Undelegate(s.Ctx, delAddr, operatorAddress, sdk.NewDec(1)) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestRedelegations() { | ||||
| 	method := stakingprecompile.StakingFunctionRedelegations | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr, srcValAddr, dstValAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr, srcValAddr, dstValAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					srcValAddr, | ||||
| 					dstValAddr, | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				d := out[0].([]stakingprecompile.RedelegationResponse) | ||||
| 				paginationResult := out[1].(stakingprecompile.PageResponse) | ||||
| 				s.Assert().EqualValues(1, len(d)) | ||||
| 				s.Assert().EqualValues(1, paginationResult.Total) | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("redelegations: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 			// setup redelegations
 | ||||
| 			s.setupValidator(s.signerOne) | ||||
| 			_, err = s.stakingKeeper.BeginRedelegation(s.Ctx, delAddr, operatorAddress, s.signerOne.ValAddr, sdk.NewDec(1)) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String(), s.signerOne.ValAddr.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestDelegatorValidators() { | ||||
| 	method := stakingprecompile.StakingFunctionDelegatorValidators | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					query.PageRequest{ | ||||
| 						Limit:      10, | ||||
| 						CountTotal: true, | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				v := out[0].([]stakingprecompile.Validator) | ||||
| 				paginationResult := out[1].(stakingprecompile.PageResponse) | ||||
| 				s.Assert().EqualValues(1, len(v)) | ||||
| 				s.Assert().EqualValues(1, paginationResult.Total) | ||||
| 				// jsonData, _ := json.MarshalIndent(v, "", "    ")
 | ||||
| 				// fmt.Printf("validators: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestDelegatorValidator() { | ||||
| 	method := stakingprecompile.StakingFunctionDelegatorValidator | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func(delAddr, valAddr string) []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(delAddr, valAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					delAddr, | ||||
| 					valAddr, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				v := out[0].(stakingprecompile.Validator) | ||||
| 				_ = v | ||||
| 				// jsonData, _ := json.MarshalIndent(v, "", "    ")
 | ||||
| 				// fmt.Printf("validators: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 			d := s.stakingKeeper.GetValidatorDelegations(s.Ctx, operatorAddress) | ||||
| 			delAddr, err := sdk.AccAddressFromBech32(d[0].DelegatorAddress) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(delAddr.String(), operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestPool() { | ||||
| 	method := stakingprecompile.StakingFunctionPool | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func() []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func() []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				bonded := out[0].(*big.Int) | ||||
| 				unbonded := out[0].(*big.Int) | ||||
| 				s.Assert().Equal(bonded.Int64(), int64(0)) | ||||
| 				s.Assert().Equal(unbonded.Int64(), int64(0)) | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestParams() { | ||||
| 	method := stakingprecompile.StakingFunctionParams | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| 		malleate    func() []byte | ||||
| 		postCheck   func(bz []byte) | ||||
| 		gas         uint64 | ||||
| 		expErr      bool | ||||
| 		errContains string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func() []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			func(data []byte) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 				params := out[0].(stakingprecompile.Params) | ||||
| 				_ = params | ||||
| 				// jsonData, _ := json.MarshalIndent(params, "", "    ")
 | ||||
| 				// fmt.Printf("params: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			100000, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expErr { | ||||
| 				s.Require().Error(err) | ||||
| 				s.Require().Contains(err.Error(), tc.errContains) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				s.Require().NotNil(bz) | ||||
| 				tc.postCheck(bz) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										148
									
								
								precompiles/staking/staking.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								precompiles/staking/staking.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,148 @@ | ||||
| package staking | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" | ||||
| 	"github.com/cosmos/cosmos-sdk/store/types" | ||||
| 	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" | ||||
| 	"github.com/ethereum/go-ethereum/accounts/abi" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| 	"github.com/evmos/ethermint/x/evm/statedb" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	PrecompileAddress = "0x0000000000000000000000000000000000001001" | ||||
| 
 | ||||
| 	// txs
 | ||||
| 	StakingFunctionCreateValidator           = "createValidator" | ||||
| 	StakingFunctionEditValidator             = "editValidator" | ||||
| 	StakingFunctionDelegate                  = "delegate" | ||||
| 	StakingFunctionBeginRedelegate           = "beginRedelegate" | ||||
| 	StakingFunctionUndelegate                = "undelegate" | ||||
| 	StakingFunctionCancelUnbondingDelegation = "cancelUnbondingDelegation" | ||||
| 	// queries
 | ||||
| 	StakingFunctionValidators                    = "validators" | ||||
| 	StakingFunctionValidator                     = "validator" | ||||
| 	StakingFunctionValidatorDelegations          = "validatorDelegations" | ||||
| 	StakingFunctionValidatorUnbondingDelegations = "validatorUnbondingDelegations" | ||||
| 	StakingFunctionDelegation                    = "delegation" | ||||
| 	StakingFunctionUnbondingDelegation           = "unbondingDelegation" | ||||
| 	StakingFunctionDelegatorDelegations          = "delegatorDelegations" | ||||
| 	StakingFunctionDelegatorUnbondingDelegations = "delegatorUnbondingDelegations" | ||||
| 	StakingFunctionRedelegations                 = "redelegations" | ||||
| 	StakingFunctionDelegatorValidators           = "delegatorValidators" | ||||
| 	StakingFunctionDelegatorValidator            = "delegatorValidator" | ||||
| 	StakingFunctionPool                          = "pool" | ||||
| 	StakingFunctionParams                        = "params" | ||||
| ) | ||||
| 
 | ||||
| var _ vm.PrecompiledContract = &StakingPrecompile{} | ||||
| 
 | ||||
| type StakingPrecompile struct { | ||||
| 	abi           abi.ABI | ||||
| 	stakingKeeper *stakingkeeper.Keeper | ||||
| } | ||||
| 
 | ||||
| func NewStakingPrecompile(stakingKeeper *stakingkeeper.Keeper) (*StakingPrecompile, error) { | ||||
| 	abi, err := abi.JSON(strings.NewReader(StakingABI)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &StakingPrecompile{ | ||||
| 		abi:           abi, | ||||
| 		stakingKeeper: stakingKeeper, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // Address implements vm.PrecompiledContract.
 | ||||
| func (s *StakingPrecompile) Address() common.Address { | ||||
| 	return common.HexToAddress(PrecompileAddress) | ||||
| } | ||||
| 
 | ||||
| // RequiredGas implements vm.PrecompiledContract.
 | ||||
| func (s *StakingPrecompile) RequiredGas(input []byte) uint64 { | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| // Run implements vm.PrecompiledContract.
 | ||||
| func (s *StakingPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { | ||||
| 	// parse input
 | ||||
| 	if len(contract.Input) < 4 { | ||||
| 		return nil, vm.ErrExecutionReverted | ||||
| 	} | ||||
| 	method, err := s.abi.MethodById(contract.Input[:4]) | ||||
| 	if err != nil { | ||||
| 		return nil, vm.ErrExecutionReverted | ||||
| 	} | ||||
| 	args, err := method.Inputs.Unpack(contract.Input[4:]) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// get state db and context
 | ||||
| 	stateDB, ok := evm.StateDB.(*statedb.StateDB) | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrGetStateDB) | ||||
| 	} | ||||
| 	ctx := stateDB.GetContext() | ||||
| 	// reset gas config
 | ||||
| 	ctx = ctx.WithKVGasConfig(types.KVGasConfig()) | ||||
| 	initialGas := ctx.GasMeter().GasConsumed() | ||||
| 
 | ||||
| 	var bz []byte | ||||
| 	switch method.Name { | ||||
| 	// queries
 | ||||
| 	case StakingFunctionValidators: | ||||
| 		bz, err = s.Validators(ctx, evm, method, args) | ||||
| 	case StakingFunctionValidator: | ||||
| 		bz, err = s.Validator(ctx, evm, method, args) | ||||
| 	case StakingFunctionValidatorDelegations: | ||||
| 		bz, err = s.ValidatorDelegations(ctx, evm, method, args) | ||||
| 	case StakingFunctionValidatorUnbondingDelegations: | ||||
| 		bz, err = s.ValidatorUnbondingDelegations(ctx, evm, method, args) | ||||
| 	case StakingFunctionDelegation: | ||||
| 		bz, err = s.Delegation(ctx, evm, method, args) | ||||
| 	case StakingFunctionUnbondingDelegation: | ||||
| 		bz, err = s.UnbondingDelegation(ctx, evm, method, args) | ||||
| 	case StakingFunctionDelegatorDelegations: | ||||
| 		bz, err = s.DelegatorDelegations(ctx, evm, method, args) | ||||
| 	case StakingFunctionDelegatorUnbondingDelegations: | ||||
| 		bz, err = s.DelegatorUnbondingDelegations(ctx, evm, method, args) | ||||
| 	case StakingFunctionRedelegations: | ||||
| 		bz, err = s.Redelegations(ctx, evm, method, args) | ||||
| 	case StakingFunctionDelegatorValidators: | ||||
| 		bz, err = s.DelegatorValidators(ctx, evm, method, args) | ||||
| 	case StakingFunctionDelegatorValidator: | ||||
| 		bz, err = s.DelegatorValidator(ctx, evm, method, args) | ||||
| 	case StakingFunctionPool: | ||||
| 		bz, err = s.Pool(ctx, evm, method, args) | ||||
| 	case StakingFunctionParams: | ||||
| 		bz, err = s.Params(ctx, evm, method, args) | ||||
| 	// txs
 | ||||
| 	case StakingFunctionCreateValidator: | ||||
| 		bz, err = s.CreateValidator(ctx, evm, stateDB, contract, method, args) | ||||
| 	case StakingFunctionEditValidator: | ||||
| 		bz, err = s.EditValidator(ctx, evm, stateDB, contract, method, args) | ||||
| 	case StakingFunctionDelegate: | ||||
| 		bz, err = s.Delegate(ctx, evm, stateDB, contract, method, args) | ||||
| 	case StakingFunctionBeginRedelegate: | ||||
| 		bz, err = s.BeginRedelegate(ctx, evm, stateDB, contract, method, args) | ||||
| 	case StakingFunctionUndelegate: | ||||
| 		bz, err = s.Undelegate(ctx, evm, stateDB, contract, method, args) | ||||
| 	case StakingFunctionCancelUnbondingDelegation: | ||||
| 		bz, err = s.CancelUnbondingDelegation(ctx, evm, stateDB, contract, method, args) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	cost := ctx.GasMeter().GasConsumed() - initialGas | ||||
| 
 | ||||
| 	if !contract.UseGas(cost) { | ||||
| 		return nil, vm.ErrOutOfGas | ||||
| 	} | ||||
| 	return bz, nil | ||||
| } | ||||
							
								
								
									
										145
									
								
								precompiles/staking/staking_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								precompiles/staking/staking_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,145 @@ | ||||
| package staking_test | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"cosmossdk.io/math" | ||||
| 	stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" | ||||
| 	"github.com/0glabs/0g-chain/precompiles/testutil" | ||||
| 	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" | ||||
| 	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||||
| 	"github.com/ethereum/go-ethereum/accounts/abi" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| 	evmtypes "github.com/evmos/ethermint/x/evm/types" | ||||
| 	"github.com/stretchr/testify/suite" | ||||
| ) | ||||
| 
 | ||||
| type StakingTestSuite struct { | ||||
| 	testutil.PrecompileTestSuite | ||||
| 
 | ||||
| 	abi           abi.ABI | ||||
| 	addr          common.Address | ||||
| 	staking       *stakingprecompile.StakingPrecompile | ||||
| 	stakingKeeper *stakingkeeper.Keeper | ||||
| 	signerOne     *testutil.TestSigner | ||||
| 	signerTwo     *testutil.TestSigner | ||||
| } | ||||
| 
 | ||||
| func (suite *StakingTestSuite) SetupTest() { | ||||
| 	suite.PrecompileTestSuite.SetupTest() | ||||
| 
 | ||||
| 	suite.stakingKeeper = suite.App.GetStakingKeeper() | ||||
| 
 | ||||
| 	suite.addr = common.HexToAddress(stakingprecompile.PrecompileAddress) | ||||
| 
 | ||||
| 	precompiles := suite.EvmKeeper.GetPrecompiles() | ||||
| 	precompile, ok := precompiles[suite.addr] | ||||
| 	suite.Assert().EqualValues(ok, true) | ||||
| 
 | ||||
| 	suite.staking = precompile.(*stakingprecompile.StakingPrecompile) | ||||
| 
 | ||||
| 	suite.signerOne = suite.GenSigner() | ||||
| 	suite.signerTwo = suite.GenSigner() | ||||
| 
 | ||||
| 	abi, err := abi.JSON(strings.NewReader(stakingprecompile.StakingABI)) | ||||
| 	suite.Assert().NoError(err) | ||||
| 	suite.abi = abi | ||||
| } | ||||
| 
 | ||||
| func (suite *StakingTestSuite) AddDelegation(from string, to string, amount math.Int) { | ||||
| 	accAddr, err := sdk.AccAddressFromHexUnsafe(from) | ||||
| 	suite.Require().NoError(err) | ||||
| 	valAddr, err := sdk.ValAddressFromHex(to) | ||||
| 	suite.Require().NoError(err) | ||||
| 	validator, found := suite.StakingKeeper.GetValidator(suite.Ctx, valAddr) | ||||
| 	if !found { | ||||
| 		consPriv := ed25519.GenPrivKey() | ||||
| 		newValidator, err := stakingtypes.NewValidator(valAddr, consPriv.PubKey(), stakingtypes.Description{}) | ||||
| 		suite.Require().NoError(err) | ||||
| 		validator = newValidator | ||||
| 	} | ||||
| 	validator.Tokens = validator.Tokens.Add(amount) | ||||
| 	validator.DelegatorShares = validator.DelegatorShares.Add(amount.ToLegacyDec()) | ||||
| 	suite.StakingKeeper.SetValidator(suite.Ctx, validator) | ||||
| 	bonded := suite.stakingKeeper.GetDelegatorBonded(suite.Ctx, accAddr) | ||||
| 	suite.StakingKeeper.SetDelegation(suite.Ctx, stakingtypes.Delegation{ | ||||
| 		DelegatorAddress: accAddr.String(), | ||||
| 		ValidatorAddress: valAddr.String(), | ||||
| 		Shares:           bonded.Add(amount).ToLegacyDec(), | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (suite *StakingTestSuite) setupValidator(signer *testutil.TestSigner) { | ||||
| 	method := stakingprecompile.StakingFunctionCreateValidator | ||||
| 	description := stakingprecompile.Description{ | ||||
| 		Moniker:         "test node", | ||||
| 		Identity:        "test node identity", | ||||
| 		Website:         "http://test.node.com", | ||||
| 		SecurityContact: "test node security contract", | ||||
| 		Details:         "test node details", | ||||
| 	} | ||||
| 	commission := stakingprecompile.CommissionRates{ | ||||
| 		Rate:          math.LegacyOneDec().BigInt(), | ||||
| 		MaxRate:       math.LegacyOneDec().BigInt(), | ||||
| 		MaxChangeRate: math.LegacyOneDec().BigInt(), | ||||
| 	} | ||||
| 	minSelfDelegation := big.NewInt(1) | ||||
| 	pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g=" | ||||
| 	value := big.NewInt(100000000) | ||||
| 	input, err := suite.abi.Pack( | ||||
| 		method, | ||||
| 		description, | ||||
| 		commission, | ||||
| 		minSelfDelegation, | ||||
| 		pubkey, | ||||
| 		value, | ||||
| 	) | ||||
| 	suite.Assert().NoError(err) | ||||
| 	_, err = suite.runTx(input, signer, 10000000) | ||||
| 	suite.Assert().NoError(err) | ||||
| 	_, err = suite.stakingKeeper.ApplyAndReturnValidatorSetUpdates(suite.Ctx) | ||||
| 	suite.Assert().NoError(err) | ||||
| } | ||||
| 
 | ||||
| func (suite *StakingTestSuite) firstBondedValidator() (sdk.ValAddress, error) { | ||||
| 	validators := suite.stakingKeeper.GetValidators(suite.Ctx, 10) | ||||
| 	for _, v := range validators { | ||||
| 		if v.IsBonded() { | ||||
| 			return sdk.ValAddressFromBech32(v.OperatorAddress) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, errors.New("no bonded validator") | ||||
| } | ||||
| 
 | ||||
| func (suite *StakingTestSuite) runTx(input []byte, signer *testutil.TestSigner, gas uint64) ([]byte, error) { | ||||
| 	contract := vm.NewPrecompile(vm.AccountRef(signer.Addr), vm.AccountRef(suite.addr), big.NewInt(0), gas) | ||||
| 	contract.Input = input | ||||
| 
 | ||||
| 	msgEthereumTx := evmtypes.NewTx(suite.EvmKeeper.ChainID(), 0, &suite.addr, big.NewInt(0), gas, big.NewInt(0), big.NewInt(0), big.NewInt(0), input, nil) | ||||
| 	msgEthereumTx.From = signer.HexAddr | ||||
| 	err := msgEthereumTx.Sign(suite.EthSigner, signer.Signer) | ||||
| 	suite.Assert().NoError(err, "failed to sign Ethereum message") | ||||
| 
 | ||||
| 	proposerAddress := suite.Ctx.BlockHeader().ProposerAddress | ||||
| 	cfg, err := suite.EvmKeeper.EVMConfig(suite.Ctx, proposerAddress, suite.EvmKeeper.ChainID()) | ||||
| 	suite.Assert().NoError(err, "failed to instantiate EVM config") | ||||
| 
 | ||||
| 	msg, err := msgEthereumTx.AsMessage(suite.EthSigner, big.NewInt(0)) | ||||
| 	suite.Assert().NoError(err, "failed to instantiate Ethereum message") | ||||
| 
 | ||||
| 	evm := suite.EvmKeeper.NewEVM(suite.Ctx, msg, cfg, nil, suite.Statedb) | ||||
| 	precompiles := suite.EvmKeeper.GetPrecompiles() | ||||
| 	evm.WithPrecompiles(precompiles, []common.Address{suite.addr}) | ||||
| 
 | ||||
| 	return suite.staking.Run(evm, contract, false) | ||||
| } | ||||
| 
 | ||||
| func TestKeeperSuite(t *testing.T) { | ||||
| 	suite.Run(t, new(StakingTestSuite)) | ||||
| } | ||||
							
								
								
									
										163
									
								
								precompiles/staking/tx.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								precompiles/staking/tx.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,163 @@ | ||||
| package staking | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" | ||||
| 	"github.com/ethereum/go-ethereum/accounts/abi" | ||||
| 	"github.com/ethereum/go-ethereum/core/vm" | ||||
| 	"github.com/evmos/ethermint/x/evm/statedb" | ||||
| ) | ||||
| 
 | ||||
| func (s *StakingPrecompile) CreateValidator( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgCreateValidator(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).CreateValidator(ctx, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// emit events
 | ||||
| 	return method.Outputs.Pack() | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) EditValidator( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgEditValidator(args, evm.Origin) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).EditValidator(ctx, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// emit events
 | ||||
| 	return method.Outputs.Pack() | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Delegate( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgDelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Delegate(ctx, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// emit events
 | ||||
| 	return method.Outputs.Pack() | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) BeginRedelegate( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgBeginRedelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).BeginRedelegate(ctx, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// emit events
 | ||||
| 	return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix())) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) Undelegate( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgUndelegate(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Undelegate(ctx, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// emit events
 | ||||
| 	return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix())) | ||||
| } | ||||
| 
 | ||||
| func (s *StakingPrecompile) CancelUnbondingDelegation( | ||||
| 	ctx sdk.Context, | ||||
| 	evm *vm.EVM, | ||||
| 	stateDB *statedb.StateDB, | ||||
| 	contract *vm.Contract, | ||||
| 	method *abi.Method, | ||||
| 	args []interface{}, | ||||
| ) ([]byte, error) { | ||||
| 	msg, err := NewMsgCancelUnbondingDelegation(args, evm.Origin, s.stakingKeeper.BondDenom(ctx)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// validation
 | ||||
| 	if contract.CallerAddress != evm.Origin { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin) | ||||
| 	} | ||||
| 	// execute
 | ||||
| 	_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).CancelUnbondingDelegation(ctx, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// emit events
 | ||||
| 	return method.Outputs.Pack() | ||||
| } | ||||
							
								
								
									
										485
									
								
								precompiles/staking/tx_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										485
									
								
								precompiles/staking/tx_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,485 @@ | ||||
| package staking_test | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"math/big" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"cosmossdk.io/math" | ||||
| 	stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/evmos/ethermint/x/evm/statedb" | ||||
| ) | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestCreateValidator() { | ||||
| 	method := stakingprecompile.StakingFunctionCreateValidator | ||||
| 	description := stakingprecompile.Description{ | ||||
| 		Moniker:         "test node", | ||||
| 		Identity:        "test node identity", | ||||
| 		Website:         "http://test.node.com", | ||||
| 		SecurityContact: "test node security contract", | ||||
| 		Details:         "test node details", | ||||
| 	} | ||||
| 	commission := stakingprecompile.CommissionRates{ | ||||
| 		Rate:          math.LegacyOneDec().BigInt(), | ||||
| 		MaxRate:       math.LegacyOneDec().BigInt(), | ||||
| 		MaxChangeRate: math.LegacyOneDec().BigInt(), | ||||
| 	} | ||||
| 	minSelfDelegation := big.NewInt(1) | ||||
| 	pubkey := "eh/aR8BGUBIYI/Ust0NVBxZafLDAm7344F9dKzZU+7g=" | ||||
| 	value := big.NewInt(100000000) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| 		malleate      func() []byte | ||||
| 		gas           uint64 | ||||
| 		callerAddress *common.Address | ||||
| 		postCheck     func(data []byte) | ||||
| 		expError      bool | ||||
| 		errContains   string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - ErrPubKeyInvalidLength", | ||||
| 			func() []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					description, | ||||
| 					commission, | ||||
| 					minSelfDelegation, | ||||
| 					s.signerOne.HexAddr, | ||||
| 					value, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func([]byte) {}, | ||||
| 			true, | ||||
| 			stakingprecompile.ErrPubKeyInvalidLength, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func() []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					description, | ||||
| 					commission, | ||||
| 					minSelfDelegation, | ||||
| 					pubkey, | ||||
| 					value, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func(data []byte) {}, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) | ||||
| 			s.stakingKeeper.ApplyAndReturnValidatorSetUpdates(s.Ctx) | ||||
| 
 | ||||
| 			if tc.expError { | ||||
| 				s.Require().ErrorContains(err, tc.errContains) | ||||
| 				s.Require().Empty(bz) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				// query the validator in the staking keeper
 | ||||
| 				validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr) | ||||
| 				s.Require().NoError(err) | ||||
| 
 | ||||
| 				s.Require().NotNil(validator, "expected validator not to be nil") | ||||
| 				tc.postCheck(bz) | ||||
| 
 | ||||
| 				isBonded := validator.IsBonded() | ||||
| 				s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", true, isBonded) | ||||
| 
 | ||||
| 				consPubKey, err := validator.ConsPubKey() | ||||
| 				s.Require().NoError(err) | ||||
| 				consPubKeyBase64 := base64.StdEncoding.EncodeToString(consPubKey.Bytes()) | ||||
| 				s.Require().Equal(pubkey, consPubKeyBase64, "expected validator pubkey to be %s; got %s", pubkey, consPubKeyBase64) | ||||
| 
 | ||||
| 				operator := validator.GetOperator() | ||||
| 				s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator) | ||||
| 
 | ||||
| 				commissionRate := validator.GetCommission() | ||||
| 				s.Require().Equal(commission.Rate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", commission.Rate.String(), commissionRate.String()) | ||||
| 
 | ||||
| 				valMinSelfDelegation := validator.GetMinSelfDelegation() | ||||
| 				s.Require().Equal(minSelfDelegation.String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String()) | ||||
| 
 | ||||
| 				moniker := validator.GetMoniker() | ||||
| 				s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker) | ||||
| 
 | ||||
| 				jailed := validator.IsJailed() | ||||
| 				s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestEditValidator() { | ||||
| 	method := stakingprecompile.StakingFunctionEditValidator | ||||
| 	description := stakingprecompile.Description{ | ||||
| 		Moniker:         "test node", | ||||
| 		Identity:        "test node identity", | ||||
| 		Website:         "http://test.node.com", | ||||
| 		SecurityContact: "test node security contract", | ||||
| 		Details:         "test node details", | ||||
| 	} | ||||
| 	newRate := math.LegacyOneDec().BigInt() | ||||
| 	newRate.Div(newRate, big.NewInt(2)) | ||||
| 	minSelfDelegation := big.NewInt(2) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| 		malleate      func() []byte | ||||
| 		gas           uint64 | ||||
| 		callerAddress *common.Address | ||||
| 		postCheck     func(data []byte) | ||||
| 		expError      bool | ||||
| 		errContains   string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func() []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					description, | ||||
| 					stakingprecompile.NullableUint{ | ||||
| 						IsNull: false, | ||||
| 						Value:  newRate, | ||||
| 					}, | ||||
| 					stakingprecompile.NullableUint{ | ||||
| 						IsNull: true, | ||||
| 						Value:  math.LegacyOneDec().BigInt(), | ||||
| 					}, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func(data []byte) {}, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			s.setupValidator(s.signerOne) | ||||
| 			// move block time forward
 | ||||
| 			s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) | ||||
| 			s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expError { | ||||
| 				s.Require().ErrorContains(err, tc.errContains) | ||||
| 				s.Require().Empty(bz) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				// query the validator in the staking keeper
 | ||||
| 				validator := s.StakingKeeper.Validator(s.Ctx, s.signerOne.ValAddr) | ||||
| 				s.Require().NoError(err) | ||||
| 
 | ||||
| 				s.Require().NotNil(validator, "expected validator not to be nil") | ||||
| 				tc.postCheck(bz) | ||||
| 
 | ||||
| 				isBonded := validator.IsBonded() | ||||
| 				s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", false, isBonded) | ||||
| 
 | ||||
| 				operator := validator.GetOperator() | ||||
| 				s.Require().Equal(s.signerOne.ValAddr, operator, "expected validator operator to be %s; got %s", s.signerOne.ValAddr, operator) | ||||
| 
 | ||||
| 				commissionRate := validator.GetCommission() | ||||
| 				s.Require().Equal(newRate.String(), commissionRate.BigInt().String(), "expected validator commission rate to be %s; got %s", newRate.String(), commissionRate.String()) | ||||
| 
 | ||||
| 				valMinSelfDelegation := validator.GetMinSelfDelegation() | ||||
| 				s.Require().Equal(big.NewInt(1).String(), valMinSelfDelegation.String(), "expected validator min self delegation to be %s; got %s", minSelfDelegation.String(), valMinSelfDelegation.String()) | ||||
| 
 | ||||
| 				moniker := validator.GetMoniker() | ||||
| 				s.Require().Equal(description.Moniker, moniker, "expected validator moniker to be %s; got %s", description.Moniker, moniker) | ||||
| 
 | ||||
| 				jailed := validator.IsJailed() | ||||
| 				s.Require().Equal(false, jailed, "expected validator jailed to be %t; got %t", false, jailed) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestDelegate() { | ||||
| 	method := stakingprecompile.StakingFunctionDelegate | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| 		malleate      func(valAddr string) []byte | ||||
| 		gas           uint64 | ||||
| 		callerAddress *common.Address | ||||
| 		postCheck     func(valAddr sdk.ValAddress) | ||||
| 		expError      bool | ||||
| 		errContains   string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(valAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					valAddr, | ||||
| 					big.NewInt(1000000), | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func(valAddr sdk.ValAddress) { | ||||
| 				d, found := s.stakingKeeper.GetDelegation(s.Ctx, s.signerOne.AccAddr, valAddr) | ||||
| 				s.Assert().EqualValues(found, true) | ||||
| 				s.Assert().EqualValues(d.ValidatorAddress, valAddr.String()) | ||||
| 				s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String()) | ||||
| 
 | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("delegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 
 | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expError { | ||||
| 				s.Require().ErrorContains(err, tc.errContains) | ||||
| 				s.Require().Empty(bz) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				tc.postCheck(operatorAddress) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestBeginRedelegate() { | ||||
| 	method := stakingprecompile.StakingFunctionBeginRedelegate | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| 		malleate      func(srcAddr, dstAddr string) []byte | ||||
| 		gas           uint64 | ||||
| 		callerAddress *common.Address | ||||
| 		postCheck     func(data []byte, srcAddr, dstAddr sdk.ValAddress) | ||||
| 		expError      bool | ||||
| 		errContains   string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(srcAddr, dstAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					srcAddr, | ||||
| 					dstAddr, | ||||
| 					big.NewInt(1000000), | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func(data []byte, srcAddr, dstAddr sdk.ValAddress) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 
 | ||||
| 				d, found := s.stakingKeeper.GetRedelegation(s.Ctx, s.signerOne.AccAddr, srcAddr, dstAddr) | ||||
| 				s.Assert().EqualValues(found, true) | ||||
| 				s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String()) | ||||
| 				s.Assert().EqualValues(d.ValidatorSrcAddress, srcAddr.String()) | ||||
| 				s.Assert().EqualValues(d.ValidatorDstAddress, dstAddr.String()) | ||||
| 
 | ||||
| 				completionTime := out[0].(*big.Int) | ||||
| 				params := s.stakingKeeper.GetParams(s.Ctx) | ||||
| 				s.Assert().EqualValues(completionTime.Int64(), s.Ctx.BlockHeader().Time.Add(params.UnbondingTime).UTC().Unix()) | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("redelegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 			operatorAddress, err := s.firstBondedValidator() | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			// move block time forward
 | ||||
| 			s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) | ||||
| 			s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) | ||||
| 
 | ||||
| 			s.setupValidator(s.signerOne) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String(), operatorAddress.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expError { | ||||
| 				s.Require().ErrorContains(err, tc.errContains) | ||||
| 				s.Require().Empty(bz) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				tc.postCheck(bz, s.signerOne.ValAddr, operatorAddress) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestUndelegate() { | ||||
| 	method := stakingprecompile.StakingFunctionUndelegate | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| 		malleate      func(valAddr string) []byte | ||||
| 		gas           uint64 | ||||
| 		callerAddress *common.Address | ||||
| 		postCheck     func(data []byte, valAddr sdk.ValAddress) | ||||
| 		expError      bool | ||||
| 		errContains   string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(valAddr string) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					valAddr, | ||||
| 					big.NewInt(1000000), | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func(data []byte, valAddr sdk.ValAddress) { | ||||
| 				out, err := s.abi.Methods[method].Outputs.Unpack(data) | ||||
| 				s.Require().NoError(err, "failed to unpack output") | ||||
| 
 | ||||
| 				d, found := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, valAddr) | ||||
| 				s.Assert().EqualValues(found, true) | ||||
| 				s.Assert().EqualValues(d.DelegatorAddress, s.signerOne.AccAddr.String()) | ||||
| 				s.Assert().EqualValues(d.ValidatorAddress, valAddr.String()) | ||||
| 
 | ||||
| 				completionTime := out[0].(*big.Int) | ||||
| 				params := s.stakingKeeper.GetParams(s.Ctx) | ||||
| 				s.Assert().EqualValues(completionTime.Int64(), s.Ctx.BlockHeader().Time.Add(params.UnbondingTime).UTC().Unix()) | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("redelegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 
 | ||||
| 			// move block time forward
 | ||||
| 			s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) | ||||
| 			s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) | ||||
| 
 | ||||
| 			s.setupValidator(s.signerOne) | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String()), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expError { | ||||
| 				s.Require().ErrorContains(err, tc.errContains) | ||||
| 				s.Require().Empty(bz) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				tc.postCheck(bz, s.signerOne.ValAddr) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *StakingTestSuite) TestCancelUnbondingDelegation() { | ||||
| 	method := stakingprecompile.StakingFunctionCancelUnbondingDelegation | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| 		malleate      func(valAddr string, height *big.Int) []byte | ||||
| 		gas           uint64 | ||||
| 		callerAddress *common.Address | ||||
| 		postCheck     func(valAddr sdk.ValAddress) | ||||
| 		expError      bool | ||||
| 		errContains   string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success", | ||||
| 			func(valAddr string, height *big.Int) []byte { | ||||
| 				input, err := s.abi.Pack( | ||||
| 					method, | ||||
| 					valAddr, | ||||
| 					big.NewInt(1), | ||||
| 					height, | ||||
| 				) | ||||
| 				s.Assert().NoError(err) | ||||
| 				return input | ||||
| 			}, | ||||
| 			200000, | ||||
| 			nil, | ||||
| 			func(valAddr sdk.ValAddress) { | ||||
| 				_, found := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, valAddr) | ||||
| 				s.Assert().EqualValues(found, false) | ||||
| 				// jsonData, _ := json.MarshalIndent(d, "", "    ")
 | ||||
| 				// fmt.Printf("redelegation: %s\n", string(jsonData))
 | ||||
| 			}, | ||||
| 			false, | ||||
| 			"", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		s.Run(tc.name, func() { | ||||
| 			s.SetupTest() | ||||
| 
 | ||||
| 			// move block time forward
 | ||||
| 			s.Ctx = s.Ctx.WithBlockTime(time.Now().Add(time.Hour * 100)) | ||||
| 			s.Statedb = statedb.New(s.Ctx, s.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(s.Ctx.HeaderHash().Bytes()))) | ||||
| 
 | ||||
| 			s.setupValidator(s.signerOne) | ||||
| 			// unbond
 | ||||
| 			_, err := s.stakingKeeper.Undelegate(s.Ctx, s.signerOne.AccAddr, s.signerOne.ValAddr, sdk.NewDec(1)) | ||||
| 			s.Require().NoError(err) | ||||
| 
 | ||||
| 			u, _ := s.stakingKeeper.GetUnbondingDelegation(s.Ctx, s.signerOne.AccAddr, s.signerOne.ValAddr) | ||||
| 			height := u.Entries[0].CreationHeight | ||||
| 
 | ||||
| 			bz, err := s.runTx(tc.malleate(s.signerOne.ValAddr.String(), big.NewInt(height)), s.signerOne, 10000000) | ||||
| 
 | ||||
| 			if tc.expError { | ||||
| 				s.Require().ErrorContains(err, tc.errContains) | ||||
| 				s.Require().Empty(bz) | ||||
| 			} else { | ||||
| 				s.Require().NoError(err) | ||||
| 				tc.postCheck(s.signerOne.ValAddr) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										602
									
								
								precompiles/staking/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										602
									
								
								precompiles/staking/types.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,602 @@ | ||||
| package staking | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	"cosmossdk.io/math" | ||||
| 	precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" | ||||
| 	codectypes "github.com/cosmos/cosmos-sdk/codec/types" | ||||
| 	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" | ||||
| 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	query "github.com/cosmos/cosmos-sdk/types/query" | ||||
| 	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| ) | ||||
| 
 | ||||
| type Commission = struct { | ||||
| 	CommissionRates CommissionRates `json:"commissionRates"` | ||||
| 	UpdateTime      *big.Int        `json:"updateTime"` | ||||
| } | ||||
| 
 | ||||
| type CommissionRates = struct { | ||||
| 	Rate          *big.Int `json:"rate"` | ||||
| 	MaxRate       *big.Int `json:"maxRate"` | ||||
| 	MaxChangeRate *big.Int `json:"maxChangeRate"` | ||||
| } | ||||
| 
 | ||||
| type Delegation = struct { | ||||
| 	DelegatorAddress string   `json:"delegatorAddress"` | ||||
| 	ValidatorAddress string   `json:"validatorAddress"` | ||||
| 	Shares           *big.Int `json:"shares"` | ||||
| } | ||||
| 
 | ||||
| type DelegationResponse = struct { | ||||
| 	Delegation Delegation `json:"delegation"` | ||||
| 	Balance    *big.Int   `json:"balance"` | ||||
| } | ||||
| 
 | ||||
| type Description = struct { | ||||
| 	Moniker         string `json:"moniker"` | ||||
| 	Identity        string `json:"identity"` | ||||
| 	Website         string `json:"website"` | ||||
| 	SecurityContact string `json:"securityContact"` | ||||
| 	Details         string `json:"details"` | ||||
| } | ||||
| 
 | ||||
| type NullableUint = struct { | ||||
| 	IsNull bool     `json:"isNull"` | ||||
| 	Value  *big.Int `json:"value"` | ||||
| } | ||||
| 
 | ||||
| type PageRequest = struct { | ||||
| 	Key        []byte `json:"key"` | ||||
| 	Offset     uint64 `json:"offset"` | ||||
| 	Limit      uint64 `json:"limit"` | ||||
| 	CountTotal bool   `json:"countTotal"` | ||||
| 	Reverse    bool   `json:"reverse"` | ||||
| } | ||||
| 
 | ||||
| type PageResponse = struct { | ||||
| 	NextKey []byte `json:"nextKey"` | ||||
| 	Total   uint64 `json:"total"` | ||||
| } | ||||
| 
 | ||||
| type Params = struct { | ||||
| 	UnbondingTime     int64    `json:"unbondingTime"` | ||||
| 	MaxValidators     uint32   `json:"maxValidators"` | ||||
| 	MaxEntries        uint32   `json:"maxEntries"` | ||||
| 	HistoricalEntries uint32   `json:"historicalEntries"` | ||||
| 	BondDenom         string   `json:"bondDenom"` | ||||
| 	MinCommissionRate *big.Int `json:"minCommissionRate"` | ||||
| } | ||||
| 
 | ||||
| type Redelegation = struct { | ||||
| 	DelegatorAddress    string              `json:"delegatorAddress"` | ||||
| 	ValidatorSrcAddress string              `json:"validatorSrcAddress"` | ||||
| 	ValidatorDstAddress string              `json:"validatorDstAddress"` | ||||
| 	Entries             []RedelegationEntry `json:"entries"` | ||||
| } | ||||
| 
 | ||||
| type RedelegationEntry = struct { | ||||
| 	CreationHeight          int64    `json:"creationHeight"` | ||||
| 	CompletionTime          int64    `json:"completionTime"` | ||||
| 	InitialBalance          *big.Int `json:"initialBalance"` | ||||
| 	SharesDst               *big.Int `json:"sharesDst"` | ||||
| 	UnbondingId             uint64   `json:"unbondingId"` | ||||
| 	UnbondingOnHoldRefCount int64    `json:"unbondingOnHoldRefCount"` | ||||
| } | ||||
| 
 | ||||
| type RedelegationEntryResponse = struct { | ||||
| 	RedelegationEntry RedelegationEntry `json:"redelegationEntry"` | ||||
| 	Balance           *big.Int          `json:"balance"` | ||||
| } | ||||
| 
 | ||||
| type RedelegationResponse = struct { | ||||
| 	Redelegation Redelegation                `json:"redelegation"` | ||||
| 	Entries      []RedelegationEntryResponse `json:"entries"` | ||||
| } | ||||
| 
 | ||||
| type UnbondingDelegation = struct { | ||||
| 	DelegatorAddress string                     `json:"delegatorAddress"` | ||||
| 	ValidatorAddress string                     `json:"validatorAddress"` | ||||
| 	Entries          []UnbondingDelegationEntry `json:"entries"` | ||||
| } | ||||
| 
 | ||||
| type UnbondingDelegationEntry = struct { | ||||
| 	CreationHeight          int64    `json:"creationHeight"` | ||||
| 	CompletionTime          int64    `json:"completionTime"` | ||||
| 	InitialBalance          *big.Int `json:"initialBalance"` | ||||
| 	Balance                 *big.Int `json:"balance"` | ||||
| 	UnbondingId             uint64   `json:"unbondingId"` | ||||
| 	UnbondingOnHoldRefCount int64    `json:"unbondingOnHoldRefCount"` | ||||
| } | ||||
| 
 | ||||
| type Validator = struct { | ||||
| 	OperatorAddress         string      `json:"operatorAddress"` | ||||
| 	ConsensusPubkey         string      `json:"consensusPubkey"` | ||||
| 	Jailed                  bool        `json:"jailed"` | ||||
| 	Status                  uint8       `json:"status"` | ||||
| 	Tokens                  *big.Int    `json:"tokens"` | ||||
| 	DelegatorShares         *big.Int    `json:"delegatorShares"` | ||||
| 	Description             Description `json:"description"` | ||||
| 	UnbondingHeight         int64       `json:"unbondingHeight"` | ||||
| 	UnbondingTime           int64       `json:"unbondingTime"` | ||||
| 	Commission              Commission  `json:"commission"` | ||||
| 	MinSelfDelegation       *big.Int    `json:"minSelfDelegation"` | ||||
| 	UnbondingOnHoldRefCount int64       `json:"unbondingOnHoldRefCount"` | ||||
| 	UnbondingIds            []uint64    `json:"unbondingIds"` | ||||
| } | ||||
| 
 | ||||
| func convertValidator(v stakingtypes.Validator) Validator { | ||||
| 	validator := Validator{} | ||||
| 	operatorAddress, err := sdk.ValAddressFromBech32(v.OperatorAddress) | ||||
| 	if err != nil { | ||||
| 		validator.OperatorAddress = v.OperatorAddress | ||||
| 	} else { | ||||
| 		validator.OperatorAddress = common.BytesToAddress(operatorAddress.Bytes()).String() | ||||
| 	} | ||||
| 
 | ||||
| 	ed25519pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey) | ||||
| 	if !ok { | ||||
| 		validator.ConsensusPubkey = v.ConsensusPubkey.String() | ||||
| 	} else { | ||||
| 		validator.ConsensusPubkey = base64.StdEncoding.EncodeToString(ed25519pk.Bytes()) | ||||
| 	} | ||||
| 
 | ||||
| 	validator.Jailed = v.Jailed | ||||
| 	validator.Status = uint8(v.Status) | ||||
| 	validator.Tokens = v.Tokens.BigInt() | ||||
| 	validator.DelegatorShares = v.DelegatorShares.BigInt() | ||||
| 	validator.Description = Description{ | ||||
| 		Moniker:         v.Description.Moniker, | ||||
| 		Identity:        v.Description.Identity, | ||||
| 		Website:         v.Description.Website, | ||||
| 		SecurityContact: v.Description.SecurityContact, | ||||
| 		Details:         v.Description.Details, | ||||
| 	} | ||||
| 	validator.UnbondingHeight = v.UnbondingHeight | ||||
| 	validator.UnbondingTime = v.UnbondingTime.UTC().Unix() | ||||
| 	validator.Commission = Commission{ | ||||
| 		CommissionRates: convertCommissionRates(v.Commission.CommissionRates), | ||||
| 		UpdateTime:      big.NewInt(v.Commission.UpdateTime.UTC().Unix()), | ||||
| 	} | ||||
| 	validator.MinSelfDelegation = v.MinSelfDelegation.BigInt() | ||||
| 	validator.UnbondingOnHoldRefCount = v.UnbondingOnHoldRefCount | ||||
| 	validator.UnbondingIds = v.UnbondingIds | ||||
| 	return validator | ||||
| } | ||||
| 
 | ||||
| func convertQueryPageRequest(pagination PageRequest) *query.PageRequest { | ||||
| 	return &query.PageRequest{ | ||||
| 		Key:        pagination.Key, | ||||
| 		Offset:     pagination.Offset, | ||||
| 		Limit:      pagination.Limit, | ||||
| 		CountTotal: pagination.CountTotal, | ||||
| 		Reverse:    pagination.Reverse, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertPageResponse(pagination *query.PageResponse) PageResponse { | ||||
| 	if pagination == nil { | ||||
| 		return PageResponse{ | ||||
| 			NextKey: make([]byte, 0), | ||||
| 			Total:   1, | ||||
| 		} | ||||
| 	} | ||||
| 	return PageResponse{ | ||||
| 		NextKey: pagination.NextKey, | ||||
| 		Total:   pagination.Total, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertStakingDescription(description Description) stakingtypes.Description { | ||||
| 	return stakingtypes.Description{ | ||||
| 		Moniker:         description.Moniker, | ||||
| 		Identity:        description.Identity, | ||||
| 		Website:         description.Website, | ||||
| 		SecurityContact: description.SecurityContact, | ||||
| 		Details:         description.Details, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertStakingCommissionRates(commission CommissionRates) stakingtypes.CommissionRates { | ||||
| 	return stakingtypes.CommissionRates{ | ||||
| 		Rate:          precopmiles_common.BigIntToLegacyDec(commission.Rate), | ||||
| 		MaxRate:       precopmiles_common.BigIntToLegacyDec(commission.MaxRate), | ||||
| 		MaxChangeRate: precopmiles_common.BigIntToLegacyDec(commission.MaxChangeRate), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertCommissionRates(commission stakingtypes.CommissionRates) CommissionRates { | ||||
| 	return CommissionRates{ | ||||
| 		Rate:          commission.Rate.BigInt(), | ||||
| 		MaxRate:       commission.MaxRate.BigInt(), | ||||
| 		MaxChangeRate: commission.MaxChangeRate.BigInt(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertDelegation(delegation stakingtypes.Delegation) Delegation { | ||||
| 	return Delegation{ | ||||
| 		DelegatorAddress: delegation.DelegatorAddress, | ||||
| 		ValidatorAddress: delegation.ValidatorAddress, | ||||
| 		Shares:           delegation.Shares.BigInt(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertDelegationResponse(response stakingtypes.DelegationResponse) DelegationResponse { | ||||
| 	return DelegationResponse{ | ||||
| 		Delegation: convertDelegation(response.Delegation), | ||||
| 		Balance:    response.Balance.Amount.BigInt(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertUnbondingDelegationEntry(entry stakingtypes.UnbondingDelegationEntry) UnbondingDelegationEntry { | ||||
| 	return UnbondingDelegationEntry{ | ||||
| 		CreationHeight:          entry.CreationHeight, | ||||
| 		CompletionTime:          entry.CompletionTime.UTC().Unix(), | ||||
| 		InitialBalance:          entry.InitialBalance.BigInt(), | ||||
| 		Balance:                 entry.Balance.BigInt(), | ||||
| 		UnbondingId:             entry.UnbondingId, | ||||
| 		UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertUnbondingDelegation(response stakingtypes.UnbondingDelegation) UnbondingDelegation { | ||||
| 	entries := make([]UnbondingDelegationEntry, len(response.Entries)) | ||||
| 	for i, v := range response.Entries { | ||||
| 		entries[i] = convertUnbondingDelegationEntry(v) | ||||
| 	} | ||||
| 	return UnbondingDelegation{ | ||||
| 		DelegatorAddress: response.DelegatorAddress, | ||||
| 		ValidatorAddress: response.ValidatorAddress, | ||||
| 		Entries:          entries, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertRedelegationEntry(entry stakingtypes.RedelegationEntry) RedelegationEntry { | ||||
| 	return RedelegationEntry{ | ||||
| 		CreationHeight:          entry.CreationHeight, | ||||
| 		CompletionTime:          entry.CompletionTime.UTC().Unix(), | ||||
| 		InitialBalance:          entry.InitialBalance.BigInt(), | ||||
| 		SharesDst:               entry.SharesDst.BigInt(), | ||||
| 		UnbondingId:             entry.UnbondingId, | ||||
| 		UnbondingOnHoldRefCount: entry.UnbondingOnHoldRefCount, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertRedelegation(redelegation stakingtypes.Redelegation) Redelegation { | ||||
| 	entries := make([]RedelegationEntry, len(redelegation.Entries)) | ||||
| 	for i, v := range redelegation.Entries { | ||||
| 		entries[i] = convertRedelegationEntry(v) | ||||
| 	} | ||||
| 	return Redelegation{ | ||||
| 		DelegatorAddress:    redelegation.DelegatorAddress, | ||||
| 		ValidatorSrcAddress: redelegation.ValidatorSrcAddress, | ||||
| 		ValidatorDstAddress: redelegation.ValidatorDstAddress, | ||||
| 		Entries:             entries, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertRedelegationEntryResponse(response stakingtypes.RedelegationEntryResponse) RedelegationEntryResponse { | ||||
| 	return RedelegationEntryResponse{ | ||||
| 		RedelegationEntry: convertRedelegationEntry(response.RedelegationEntry), | ||||
| 		Balance:           response.Balance.BigInt(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertRedelegationResponse(response stakingtypes.RedelegationResponse) RedelegationResponse { | ||||
| 	entries := make([]RedelegationEntryResponse, len(response.Entries)) | ||||
| 	for i, v := range response.Entries { | ||||
| 		entries[i] = convertRedelegationEntryResponse(v) | ||||
| 	} | ||||
| 	return RedelegationResponse{ | ||||
| 		Redelegation: convertRedelegation(response.Redelegation), | ||||
| 		Entries:      entries, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func convertParams(params stakingtypes.Params) Params { | ||||
| 	return Params{ | ||||
| 		UnbondingTime:     int64(params.UnbondingTime.Seconds()), | ||||
| 		MaxValidators:     params.MaxValidators, | ||||
| 		MaxEntries:        params.MaxEntries, | ||||
| 		HistoricalEntries: params.HistoricalEntries, | ||||
| 		BondDenom:         params.BondDenom, | ||||
| 		MinCommissionRate: params.MinCommissionRate.BigInt(), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewMsgCreateValidator(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCreateValidator, error) { | ||||
| 	if len(args) != 5 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 5, len(args)) | ||||
| 	} | ||||
| 	description := args[0].(Description) | ||||
| 	commission := args[1].(CommissionRates) | ||||
| 	minSelfDelegation := args[2].(*big.Int) | ||||
| 
 | ||||
| 	pkstr := args[3].(string) | ||||
| 	bz, err := base64.StdEncoding.DecodeString(pkstr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var pk cryptotypes.PubKey | ||||
| 	if len(bz) == ed25519.PubKeySize { | ||||
| 		pk = &ed25519.PubKey{Key: bz} | ||||
| 	} else { | ||||
| 		return nil, errors.New(ErrPubKeyInvalidLength) | ||||
| 	} | ||||
| 	pkAny, err := codectypes.NewAnyWithValue(pk) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	value := args[4].(*big.Int) | ||||
| 	msg := &stakingtypes.MsgCreateValidator{ | ||||
| 		Description:       convertStakingDescription(description), | ||||
| 		Commission:        convertStakingCommissionRates(commission), | ||||
| 		MinSelfDelegation: math.NewIntFromBigInt(minSelfDelegation), | ||||
| 		DelegatorAddress:  sdk.AccAddress(sender.Bytes()).String(), | ||||
| 		ValidatorAddress:  sdk.ValAddress(sender.Bytes()).String(), | ||||
| 		Pubkey:            pkAny, | ||||
| 		Value:             sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(value)}, | ||||
| 	} | ||||
| 	return msg, msg.ValidateBasic() | ||||
| } | ||||
| 
 | ||||
| func NewMsgEditValidator(args []interface{}, sender common.Address) (*stakingtypes.MsgEditValidator, error) { | ||||
| 	if len(args) != 3 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args)) | ||||
| 	} | ||||
| 	description := args[0].(Description) | ||||
| 
 | ||||
| 	commissionRateNullable := args[1].(NullableUint) | ||||
| 	var commissionRate *sdk.Dec | ||||
| 	if !commissionRateNullable.IsNull { | ||||
| 		value := precopmiles_common.BigIntToLegacyDec(commissionRateNullable.Value) | ||||
| 		commissionRate = &value | ||||
| 	} | ||||
| 
 | ||||
| 	minSelfDelegationNullable := args[2].(NullableUint) | ||||
| 	var minSelfDelegation *sdk.Int | ||||
| 	if !minSelfDelegationNullable.IsNull { | ||||
| 		value := math.NewIntFromBigInt(minSelfDelegationNullable.Value) | ||||
| 		minSelfDelegation = &value | ||||
| 	} | ||||
| 
 | ||||
| 	msg := &stakingtypes.MsgEditValidator{ | ||||
| 		Description:       convertStakingDescription(description), | ||||
| 		CommissionRate:    commissionRate, | ||||
| 		ValidatorAddress:  sdk.ValAddress(sender.Bytes()).String(), | ||||
| 		MinSelfDelegation: minSelfDelegation, | ||||
| 	} | ||||
| 	return msg, msg.ValidateBasic() | ||||
| } | ||||
| 
 | ||||
| func NewMsgDelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgDelegate, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	validatorAddress := args[0].(string) | ||||
| 	amount := args[1].(*big.Int) | ||||
| 
 | ||||
| 	msg := &stakingtypes.MsgDelegate{ | ||||
| 		DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), | ||||
| 		ValidatorAddress: validatorAddress, | ||||
| 		Amount:           sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, | ||||
| 	} | ||||
| 	return msg, msg.ValidateBasic() | ||||
| } | ||||
| 
 | ||||
| func NewMsgBeginRedelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgBeginRedelegate, error) { | ||||
| 	if len(args) != 3 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args)) | ||||
| 	} | ||||
| 	validatorSrcAddress := args[0].(string) | ||||
| 	validatorDstAddress := args[1].(string) | ||||
| 	amount := args[2].(*big.Int) | ||||
| 
 | ||||
| 	msg := &stakingtypes.MsgBeginRedelegate{ | ||||
| 		DelegatorAddress:    sdk.AccAddress(sender.Bytes()).String(), | ||||
| 		ValidatorSrcAddress: validatorSrcAddress, | ||||
| 		ValidatorDstAddress: validatorDstAddress, | ||||
| 		Amount:              sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, | ||||
| 	} | ||||
| 	return msg, msg.ValidateBasic() | ||||
| } | ||||
| 
 | ||||
| func NewMsgUndelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgUndelegate, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	validatorAddress := args[0].(string) | ||||
| 	amount := args[1].(*big.Int) | ||||
| 
 | ||||
| 	msg := &stakingtypes.MsgUndelegate{ | ||||
| 		DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), | ||||
| 		ValidatorAddress: validatorAddress, | ||||
| 		Amount:           sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, | ||||
| 	} | ||||
| 	return msg, msg.ValidateBasic() | ||||
| } | ||||
| 
 | ||||
| func NewMsgCancelUnbondingDelegation(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCancelUnbondingDelegation, error) { | ||||
| 	if len(args) != 3 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 3, len(args)) | ||||
| 	} | ||||
| 	validatorAddress := args[0].(string) | ||||
| 	amount := args[1].(*big.Int) | ||||
| 	creationHeight := args[2].(*big.Int) | ||||
| 
 | ||||
| 	msg := &stakingtypes.MsgCancelUnbondingDelegation{ | ||||
| 		DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(), | ||||
| 		ValidatorAddress: validatorAddress, | ||||
| 		Amount:           sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)}, | ||||
| 		CreationHeight:   creationHeight.Int64(), | ||||
| 	} | ||||
| 	return msg, msg.ValidateBasic() | ||||
| } | ||||
| 
 | ||||
| func NewQueryValidatorsRequest(args []interface{}) (*stakingtypes.QueryValidatorsRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	status := args[0].(string) | ||||
| 	pagination := args[1].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryValidatorsRequest{ | ||||
| 		Status:     status, | ||||
| 		Pagination: convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryValidatorRequest(args []interface{}) (*stakingtypes.QueryValidatorRequest, error) { | ||||
| 	if len(args) != 1 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 1, len(args)) | ||||
| 	} | ||||
| 	validatorAddress := args[0].(string) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryValidatorRequest{ | ||||
| 		ValidatorAddr: validatorAddress, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryValidatorDelegationsRequest(args []interface{}) (*stakingtypes.QueryValidatorDelegationsRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	validatorAddr := args[0].(string) | ||||
| 	pagination := args[1].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryValidatorDelegationsRequest{ | ||||
| 		ValidatorAddr: validatorAddr, | ||||
| 		Pagination:    convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryValidatorUnbondingDelegationsRequest(args []interface{}) (*stakingtypes.QueryValidatorUnbondingDelegationsRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	validatorAddr := args[0].(string) | ||||
| 	pagination := args[1].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ | ||||
| 		ValidatorAddr: validatorAddr, | ||||
| 		Pagination:    convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryDelegationRequest(args []interface{}) (*stakingtypes.QueryDelegationRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	delegatorAddr := args[0].(string) | ||||
| 	validatorAddr := args[1].(string) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryDelegationRequest{ | ||||
| 		DelegatorAddr: delegatorAddr, | ||||
| 		ValidatorAddr: validatorAddr, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryUnbondingDelegationRequest(args []interface{}) (*stakingtypes.QueryUnbondingDelegationRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	delegatorAddr := args[0].(string) | ||||
| 	validatorAddr := args[1].(string) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryUnbondingDelegationRequest{ | ||||
| 		DelegatorAddr: delegatorAddr, | ||||
| 		ValidatorAddr: validatorAddr, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryDelegatorDelegationsRequest(args []interface{}) (*stakingtypes.QueryDelegatorDelegationsRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	delegatorAddr := args[0].(string) | ||||
| 	pagination := args[1].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryDelegatorDelegationsRequest{ | ||||
| 		DelegatorAddr: delegatorAddr, | ||||
| 		Pagination:    convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryDelegatorUnbondingDelegationsRequest(args []interface{}) (*stakingtypes.QueryDelegatorUnbondingDelegationsRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	delegatorAddr := args[0].(string) | ||||
| 	pagination := args[1].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ | ||||
| 		DelegatorAddr: delegatorAddr, | ||||
| 		Pagination:    convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryRedelegationsRequest(args []interface{}) (*stakingtypes.QueryRedelegationsRequest, error) { | ||||
| 	if len(args) != 4 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 4, len(args)) | ||||
| 	} | ||||
| 	delegatorAddress := args[0].(string) | ||||
| 	validatorSrcAddress := args[1].(string) | ||||
| 	validatorDstAddress := args[2].(string) | ||||
| 	pagination := args[3].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryRedelegationsRequest{ | ||||
| 		DelegatorAddr:    delegatorAddress, | ||||
| 		SrcValidatorAddr: validatorSrcAddress, | ||||
| 		DstValidatorAddr: validatorDstAddress, | ||||
| 		Pagination:       convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryDelegatorValidatorsRequest(args []interface{}) (*stakingtypes.QueryDelegatorValidatorsRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	delegatorAddr := args[0].(string) | ||||
| 	pagination := args[1].(PageRequest) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryDelegatorValidatorsRequest{ | ||||
| 		DelegatorAddr: delegatorAddr, | ||||
| 		Pagination:    convertQueryPageRequest(pagination), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryDelegatorValidatorRequest(args []interface{}) (*stakingtypes.QueryDelegatorValidatorRequest, error) { | ||||
| 	if len(args) != 2 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 2, len(args)) | ||||
| 	} | ||||
| 	delegatorAddr := args[0].(string) | ||||
| 	validatorAddr := args[1].(string) | ||||
| 
 | ||||
| 	return &stakingtypes.QueryDelegatorValidatorRequest{ | ||||
| 		DelegatorAddr: delegatorAddr, | ||||
| 		ValidatorAddr: validatorAddr, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryPoolRequest(args []interface{}) (*stakingtypes.QueryPoolRequest, error) { | ||||
| 	if len(args) != 0 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 0, len(args)) | ||||
| 	} | ||||
| 
 | ||||
| 	return &stakingtypes.QueryPoolRequest{}, nil | ||||
| } | ||||
| 
 | ||||
| func NewQueryParamsRequest(args []interface{}) (*stakingtypes.QueryParamsRequest, error) { | ||||
| 	if len(args) != 0 { | ||||
| 		return nil, fmt.Errorf(precopmiles_common.ErrInvalidNumberOfArgs, 0, len(args)) | ||||
| 	} | ||||
| 
 | ||||
| 	return &stakingtypes.QueryParamsRequest{}, nil | ||||
| } | ||||
| @ -1,11 +1,13 @@ | ||||
| package testutil | ||||
| 
 | ||||
| import ( | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/0glabs/0g-chain/app" | ||||
| 	"github.com/0glabs/0g-chain/chaincfg" | ||||
| 	dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners" | ||||
| 	precopmiles_common "github.com/0glabs/0g-chain/precompiles/common" | ||||
| 	"github.com/0glabs/0g-chain/x/bep3/types" | ||||
| 	"github.com/cosmos/cosmos-sdk/crypto/keyring" | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| @ -44,15 +46,25 @@ type TestSigner struct { | ||||
| 	HexAddr string | ||||
| 	PrivKey cryptotypes.PrivKey | ||||
| 	Signer  keyring.Signer | ||||
| 	ValAddr sdk.ValAddress | ||||
| 	AccAddr sdk.AccAddress | ||||
| } | ||||
| 
 | ||||
| func GenSigner() *TestSigner { | ||||
| func (suite *PrecompileTestSuite) GenSigner() *TestSigner { | ||||
| 	var s TestSigner | ||||
| 	addr, priv := emtests.NewAddrKey() | ||||
| 	s.PrivKey = priv | ||||
| 	s.Addr = addr | ||||
| 	s.HexAddr = dasignersprecompile.ToLowerHexWithoutPrefix(s.Addr) | ||||
| 	s.HexAddr = precopmiles_common.ToLowerHexWithoutPrefix(s.Addr) | ||||
| 	s.Signer = emtests.NewSigner(priv) | ||||
| 	valAddr, _ := sdk.ValAddressFromHex(s.HexAddr) | ||||
| 	accAddr, _ := sdk.AccAddressFromHexUnsafe(s.HexAddr) | ||||
| 	s.ValAddr = valAddr | ||||
| 	s.AccAddr = accAddr | ||||
| 
 | ||||
| 	// 10000 a0gi for test
 | ||||
| 	suite.App.GetBankKeeper().MintCoins(suite.Ctx, "mint", sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000)))) | ||||
| 	suite.App.GetBankKeeper().SendCoinsFromModuleToAccount(suite.Ctx, "mint", accAddr, sdk.NewCoins(chaincfg.MakeCoinForGasDenom(big.NewInt(10000000000)))) | ||||
| 	return &s | ||||
| } | ||||
| 
 | ||||
| @ -70,7 +82,7 @@ func (suite *PrecompileTestSuite) SetupTest() { | ||||
| 	hexAddr := strings.ToLower(crypto.PubkeyToAddress(key.PublicKey).Hex()[2:]) | ||||
| 	valAddr, err := sdk.ValAddressFromHex(hexAddr) | ||||
| 	suite.Assert().NoError(err) | ||||
| 	suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress}) | ||||
| 	suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress, Time: time.Now()}) | ||||
| 	newValidator, err := stakingtypes.NewValidator(valAddr, privkey.PubKey(), stakingtypes.Description{}) | ||||
| 	suite.Assert().NoError(err) | ||||
| 	err = suite.StakingKeeper.SetValidatorByConsAddr(suite.Ctx, newValidator) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 MiniFrenchBread
						MiniFrenchBread