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

fix: (x/feegrant) expiration when overwriting an existing grant #11845

Merged
merged 13 commits into from
May 6, 2022
Merged
13 changes: 10 additions & 3 deletions x/feegrant/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@ func (k Keeper) GrantAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress,
key := feegrant.FeeAllowanceKey(granter, grantee)

var oldExp *time.Time
existingGrant, err := k.getGrant(ctx, grantee, granter)
if err != nil && existingGrant != nil && existingGrant.GetAllowance() != nil {
existingGrant, err := k.getGrant(ctx, granter, grantee)

// If we didn't find any grant, we don't return any error.
// All other kinds of errors are returned.
if err != nil && !sdkerrors.IsOf(err, sdkerrors.ErrNotFound) {
return err
}

if existingGrant != nil && existingGrant.GetAllowance() != nil {
grantInfo, err := existingGrant.GetGrant()
if err != nil {
return err
Expand Down Expand Up @@ -184,7 +191,7 @@ func (k Keeper) getGrant(ctx sdk.Context, granter sdk.AccAddress, grantee sdk.Ac
key := feegrant.FeeAllowanceKey(granter, grantee)
bz := store.Get(key)
if len(bz) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "fee-grant not found")
return nil, sdkerrors.ErrNotFound.Wrap("fee-grant not found")
}

var feegrant feegrant.Grant
Expand Down
114 changes: 111 additions & 3 deletions x/feegrant/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (suite *KeeperTestSuite) TestKeeperCrud() {
// some helpers
eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123))
exp := suite.sdkCtx.BlockTime().AddDate(1, 0, 0)
exp2 := suite.sdkCtx.BlockTime().AddDate(2, 0, 0)
basic := &feegrant.BasicAllowance{
SpendLimit: suite.atom,
Expiration: &exp,
Expand All @@ -56,6 +57,11 @@ func (suite *KeeperTestSuite) TestKeeperCrud() {
Expiration: &exp,
}

basic3 := &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &exp2,
}

// let's set up some initial state here
err := suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[0], suite.addrs[1], basic)
suite.Require().NoError(err)
Expand Down Expand Up @@ -85,7 +91,7 @@ func (suite *KeeperTestSuite) TestKeeperCrud() {
err = suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[0], suite.addrs[2], basic)
suite.Require().NoError(err)

err = suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[1], suite.addrs[2], basic2)
err = suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[1], suite.addrs[2], basic3)
suite.Require().NoError(err)

// end state:
Expand Down Expand Up @@ -115,7 +121,7 @@ func (suite *KeeperTestSuite) TestKeeperCrud() {
"addr modified": {
granter: suite.addrs[1],
grantee: suite.addrs[2],
allowance: basic2,
allowance: basic3,
},
}

Expand Down Expand Up @@ -265,6 +271,7 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123))
now := suite.sdkCtx.BlockTime()
oneYearExpiry := now.AddDate(1, 0, 0)
oneDay := now.AddDate(0, 0, 1)

testCases := []struct {
name string
Expand All @@ -273,6 +280,8 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
grantee sdk.AccAddress
allowance feegrant.FeeAllowanceI
expErrMsg string
preRun func()
postRun func()
}{
{
name: "grant not pruned from state",
Expand Down Expand Up @@ -326,12 +335,108 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
Expiration: &oneYearExpiry,
},
},
{
name: "grant created with a day expiry & overwritten with no expiry shouldn't be pruned: no error",
ctx: suite.sdkCtx.WithBlockTime(now.AddDate(0, 0, 2)),
granter: suite.addrs[2],
grantee: suite.addrs[1],
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
},
preRun: func() {
// create a grant with a day expiry.
allowance := &feegrant.BasicAllowance{
SpendLimit: suite.atom,
Expiration: &oneDay,
}
err := suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[2], suite.addrs[1], allowance)
suite.NoError(err)
},
postRun: func() {
_, err := suite.msgSrvr.RevokeAllowance(suite.sdkCtx, &feegrant.MsgRevokeAllowance{
Granter: suite.addrs[2].String(),
Grantee: suite.addrs[1].String(),
})
suite.NoError(err)
},
},
{
name: "grant created with a day expiry & overwritten with a year expiry shouldn't be pruned: no error",
ctx: suite.sdkCtx.WithBlockTime(now.AddDate(0, 0, 2)),
granter: suite.addrs[2],
grantee: suite.addrs[1],
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &oneYearExpiry,
},
preRun: func() {
// create a grant with a day expiry.
allowance := &feegrant.BasicAllowance{
SpendLimit: suite.atom,
Expiration: &oneDay,
}
err := suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[2], suite.addrs[1], allowance)
suite.NoError(err)
},
postRun: func() {
_, err := suite.msgSrvr.RevokeAllowance(suite.sdkCtx, &feegrant.MsgRevokeAllowance{
Granter: suite.addrs[2].String(),
Grantee: suite.addrs[1].String(),
})
suite.NoError(err)
},
},
{
name: "grant created with a year expiry & overwritten with a day expiry should be pruned after a day: error",
ctx: suite.sdkCtx.WithBlockTime(now.AddDate(0, 0, 2)),
granter: suite.addrs[2],
grantee: suite.addrs[1],
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &oneDay,
},
preRun: func() {
// create a grant with a year expiry.
allowance := &feegrant.BasicAllowance{
SpendLimit: suite.atom,
Expiration: &oneYearExpiry,
}
err := suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[2], suite.addrs[1], allowance)
suite.NoError(err)
},
postRun: func() {},
expErrMsg: "not found",
},
{
name: "grant created with no expiry & overwritten with a day expiry should be pruned after a day: error",
ctx: suite.sdkCtx.WithBlockTime(now.AddDate(0, 0, 2)),
granter: suite.addrs[2],
grantee: suite.addrs[1],
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &oneDay,
},
preRun: func() {
// create a grant with no expiry.
allowance := &feegrant.BasicAllowance{
SpendLimit: suite.atom,
}
err := suite.keeper.GrantAllowance(suite.sdkCtx, suite.addrs[2], suite.addrs[1], allowance)
suite.NoError(err)
},
postRun: func() {},
expErrMsg: "not found",
},
}

for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.keeper.GrantAllowance(suite.sdkCtx, tc.granter, tc.grantee, tc.allowance)
if tc.preRun != nil {
tc.preRun()
}
err := suite.keeper.GrantAllowance(suite.sdkCtx, tc.granter, tc.grantee, tc.allowance)
suite.NoError(err)
suite.app.FeeGrantKeeper.RemoveExpiredAllowances(tc.ctx)
grant, err := suite.keeper.GetAllowance(tc.ctx, tc.granter, tc.grantee)
if tc.expErrMsg != "" {
Expand All @@ -340,6 +445,9 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
} else {
suite.NotNil(grant)
}
if tc.postRun != nil {
tc.postRun()
}
})
}
}