-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e308e44
commit 759d08a
Showing
8 changed files
with
331 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package staking_test | ||
|
||
import ( | ||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
query "github.com/cosmos/cosmos-sdk/types/query" | ||
) | ||
|
||
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) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package staking_test | ||
|
||
import ( | ||
"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) 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)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package staking_test | ||
|
||
import ( | ||
"encoding/base64" | ||
"math/big" | ||
|
||
"cosmossdk.io/math" | ||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking" | ||
"github.com/ethereum/go-ethereum/common" | ||
) | ||
|
||
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) | ||
|
||
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(false, isBonded, "expected validator bonded to be %t; got %t", false, 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) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.