-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
fix(x/accounts/default/lockup) Lockup account track undelegation when unbonding entry is mature #22254
base: main
Are you sure you want to change the base?
fix(x/accounts/default/lockup) Lockup account track undelegation when unbonding entry is mature #22254
Changes from 13 commits
4fd342f
83d300d
41a1808
a63f909
0544b0d
a37205e
e1e0ce2
b1135b6
716621a
7641b26
700ea01
0c26ac3
2eaff98
8ff7f82
f157e17
de6f925
075d9ee
9f25810
22d24c1
c990e46
8e9bde2
70e61c5
4158151
e0b096e
7e5d20e
2a8d551
4e83bc7
646c178
f9dcc39
f9d1bfb
8e3be3d
7fb8c29
ed0cbdb
1ed4b64
a7ee203
af32a94
54c8f5c
a4c8c3e
292cf01
ce829cf
be528f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ func (s *E2ETestSuite) TestContinuousLockingAccount() { | |
ctx := sdk.NewContext(app.CommitMultiStore(), false, app.Logger()).WithHeaderInfo(header.Info{ | ||
Time: currentTime, | ||
}) | ||
s.setupStakingParams(ctx, app) | ||
ownerAddrStr, err := app.AuthKeeper.AddressCodec().BytesToString(accOwner) | ||
require.NoError(t, err) | ||
s.fundAccount(app, ctx, accOwner, sdk.Coins{sdk.NewCoin("stake", math.NewInt(1000000))}) | ||
|
@@ -163,17 +164,32 @@ func (s *E2ETestSuite) TestContinuousLockingAccount() { | |
require.NoError(t, err) | ||
require.Equal(t, len(ubd.Entries), 1) | ||
|
||
// check if tracking is updated accordingly | ||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt())) | ||
// check if an entry is added | ||
unbondingEntriesResponse := s.queryUnbondingEntries(ctx, app, accountAddr) | ||
entries := unbondingEntriesResponse.UnbondingEntries | ||
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100))) | ||
require.True(t, entries[0].ValidatorAddress == val.OperatorAddress) | ||
}) | ||
|
||
// Update context time to end time | ||
ctx = ctx.WithHeaderInfo(header.Info{ | ||
Time: currentTime.Add(time.Minute), | ||
}) | ||
|
||
t.Run("ok - execute tracking unbonding entry", func(t *testing.T) { | ||
msg := &types.MsgTrackUndelegation{ | ||
Sender: ownerAddrStr, | ||
Id: 0, | ||
} | ||
err = s.executeTx(ctx, msg, app, accountAddr, accOwner) | ||
require.NoError(t, err) | ||
|
||
// check if tracking is updated accordingly | ||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt())) | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be helpful to cover the unhappy path when there is no unbonding or the unboding is not mature, yet. Personal preference: this is a big test method already. Would it make sense to have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. like spliting to multiple tests method for each actions right ? |
||
|
||
// test if tracking delegate work perfectly | ||
t.Run("ok - execute delegate message", func(t *testing.T) { | ||
msg := &types.MsgDelegate{ | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -23,6 +23,7 @@ func (s *E2ETestSuite) TestDelayedLockingAccount() { | |||||||||||||||||||||||||||
ctx := sdk.NewContext(app.CommitMultiStore(), false, app.Logger()).WithHeaderInfo(header.Info{ | ||||||||||||||||||||||||||||
Time: currentTime, | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
s.setupStakingParams(ctx, app) | ||||||||||||||||||||||||||||
ownerAddrStr, err := app.AuthKeeper.AddressCodec().BytesToString(accOwner) | ||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||
s.fundAccount(app, ctx, accOwner, sdk.Coins{sdk.NewCoin("stake", math.NewInt(1000000))}) | ||||||||||||||||||||||||||||
|
@@ -125,6 +126,27 @@ func (s *E2ETestSuite) TestDelayedLockingAccount() { | |||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||
require.Equal(t, len(ubd.Entries), 1) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// check if an entry is added | ||||||||||||||||||||||||||||
unbondingEntriesResponse := s.queryUnbondingEntries(ctx, app, accountAddr) | ||||||||||||||||||||||||||||
entries := unbondingEntriesResponse.UnbondingEntries | ||||||||||||||||||||||||||||
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100))) | ||||||||||||||||||||||||||||
require.True(t, entries[0].ValidatorAddress == val.OperatorAddress) | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent potential panic by verifying Accessing Apply this diff to fix the issue: + require.NotEmpty(t, entries)
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100)))
require.True(t, entries[0].ValidatorAddress == val.OperatorAddress) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Update context time | ||||||||||||||||||||||||||||
// After unbond time elapsed | ||||||||||||||||||||||||||||
ctx = ctx.WithHeaderInfo(header.Info{ | ||||||||||||||||||||||||||||
Time: currentTime.Add(time.Second * 11), | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use unbonding duration constant instead of hardcoding Currently, the unbonding time is hardcoded as Apply this diff: - ctx = ctx.WithHeaderInfo(header.Info{
- Time: currentTime.Add(time.Second * 11),
- })
+ unbondingDuration := /* retrieve unbonding duration from staking params */
+ ctx = ctx.WithHeaderInfo(header.Info{
+ Time: currentTime.Add(unbondingDuration),
+ }) Ensure that
|
||||||||||||||||||||||||||||
t.Run("ok - execute tracking unbonding entry", func(t *testing.T) { | ||||||||||||||||||||||||||||
msg := &types.MsgTrackUndelegation{ | ||||||||||||||||||||||||||||
Sender: ownerAddrStr, | ||||||||||||||||||||||||||||
Id: 0, | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
err = s.executeTx(ctx, msg, app, accountAddr, accOwner) | ||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage by adding cases for multiple and invalid unbonding entries The current test covers tracking a single unbonding entry with
|
||||||||||||||||||||||||||||
// check if tracking is updated accordingly | ||||||||||||||||||||||||||||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||||||||||||||||||||||||||||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -23,6 +23,7 @@ func (s *E2ETestSuite) TestPeriodicLockingAccount() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ctx := sdk.NewContext(app.CommitMultiStore(), false, app.Logger()).WithHeaderInfo(header.Info{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Time: currentTime, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
s.setupStakingParams(ctx, app) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ownerAddrStr, err := app.AuthKeeper.AddressCodec().BytesToString(accOwner) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
s.fundAccount(app, ctx, accOwner, sdk.Coins{sdk.NewCoin("stake", math.NewInt(1000000))}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -185,10 +186,11 @@ func (s *E2ETestSuite) TestPeriodicLockingAccount() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.Equal(t, len(ubd.Entries), 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// check if tracking is updated accordingly | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// check if an entry is added | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
unbondingEntriesResponse := s.queryUnbondingEntries(ctx, app, accountAddr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
entries := unbondingEntriesResponse.UnbondingEntries | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.True(t, entries[0].ValidatorAddress == val.OperatorAddress) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure unbonding entries are not empty before accessing Accessing Apply this diff to add a length check: + require.True(t, len(entries) > 0)
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100)))
require.True(t, entries[0].ValidatorAddress == val.OperatorAddress) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Update context time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -197,6 +199,20 @@ func (s *E2ETestSuite) TestPeriodicLockingAccount() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Time: currentTime.Add(time.Minute * 3), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
t.Run("ok - execute tracking unbonding entry", func(t *testing.T) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
msg := &types.MsgTrackUndelegation{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sender: ownerAddrStr, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Id: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
err = s.executeTx(ctx, msg, app, accountAddr, accOwner) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// check if tracking is updated accordingly | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid hardcoding unbonding entry ID; obtain it dynamically Currently, the unbonding entry Apply this diff to obtain the entry ID dynamically: t.Run("ok - execute tracking unbonding entry", func(t *testing.T) {
+ // Retrieve the unbonding entries to get the correct ID
+ unbondingEntriesResponse := s.queryUnbondingEntries(ctx, app, accountAddr)
+ entries := unbondingEntriesResponse.UnbondingEntries
+ require.True(t, len(entries) > 0)
+ entryID := entries[0].Id
msg := &types.MsgTrackUndelegation{
Sender: ownerAddrStr,
- Id: 0,
+ Id: entryID,
}
err = s.executeTx(ctx, msg, app, accountAddr, accOwner)
require.NoError(t, err)
// check if tracking is updated accordingly
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr)
delLocking := lockupAccountInfoResponse.DelegatedLocking
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt()))
}) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
t.Run("ok - execute delegate message", func(t *testing.T) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
msg := &types.MsgDelegate{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sender: ownerAddrStr, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -23,6 +23,7 @@ func (s *E2ETestSuite) TestPermanentLockingAccount() { | |||||||||||||||||||||||||||||||
ctx := sdk.NewContext(app.CommitMultiStore(), false, app.Logger()).WithHeaderInfo(header.Info{ | ||||||||||||||||||||||||||||||||
Time: currentTime, | ||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||
s.setupStakingParams(ctx, app) | ||||||||||||||||||||||||||||||||
ownerAddrStr, err := app.AuthKeeper.AddressCodec().BytesToString(accOwner) | ||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||
s.fundAccount(app, ctx, accOwner, sdk.Coins{sdk.NewCoin("stake", math.NewInt(1000000))}) | ||||||||||||||||||||||||||||||||
|
@@ -109,10 +110,11 @@ func (s *E2ETestSuite) TestPermanentLockingAccount() { | |||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||
require.Equal(t, len(ubd.Entries), 1) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// check if tracking is updated accordingly | ||||||||||||||||||||||||||||||||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||||||||||||||||||||||||||||||||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||||||||||||||||||||||||||||||||
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt())) | ||||||||||||||||||||||||||||||||
// check if an entry is added | ||||||||||||||||||||||||||||||||
unbondingEntriesResponse := s.queryUnbondingEntries(ctx, app, accountAddr) | ||||||||||||||||||||||||||||||||
entries := unbondingEntriesResponse.UnbondingEntries | ||||||||||||||||||||||||||||||||
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100))) | ||||||||||||||||||||||||||||||||
require.True(t, entries[0].ValidatorAddress == val.OperatorAddress) | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use Using Apply this diff: - require.True(t, entries[0].ValidatorAddress == val.OperatorAddress)
+ require.Equal(t, val.OperatorAddress, entries[0].ValidatorAddress) 📝 Committable suggestion
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check for empty unbonding entries before accessing Accessing Apply this diff to add the length check: + require.Greater(t, len(entries), 0)
require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100)))
require.Equal(t, val.OperatorAddress, entries[0].ValidatorAddress) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
s.fundAccount(app, ctx, accountAddr, sdk.Coins{sdk.NewCoin("stake", math.NewInt(1000))}) | ||||||||||||||||||||||||||||||||
|
@@ -129,4 +131,23 @@ func (s *E2ETestSuite) TestPermanentLockingAccount() { | |||||||||||||||||||||||||||||||
balance := app.BankKeeper.GetBalance(ctx, randAcc, "stake") | ||||||||||||||||||||||||||||||||
require.True(t, balance.Amount.Equal(math.NewInt(100))) | ||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// Update context time | ||||||||||||||||||||||||||||||||
ctx = ctx.WithHeaderInfo(header.Info{ | ||||||||||||||||||||||||||||||||
Time: currentTime.Add(time.Second * 11), | ||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Unbonding Time Discrepancies Detected The unbonding periods across the codebase vary and do not consistently align with the test's assumption of a maximum 10-second unbonding period. This may lead to tests failing if unbonding entries have not matured as expected.
🔗 Analysis chainVerify unbonding period before advancing context time Advancing the context time by 11 seconds assumes that the unbonding period is less than or equal to 10 seconds. Please verify that the unbonding period set in the staking parameters matches this assumption to ensure unbonding entries have matured. Run the following script to confirm the unbonding time: 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Retrieve the unbonding time from the staking parameters to verify it aligns with the test's time advancement.
# Command:
ast-grep --lang go --pattern 'UnbondingTime: $time' --json 'app.StakingKeeper.SetParams(ctx, stakingtypes.Params{ $$$ })' | jq '.[].meta.captures.time'
Length of output: 261 Script: #!/bin/bash
# Description: Search for the UnbondingTime parameter in the staking parameters setup to verify its value.
# Using ripgrep to find lines where UnbondingTime is set
rg 'UnbondingTime\s*:\s*\w+' --files-with-matches | xargs rg 'UnbondingTime\s*:\s*(\w+)'
Length of output: 1912 |
||||||||||||||||||||||||||||||||
t.Run("ok - execute tracking unbonding entry", func(t *testing.T) { | ||||||||||||||||||||||||||||||||
msg := &types.MsgTrackUndelegation{ | ||||||||||||||||||||||||||||||||
Sender: ownerAddrStr, | ||||||||||||||||||||||||||||||||
Id: 0, | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
err = s.executeTx(ctx, msg, app, accountAddr, accOwner) | ||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// check if tracking is updated accordingly | ||||||||||||||||||||||||||||||||
lockupAccountInfoResponse := s.queryLockupAccInfo(ctx, app, accountAddr) | ||||||||||||||||||||||||||||||||
delLocking := lockupAccountInfoResponse.DelegatedLocking | ||||||||||||||||||||||||||||||||
require.True(t, delLocking.AmountOf("stake").Equal(math.ZeroInt())) | ||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add test cases for multiple unbonding entries Currently, the test tracks undelegation for a single entry with |
||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -102,48 +102,23 @@ func TestContinousAccountUndelegate(t *testing.T) { | |||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test") | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
require.True(t, delLocking.Equal(math.ZeroInt())) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
startTime, err := acc.StartTime.Get(sdkCtx) | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// Update context time to unlocked half of the original locking amount | ||||||||||||||||||||||||||
sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ | ||||||||||||||||||||||||||
Time: startTime.Add(time.Minute * 1), | ||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
_, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ | ||||||||||||||||||||||||||
Sender: "owner", | ||||||||||||||||||||||||||
ValidatorAddress: "val_address", | ||||||||||||||||||||||||||
Amount: sdk.NewCoin("test", math.NewInt(6)), | ||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test") | ||||||||||||||||||||||||||
ubdSeq, err := acc.UnbondingSequence.Peek(sdkCtx) | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
require.True(t, delLocking.Equal(math.NewInt(5))) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
delFree, err := acc.DelegatedFree.Get(ctx, "test") | ||||||||||||||||||||||||||
// sequence should be the previous one | ||||||||||||||||||||||||||
ubdEntry, err := acc.UnbondEntries.Get(sdkCtx, ubdSeq-1) | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent potential underflow when accessing unbonding entries When subtracting 1 from Consider adding a check to confirm ubdSeq, err := acc.UnbondingSequence.Peek(sdkCtx)
require.NoError(t, err)
+require.True(t, ubdSeq > 0, "Unbonding sequence must be greater than zero")
// sequence should be the previous one
ubdEntry, err := acc.UnbondEntries.Get(sdkCtx, ubdSeq-1)
require.NoError(t, err) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
require.True(t, delFree.Equal(math.NewInt(1))) | ||||||||||||||||||||||||||
require.True(t, ubdEntry.Amount.Amount.Equal(math.NewInt(1))) | ||||||||||||||||||||||||||
require.True(t, ubdEntry.ValidatorAddress == "val_address") | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// Undelegate | ||||||||||||||||||||||||||
_, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ | ||||||||||||||||||||||||||
Sender: "owner", | ||||||||||||||||||||||||||
ValidatorAddress: "val_address", | ||||||||||||||||||||||||||
Amount: sdk.NewCoin("test", math.NewInt(4)), | ||||||||||||||||||||||||||
_, err = acc.TrackUndelegationEntry(sdkCtx, &lockuptypes.MsgTrackUndelegation{ | ||||||||||||||||||||||||||
Sender: "owner", | ||||||||||||||||||||||||||
Id: ubdSeq - 1, | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure valid unbonding entry ID before tracking undelegation Similar to the previous issue, when passing Add a check before calling +require.True(t, ubdSeq > 0, "Unbonding sequence must be greater than zero")
_, err = acc.TrackUndelegationEntry(sdkCtx, &lockuptypes.MsgTrackUndelegation{
Sender: "owner",
Id: ubdSeq - 1,
})
require.NoError(t, err)
|
||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
delLocking, err = acc.DelegatedLocking.Get(ctx, "test") | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
require.True(t, delLocking.Equal(math.NewInt(2))) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
delFree, err = acc.DelegatedFree.Get(ctx, "test") | ||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||
require.True(t, delFree.Equal(math.ZeroInt())) | ||||||||||||||||||||||||||
require.True(t, delLocking.Equal(math.ZeroInt())) | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add timeline validation for undelegation process The test should verify the intermediate state where funds are still locked during the unbonding period. Add assertions to check:
Example: // Check intermediate state
delLocking, err = acc.DelegatedLocking.Get(ctx, "test")
require.NoError(t, err)
require.True(t, delLocking.Equal(math.NewInt(1))) // Should still be locked
// Advance time to maturity
sdkCtx = sdkCtx.WithHeaderInfo(header.Info{
Time: ubdEntry.CompletionTime,
})
// Update undelegation entry after maturity
_, err = acc.UpdateUndelegationEntry(sdkCtx, &lockuptypes.MsgUpdateUndelegationEntry{
Sender: "owner",
Id: ubdSeq - 1,
})
require.NoError(t, err)
// Now verify zero locking amount
delLocking, err = acc.DelegatedLocking.Get(ctx, "test")
require.NoError(t, err)
require.True(t, delLocking.Equal(math.ZeroInt())) |
||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
func TestContinousAccountSendCoins(t *testing.T) { | ||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,4 +149,5 @@ func (dva DelayedLockingAccount) RegisterExecuteHandlers(builder *accountstd.Exe | |
|
||
func (dva DelayedLockingAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) { | ||
accountstd.RegisterQueryHandler(builder, dva.QueryVestingAccountInfo) | ||
accountstd.RegisterQueryHandler(builder, dva.QueryUnbondingEntries) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification 🔍 Missing Implementation of The
🔗 Analysis chainLGTM. Verify the implementation of QueryUnbondingEntries. The addition of the Please run the following script to verify the existence and implementation of the If the method is not found or the types are not defined, please implement them to ensure the newly added query handler functions correctly. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Verify the implementation of QueryUnbondingEntries method
# Test: Search for the QueryUnbondingEntries method implementation
ast-grep --lang go --pattern $'func (dva DelayedLockingAccount) QueryUnbondingEntries(ctx context.Context, req *lockuptypes.QueryUnbondingEntriesRequest) (*lockuptypes.QueryUnbondingEntriesResponse, error) {
$$$
}'
# Test: Check if the QueryUnbondingEntriesRequest and QueryUnbondingEntriesResponse types are defined
rg --type go -e 'type QueryUnbondingEntriesRequest struct' -e 'type QueryUnbondingEntriesResponse struct'
Length of output: 693 |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent potential index out-of-range panic when accessing
entries[0]
.Before accessing
entries[0]
, add a check to ensure that theentries
slice is not empty. This avoids a possible runtime panic if the slice is empty.Apply this diff to add the necessary check:
+ require.NotEmpty(t, entries) require.True(t, entries[0].Amount.Amount.Equal(math.NewInt(100))) require.True(t, entries[0].ValidatorAddress == val.OperatorAddress)
📝 Committable suggestion