Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests(dist): Add ClaimRewards unit and event tests #1954

Merged
merged 5 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- (stride-outpost) [#1935](https://github.com/evmos/evmos/pull/1935) Refactor RedeemStake method.
- (osmosis-outpost) [#1921](https://github.com/evmos/evmos/pull/1921) Add Osmosis outpost types and errors.
- (distribution) [#1949](https://github.com/evmos/evmos/pull/1949) Add `ClaimRewards` custom transaction.
- (distribution) [#1954](https://github.com/evmos/evmos/pull/1954) Add `ClaimRewards` unit and event tests.
- (osmosis-outpost) [#1944](https://github.com/evmos/evmos/pull/1921) Add more validation to Osmosis outpost.

### Bug Fixes
Expand Down
21 changes: 21 additions & 0 deletions precompiles/distribution/distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ func (s *PrecompileTestSuite) TestRun() {
readOnly: false,
expPass: true,
},
{
name: "pass - claim rewards transaction",
malleate: func() (common.Address, []byte) {
valAddr, err := sdk.ValAddressFromBech32(s.validators[0].OperatorAddress)
s.Require().NoError(err)
val, _ := s.app.StakingKeeper.GetValidator(s.ctx, valAddr)
coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, sdk.NewInt(1e18)))
s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))

input, err := s.precompile.Pack(
distribution.ClaimRewardsMethod,
s.address,
uint32(2),
)
s.Require().NoError(err, "failed to pack input")

return s.address, input
},
readOnly: false,
expPass: true,
},
}

for _, tc := range testcases {
Expand Down
37 changes: 37 additions & 0 deletions precompiles/distribution/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,40 @@ func (s *PrecompileTestSuite) TestWithdrawValidatorCommissionEvent() {
}
}
}

func (s *PrecompileTestSuite) TestClaimRewardsEvent() {
testCases := []struct {
name string
coins sdk.Coins
postCheck func()
}{
{
"success",
sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, sdk.NewInt(1e18))),
func() {
log := s.stateDB.Logs()[0]
s.Require().Equal(log.Address, s.precompile.Address())
// Check event signature matches the one emitted
event := s.precompile.ABI.Events[distribution.EventTypeClaimRewards]
s.Require().Equal(event.ID, common.HexToHash(log.Topics[0].Hex()))
s.Require().Equal(log.BlockNumber, uint64(s.ctx.BlockHeight()))

var claimRewardsEvent distribution.EventClaimRewards
err := cmn.UnpackLog(s.precompile.ABI, &claimRewardsEvent, distribution.EventTypeClaimRewards, *log)
s.Require().NoError(err)
s.Require().Equal(common.BytesToAddress(s.address.Bytes()), claimRewardsEvent.DelegatorAddress)
s.Require().Equal(big.NewInt(1e18), claimRewardsEvent.Amount)
},
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
s.SetupTest()

err := s.precompile.EmitClaimRewardsEvent(s.ctx, s.stateDB, s.address, tc.coins)
s.Require().NoError(err)
tc.postCheck()
})
}
}
110 changes: 110 additions & 0 deletions precompiles/distribution/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,113 @@ func (s *PrecompileTestSuite) TestWithdrawValidatorCommission() {
})
}
}

func (s *PrecompileTestSuite) TestClaimRewards() {
method := s.precompile.Methods[distribution.ClaimRewardsMethod]

testCases := []struct {
name string
malleate func() []interface{}
postCheck func(data []byte)
gas uint64
expError bool
errContains string
}{
{
"fail - empty input args",
func() []interface{} {
return []interface{}{}
},
func(data []byte) {},
200000,
true,
fmt.Sprintf(cmn.ErrInvalidNumberOfArgs, 2, 0),
},
{
"fail - invalid delegator address",
func() []interface{} {
return []interface{}{
nil,
10,
}
},
func(data []byte) {},
200000,
true,
"invalid delegator address",
},
{
"fail - invalid type for maxRetrieve: expected uint32",
func() []interface{} {
return []interface{}{
s.address,
big.NewInt(100000000000000000),
}
},
func(data []byte) {},
200000,
true,
"invalid type for maxRetrieve: expected uint32",
},
{
"success - withdraw from all validators - 2",
func() []interface{} {
return []interface{}{
s.address,
uint32(2),
}
},
func(data []byte) {
balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
s.Require().Equal(balance.Amount.BigInt(), big.NewInt(7e18))
},
20000,
false,
"",
},
{
"success - withdraw from only 1 validator",
func() []interface{} {
return []interface{}{
s.address,
uint32(1),
}
},
func(data []byte) {
balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
s.Require().Equal(balance.Amount.BigInt(), big.NewInt(6e18))
},
20000,
false,
"",
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
s.SetupTest()

var contract *vm.Contract
contract, s.ctx = testutil.NewPrecompileContract(s.T(), s.ctx, s.address, s.precompile, tc.gas)

// Sanity check to make sure the starting balance is always 5 EVMOS
balance := s.app.BankKeeper.GetBalance(s.ctx, s.address.Bytes(), utils.BaseDenom)
s.Require().Equal(balance.Amount.BigInt(), big.NewInt(5e18))

// Distribute rewards to the 2 validators, 1 EVMOS each
for _, val := range s.validators {
coins := sdk.NewCoins(sdk.NewCoin(utils.BaseDenom, sdk.NewInt(1e18)))
s.app.DistrKeeper.AllocateTokensToValidator(s.ctx, val, sdk.NewDecCoinsFromCoins(coins...))
}

bz, err := s.precompile.ClaimRewards(s.ctx, s.address, contract, s.stateDB, &method, tc.malleate())

if tc.expError {
s.Require().ErrorContains(err, tc.errContains)
} else {
s.Require().NoError(err)
tc.postCheck(bz)
}
})
}
}
6 changes: 6 additions & 0 deletions precompiles/distribution/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ type EventWithdrawValidatorRewards struct {
Commission *big.Int
}

// EventClaimRewards defines the event data for the ClaimRewards transaction.
type EventClaimRewards struct {
DelegatorAddress common.Address
Amount *big.Int
}

// parseClaimRewardsArgs parses the arguments for the ClaimRewards method.
func parseClaimRewardsArgs(args []interface{}) (common.Address, uint32, error) {
if len(args) != 2 {
Expand Down