Skip to content

Commit 9fe5721

Browse files
authored
Refactor validator commission withdrawal (#2278)
refactor validator commission withdrawal
1 parent c310225 commit 9fe5721

4 files changed

Lines changed: 27 additions & 46 deletions

File tree

precompiles/distribution/Distribution.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ interface IDistr {
3737

3838
/// @notice Withdraws validator commission (only callable by the validator operator)
3939
/// @dev Only the validator operator can withdraw their commission
40-
/// @param validator The validator's Sei address (must match caller's validator)
4140
/// @return success True if commission was withdrawn successfully
42-
function withdrawValidatorCommission(string memory validator) external returns (bool success);
41+
function withdrawValidatorCommission() external returns (bool success);
4342

4443
// Queries
4544

precompiles/distribution/abi.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[{"inputs":[{"internalType":"address","name":"withdrawAddr","type":"address"}],"name":"setWithdrawAddress","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"validator","type":"string"}],"name":"withdrawDelegationRewards","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"validators","type":"string[]"}],"name":"withdrawMultipleDelegationRewards","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"validator","type":"string"}],"name":"withdrawValidatorCommission","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatorAddress","type":"address"}],"name":"rewards","outputs":[{"components":[{"components":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"string","name":"denom","type":"string"}],"internalType":"struct Coin[]","name":"coins","type":"tuple[]"},{"internalType":"string","name":"validator_address","type":"string"}],"internalType":"struct Reward[]","name":"rewards","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"string","name":"denom","type":"string"}],"internalType":"struct Coin[]","name":"total","type":"tuple[]"}],"internalType":"struct Rewards","name":"rewards","type":"tuple"}],"stateMutability":"view","type":"function"}]
1+
[{"inputs":[{"internalType":"address","name":"withdrawAddr","type":"address"}],"name":"setWithdrawAddress","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"validator","type":"string"}],"name":"withdrawDelegationRewards","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"validators","type":"string[]"}],"name":"withdrawMultipleDelegationRewards","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawValidatorCommission","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatorAddress","type":"address"}],"name":"rewards","outputs":[{"components":[{"components":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"string","name":"denom","type":"string"}],"internalType":"struct Coin[]","name":"coins","type":"tuple[]"},{"internalType":"string","name":"validator_address","type":"string"}],"internalType":"struct Reward[]","name":"rewards","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"string","name":"denom","type":"string"}],"internalType":"struct Coin[]","name":"total","type":"tuple[]"}],"internalType":"struct Rewards","name":"rewards","type":"tuple"}],"stateMutability":"view","type":"function"}]

precompiles/distribution/distribution.go

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,13 @@ func (p PrecompileExecutor) Execute(ctx sdk.Context, method *abi.Method, caller
9696
}
9797
return p.withdrawMultipleDelegationRewards(ctx, method, caller, args, value)
9898
case WithdrawValidatorCommissionMethod:
99+
if err = pcommon.ValidateNonPayable(value); err != nil {
100+
return nil, 0, err
101+
}
99102
if readOnly {
100103
return nil, 0, errors.New("cannot call distr precompile from staticcall")
101104
}
102-
return p.withdrawValidatorCommission(ctx, method, caller, args, value)
105+
return p.withdrawValidatorCommission(ctx, method, caller)
103106
case RewardsMethod:
104107
return p.rewards(ctx, method, args)
105108
}
@@ -339,7 +342,7 @@ func getResponseOutput(response *distrtypes.QueryDelegationTotalRewardsResponse)
339342
}
340343
}
341344

342-
func (p PrecompileExecutor) withdrawValidatorCommission(ctx sdk.Context, method *abi.Method, caller common.Address, args []interface{}, value *big.Int) (ret []byte, remainingGas uint64, rerr error) {
345+
func (p PrecompileExecutor) withdrawValidatorCommission(ctx sdk.Context, method *abi.Method, caller common.Address) (ret []byte, remainingGas uint64, rerr error) {
343346
defer func() {
344347
if err := recover(); err != nil {
345348
ret = nil
@@ -349,21 +352,22 @@ func (p PrecompileExecutor) withdrawValidatorCommission(ctx sdk.Context, method
349352
}
350353
}()
351354

352-
err := p.validateInput(value, args, 1)
353-
if err != nil {
354-
rerr = err
355+
validatorSeiAddr, found := p.evmKeeper.GetSeiAddress(ctx, caller)
356+
if !found {
357+
rerr = types.NewAssociationMissingErr(caller.Hex())
355358
return
356359
}
357360

358-
// The caller must be associated with a validator address
359-
validatorAddr, err := p.getValidatorFromArg(ctx, args[0])
361+
validatorAddr := sdk.ValAddress(validatorSeiAddr)
362+
363+
validator, err := sdk.ValAddressFromBech32(validatorAddr.String())
360364
if err != nil {
361365
rerr = err
362366
return
363367
}
364368

365369
// Call the distribution keeper to withdraw validator commission
366-
_, err = p.distrKeeper.WithdrawValidatorCommission(ctx, validatorAddr)
370+
_, err = p.distrKeeper.WithdrawValidatorCommission(ctx, validator)
367371
if err != nil {
368372
rerr = err
369373
return
@@ -373,12 +377,3 @@ func (p PrecompileExecutor) withdrawValidatorCommission(ctx sdk.Context, method
373377
remainingGas = pcommon.GetRemainingGas(ctx, p.evmKeeper)
374378
return
375379
}
376-
377-
func (p PrecompileExecutor) getValidatorFromArg(ctx sdk.Context, arg interface{}) (sdk.ValAddress, error) {
378-
validatorAddress := arg.(string)
379-
validator, err := sdk.ValAddressFromBech32(validatorAddress)
380-
if err != nil {
381-
return nil, err
382-
}
383-
return validator, nil
384-
}

precompiles/distribution/distribution_test.go

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,10 @@ func TestPrecompile_RunAndCalculateGas_SetWithdrawAddress(t *testing.T) {
850850
}
851851
}
852852

853-
type TestDistributionKeeper struct{}
853+
type TestDistributionKeeper struct {
854+
seiValAddr sdk.AccAddress
855+
t *testing.T
856+
}
854857

855858
func (tk *TestDistributionKeeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error {
856859
return nil
@@ -861,6 +864,10 @@ func (tk *TestDistributionKeeper) WithdrawDelegationRewards(ctx sdk.Context, del
861864
}
862865

863866
func (tk *TestDistributionKeeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, error) {
867+
if tk.seiValAddr != nil && tk.t != nil {
868+
require.Equal(tk.t, sdk.ValAddress(tk.seiValAddr), valAddr)
869+
}
870+
864871
return sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(50000))), nil
865872
}
866873

@@ -1205,7 +1212,7 @@ func TestWithdrawValidatorCommission_noCommissionToWithdrawRightAfterDelegation(
12051212

12061213
// Now test withdrawValidatorCommission
12071214
abi = pcommon.MustGetABI(f, "abi.json")
1208-
args, err = abi.Pack("withdrawValidatorCommission", val.String())
1215+
args, err = abi.Pack("withdrawValidatorCommission")
12091216
require.Nil(t, err)
12101217

12111218
addr = common.HexToAddress(distribution.DistrAddress)
@@ -1245,17 +1252,13 @@ func TestWithdrawValidatorCommission_UnitTest(t *testing.T) {
12451252
ctx := testApp.NewContext(false, tmtypes.Header{}).WithBlockHeight(2)
12461253
k := &testApp.EvmKeeper
12471254

1248-
// Set up the mock distribution keeper that always returns commission
1249-
mockDistrKeeper := &TestDistributionKeeper{}
1250-
1251-
// Create a validator address for testing
1252-
validatorAddress := "seivaloper1reedlc9w8p7jrpqfky4c5k90nea4p6dhk5yqgd"
1253-
12541255
// Set up caller
12551256
privKey := testkeeper.MockPrivateKey()
12561257
seiAddr, evmAddr := testkeeper.PrivateKeyToAddresses(privKey)
12571258
k.SetAddressMapping(ctx, seiAddr, evmAddr)
12581259

1260+
// Set up the mock distribution keeper that always returns commission
1261+
mockDistrKeeper := &TestDistributionKeeper{t: t, seiValAddr: seiAddr}
12591262
// Create the precompile with mock keeper
12601263
p, err := distribution.NewPrecompile(&app.PrecompileKeepers{DistributionKeeper: mockDistrKeeper, EVMKeeper: k})
12611264
require.Nil(t, err)
@@ -1264,10 +1267,6 @@ func TestWithdrawValidatorCommission_UnitTest(t *testing.T) {
12641267
withdrawMethod, err := p.ABI.MethodById(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawValidatorCommissionID)
12651268
require.Nil(t, err)
12661269

1267-
// Pack the arguments
1268-
inputs, err := withdrawMethod.Inputs.Pack(validatorAddress)
1269-
require.Nil(t, err)
1270-
12711270
// Create EVM state
12721271
stateDb := state.NewDBImpl(ctx, k, true)
12731272
evm := vm.EVM{
@@ -1280,7 +1279,7 @@ func TestWithdrawValidatorCommission_UnitTest(t *testing.T) {
12801279
&evm,
12811280
evmAddr, // caller
12821281
evmAddr, // callingContract
1283-
append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawValidatorCommissionID, inputs...), // input
1282+
append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawValidatorCommissionID), // input
12841283
1000000, // suppliedGas
12851284
big.NewInt(0), // value
12861285
nil, // hooks
@@ -1334,17 +1333,6 @@ func TestWithdrawValidatorCommission_InputValidation(t *testing.T) {
13341333
wantError bool
13351334
wantErrMsg string
13361335
}{
1337-
{
1338-
name: "empty validator address should fail",
1339-
wantError: true,
1340-
wantErrMsg: "empty address string is not allowed",
1341-
},
1342-
{
1343-
name: "invalid validator should fail",
1344-
validator: "invalidprefix1reedlc9w8p7jrpqfky4c5k90nea4p6dhk5yqgd",
1345-
wantError: true,
1346-
wantErrMsg: "decoding bech32 failed: invalid checksum (expected p7jtgl got k5yqgd)",
1347-
},
13481336
{
13491337
name: "sending value to non-payable function should fail",
13501338
validator: "seivaloper1reedlc9w8p7jrpqfky4c5k90nea4p6dhk5yqgd",
@@ -1371,15 +1359,14 @@ func TestWithdrawValidatorCommission_InputValidation(t *testing.T) {
13711359
for _, tc := range testCases {
13721360
t.Run(tc.name, func(t *testing.T) {
13731361
// Pack the arguments
1374-
inputs, err := withdrawMethod.Inputs.Pack(tc.validator)
13751362
require.Nil(t, err)
13761363

13771364
// Call the precompile
13781365
ret, remainingGas, err := p.RunAndCalculateGas(
13791366
&baseEvm,
13801367
evmAddr, // caller
13811368
evmAddr, // callingContract
1382-
append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawValidatorCommissionID, inputs...), // input
1369+
append(p.GetExecutor().(*distribution.PrecompileExecutor).WithdrawValidatorCommissionID), // input
13831370
1000000, // suppliedGas
13841371
tc.value, // value
13851372
nil, // hooks

0 commit comments

Comments
 (0)