diff --git a/precompiles/dasigners/dasigners_test.go b/precompiles/dasigners/dasigners_test.go index e9da44fd..a1d356bc 100644 --- a/precompiles/dasigners/dasigners_test.go +++ b/precompiles/dasigners/dasigners_test.go @@ -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 diff --git a/precompiles/staking/query_test.go b/precompiles/staking/query_test.go index db9bb0e3..093446d7 100644 --- a/precompiles/staking/query_test.go +++ b/precompiles/staking/query_test.go @@ -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) + } + }) + } +} diff --git a/precompiles/staking/staking_test.go b/precompiles/staking/staking_test.go index 86c7afac..e2e69c7a 100644 --- a/precompiles/staking/staking_test.go +++ b/precompiles/staking/staking_test.go @@ -1,6 +1,7 @@ package staking_test import ( + "errors" "math/big" "strings" "testing" @@ -74,6 +75,46 @@ 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) +} + +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 diff --git a/precompiles/staking/types.go b/precompiles/staking/types.go index dcd50569..8a4941f1 100644 --- a/precompiles/staking/types.go +++ b/precompiles/staking/types.go @@ -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,