Compare commits

..

3 Commits

Author SHA1 Message Date
MiniFrenchBread
1e4ab01bc0
Merge 605a71e826 into f2abb98d6c 2024-11-04 11:02:01 +00:00
MiniFrenchBread
605a71e826 test: tx
Some checks failed
Continuous Integration (Commit) / lint (push) Has been cancelled
2024-11-04 19:01:53 +08:00
MiniFrenchBread
1602c96a40 test: query 2024-11-04 16:20:59 +08:00
10 changed files with 1180 additions and 33 deletions

View File

@ -72,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

View File

@ -22,7 +22,6 @@ struct CommissionRates {
uint maxChangeRate; // 18 decimals
}
/**
* @dev Commission defines the commission parameters.
*/
@ -207,7 +206,7 @@ interface IStaking {
function delegate(
string memory validatorAddress,
uint amount // in bond denom
) external returns (bool success);
) external;
/**
* @dev BeginRedelegate defines a method for performing a redelegationA

View File

@ -142,13 +142,7 @@
}
],
"name": "delegate",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,12 @@
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() {
@ -63,3 +66,736 @@ func (s *StakingTestSuite) TestValidators() {
})
}
}
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)
}
})
}
}

View File

@ -1,6 +1,7 @@
package staking_test
import (
"errors"
"math/big"
"strings"
"testing"
@ -74,6 +75,48 @@ func (suite *StakingTestSuite) AddDelegation(from string, to string, amount math
})
}
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

View File

@ -2,6 +2,7 @@ package staking
import (
"fmt"
"math/big"
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -103,12 +104,12 @@ func (s *StakingPrecompile) BeginRedelegate(
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).BeginRedelegate(ctx, msg)
response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).BeginRedelegate(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix()))
}
func (s *StakingPrecompile) Undelegate(
@ -128,12 +129,12 @@ func (s *StakingPrecompile) Undelegate(
return nil, fmt.Errorf(precopmiles_common.ErrSenderNotOrigin)
}
// execute
_, err = stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Undelegate(ctx, msg)
response, err := stakingkeeper.NewMsgServerImpl(s.stakingKeeper).Undelegate(ctx, msg)
if err != nil {
return nil, err
}
// emit events
return method.Outputs.Pack()
return method.Outputs.Pack(big.NewInt(response.CompletionTime.UTC().Unix()))
}
func (s *StakingPrecompile) CancelUnbondingDelegation(

View File

@ -3,10 +3,13 @@ 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() {
@ -83,6 +86,7 @@ func (s *StakingTestSuite) TestCreateValidator() {
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)
@ -97,7 +101,7 @@ func (s *StakingTestSuite) TestCreateValidator() {
tc.postCheck(bz)
isBonded := validator.IsBonded()
s.Require().Equal(false, isBonded, "expected validator bonded to be %t; got %t", false, isBonded)
s.Require().Equal(true, isBonded, "expected validator bonded to be %t; got %t", true, isBonded)
consPubKey, err := validator.ConsPubKey()
s.Require().NoError(err)
@ -122,3 +126,360 @@ func (s *StakingTestSuite) TestCreateValidator() {
})
}
}
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)
}
})
}
}

View File

@ -181,6 +181,12 @@ func convertQueryPageRequest(pagination PageRequest) *query.PageRequest {
}
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,
@ -329,7 +335,7 @@ func NewMsgCreateValidator(args []interface{}, sender common.Address, denom stri
}
value := args[4].(*big.Int)
return &stakingtypes.MsgCreateValidator{
msg := &stakingtypes.MsgCreateValidator{
Description: convertStakingDescription(description),
Commission: convertStakingCommissionRates(commission),
MinSelfDelegation: math.NewIntFromBigInt(minSelfDelegation),
@ -337,7 +343,8 @@ func NewMsgCreateValidator(args []interface{}, sender common.Address, denom stri
ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(),
Pubkey: pkAny,
Value: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(value)},
}, nil
}
return msg, msg.ValidateBasic()
}
func NewMsgEditValidator(args []interface{}, sender common.Address) (*stakingtypes.MsgEditValidator, error) {
@ -360,12 +367,13 @@ func NewMsgEditValidator(args []interface{}, sender common.Address) (*stakingtyp
minSelfDelegation = &value
}
return &stakingtypes.MsgEditValidator{
msg := &stakingtypes.MsgEditValidator{
Description: convertStakingDescription(description),
CommissionRate: commissionRate,
ValidatorAddress: sdk.ValAddress(sender.Bytes()).String(),
MinSelfDelegation: minSelfDelegation,
}, nil
}
return msg, msg.ValidateBasic()
}
func NewMsgDelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgDelegate, error) {
@ -375,11 +383,12 @@ func NewMsgDelegate(args []interface{}, sender common.Address, denom string) (*s
validatorAddress := args[0].(string)
amount := args[1].(*big.Int)
return &stakingtypes.MsgDelegate{
msg := &stakingtypes.MsgDelegate{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: validatorAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
}, nil
}
return msg, msg.ValidateBasic()
}
func NewMsgBeginRedelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgBeginRedelegate, error) {
@ -390,12 +399,13 @@ func NewMsgBeginRedelegate(args []interface{}, sender common.Address, denom stri
validatorDstAddress := args[1].(string)
amount := args[2].(*big.Int)
return &stakingtypes.MsgBeginRedelegate{
msg := &stakingtypes.MsgBeginRedelegate{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorSrcAddress: validatorSrcAddress,
ValidatorDstAddress: validatorDstAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
}, nil
}
return msg, msg.ValidateBasic()
}
func NewMsgUndelegate(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgUndelegate, error) {
@ -405,11 +415,12 @@ func NewMsgUndelegate(args []interface{}, sender common.Address, denom string) (
validatorAddress := args[0].(string)
amount := args[1].(*big.Int)
return &stakingtypes.MsgUndelegate{
msg := &stakingtypes.MsgUndelegate{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: validatorAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
}, nil
}
return msg, msg.ValidateBasic()
}
func NewMsgCancelUnbondingDelegation(args []interface{}, sender common.Address, denom string) (*stakingtypes.MsgCancelUnbondingDelegation, error) {
@ -420,12 +431,13 @@ func NewMsgCancelUnbondingDelegation(args []interface{}, sender common.Address,
amount := args[1].(*big.Int)
creationHeight := args[2].(*big.Int)
return &stakingtypes.MsgCancelUnbondingDelegation{
msg := &stakingtypes.MsgCancelUnbondingDelegation{
DelegatorAddress: sdk.AccAddress(sender.Bytes()).String(),
ValidatorAddress: validatorAddress,
Amount: sdk.Coin{Denom: denom, Amount: math.NewIntFromBigInt(amount)},
CreationHeight: creationHeight.Int64(),
}, nil
}
return msg, msg.ValidateBasic()
}
func NewQueryValidatorsRequest(args []interface{}) (*stakingtypes.QueryValidatorsRequest, error) {

View File

@ -3,6 +3,7 @@ package testutil
import (
"math/big"
"strings"
"time"
"github.com/0glabs/0g-chain/app"
"github.com/0glabs/0g-chain/chaincfg"
@ -81,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)