mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 07:15:18 +00:00
146 lines
5.0 KiB
Go
146 lines
5.0 KiB
Go
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))
|
|
}
|