Skip to content

Commit

Permalink
Make amount claimable constant across airdrop epochs (#363)
Browse files Browse the repository at this point in the history
## Context and purpose of the change

During each period, a user should be able to claim a fixed number of tokens, relative to the total number of tokens claimable in a period. Currently, users can claim less tokens after each successive claim, because the formula for claims is
```
claimable = distributor_balance * weight
```
Instead, we should allow claims like so
```
claimable = max_claimable_in_period * weight
```

To accomplish this, we add a variable to each airdrop `ClaimedSoFar`. Then, when a user claims, they claim relative to the pool like so
```
max_claimable = distributor_balance + claimed_so_far
```
This accounts for the case where the distributor receives more tokens - `max_claimable` will be larger (by the amount of received tokens) if tokens are sent to that address.

After each claim, we increment `ClaimedSoFar` on the airdrop for which tokens were claimed.

Finally, after each epoch, we set `ClaimedSoFar` to 0.

NOTE: This also updates `ClaimFreeAmount` to claim tokens for all airdrops, removing `AirdropIdentifier` from that message.

## Brief Changelog

* add `claimed_so_far` to `Airdrop` proto
* `ClearClaimedStatus` -> `ResetClaimedStatus` to account for resetting `claimed_so_far`
* calculate `poolBal` using distributor balance and claimed so far
* add `AfterClaim` method to Increment `ClaimedSoFar`
* add airdrop update methods `IncrementClaimedSoFar` and `ResetClaimedSoFar`
* Clean up claims so that we can call a single keeper function to process all claims

## Tests
* update existing tests
* ResetClaimStatus
* Check that airdrop claimed amount updates after a claim
* Verify that ClaimAllCoinsForAction claims all free coins across two airdrops
* Verify IncrementClaimedSoFar and ResetClaimedSoFar work as expected

## Author's Checklist

I have...

- [ ] Run and PASSED locally all GAIA integration tests
- [ ] If the change is contentful, I either:
    - [ ] Added a new unit test OR 
    - [ ] Added test cases to existing unit tests
- [ ] OR this change is a trivial rework / code cleanup without any test coverage

If skipped any of the tests above, explain.


## Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] manually tested (if applicable)
- [ ] confirmed the author wrote unit tests for new logic
- [ ] reviewed documentation exists and is accurate


## Documentation and Release Note

  - [ ] Does this pull request introduce a new feature or user-facing behavior changes? 
  - [ ] Is a relevant changelog entry added to the `Unreleased` section in `CHANGELOG.md`?
  - [ ] This pull request updates existing proto field values (and require a backend and frontend migration)? 
  - [ ] Does this pull request change existing proto field names (and require a frontend migration)?
  How is the feature or change documented? 
      - [ ] not applicable
      - [ ] jira ticket `XXX` 
      - [ ] specification (`x/<module>/spec/`) 
      - [ ] README.md 
      - [ ] not documented
  • Loading branch information
asalzmann authored Nov 19, 2022
1 parent 6bf6bf4 commit 8ebccb4
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 179 deletions.
2 changes: 2 additions & 0 deletions proto/stride/claim/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ message Airdrop {
string claim_denom = 4;
// airdrop distribution account
string distributor_address = 5;
// ustrd tokens claimed so far in the current period
int64 claimed_so_far = 6;
}
2 changes: 0 additions & 2 deletions proto/stride/claim/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ message MsgSetAirdropAllocationsResponse {}

message MsgClaimFreeAmount {
string user = 1;
string airdrop_identifier = 2
[ (gogoproto.moretags) = "yaml:\"airdrop_identifier\"" ];
}

message MsgClaimFreeAmountResponse {
Expand Down
5 changes: 2 additions & 3 deletions x/claim/client/cli/tx_claim_free_amount.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (

func CmdClaimFreeAmount() *cobra.Command {
cmd := &cobra.Command{
Use: "claim-free-amount [airdrop-identifier]",
Use: "claim-free-amount",
Short: "Broadcast message claim-free-amount",
Args: cobra.ExactArgs(1),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
Expand All @@ -22,7 +22,6 @@ func CmdClaimFreeAmount() *cobra.Command {

msg := types.NewMsgClaimFreeAmount(
clientCtx.GetFromAddress().String(),
args[0],
)

if err := msg.ValidateBasic(); err != nil {
Expand Down
93 changes: 89 additions & 4 deletions x/claim/keeper/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,18 +177,24 @@ func (k Keeper) IsInitialPeriodPassed(ctx sdk.Context, airdropIdentifier string)
return goneTime.Seconds() >= types.DefaultVestingInitialPeriod.Seconds()
}

// ClearClaimedStatus clear users' claimed status only after initial period of vesting is passed
func (k Keeper) ClearClaimedStatus(ctx sdk.Context, airdropIdentifier string) {
// ResetClaimStatus clear users' claimed status only after initial period of vesting is passed
func (k Keeper) ResetClaimStatus(ctx sdk.Context, airdropIdentifier string) error {
if k.IsInitialPeriodPassed(ctx, airdropIdentifier) {
// first, reset the claim records
records := k.GetClaimRecords(ctx, airdropIdentifier)
for idx := range records {
records[idx].ActionCompleted = []bool{false, false, false}
}

if err := k.SetClaimRecords(ctx, records); err != nil {
panic(err)
return err
}
// then, reset the airdrop ClaimedSoFar
if err := k.ResetClaimedSoFar(ctx); err != nil {
return err
}
}
return nil
}

// ClearClaimables clear claimable amounts
Expand Down Expand Up @@ -369,11 +375,13 @@ func (k Keeper) GetClaimableAmountForAction(ctx sdk.Context, addr sdk.AccAddress
percentageForAction = types.PercentageForLiquidStake
}

poolBal, err := k.GetDistributorAccountBalance(ctx, airdropIdentifier)
distributorAccountBalance, err := k.GetDistributorAccountBalance(ctx, airdropIdentifier)
if err != nil {
return sdk.Coins{}, err
}

poolBal := distributorAccountBalance.AddAmount(sdk.NewInt(airdrop.ClaimedSoFar))

claimableAmount := poolBal.Amount.ToDec().
Mul(percentageForAction).
Mul(claimRecord.Weight).
Expand Down Expand Up @@ -441,6 +449,36 @@ func (k Keeper) GetAirdropIdentifiersForUser(ctx sdk.Context, addr sdk.AccAddres
return identifiers
}

func (k Keeper) AfterClaim(ctx sdk.Context, airdropIdentifier string, claimAmount int64) error {
// Increment ClaimedSoFar on the airdrop record
// fetch the airdrop
airdrop := k.GetAirdropByIdentifier(ctx, airdropIdentifier)
if airdrop == nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid airdrop identifier: AfterClaim")
}
// increment the claimed so far
err := k.IncrementClaimedSoFar(ctx, airdropIdentifier, claimAmount)
if err != nil {
return err
}
return nil
}

func (k Keeper) ClaimAllCoinsForAction(ctx sdk.Context, addr sdk.AccAddress, action types.Action) (sdk.Coins, error) {
// get all airdrops for the user
airdropIdentifiers := k.GetAirdropIdentifiersForUser(ctx, addr)
// claim all coins for the action
totalClaimable := sdk.Coins{}
for _, airdropIdentifier := range airdropIdentifiers {
claimable, err := k.ClaimCoinsForAction(ctx, addr, action, airdropIdentifier)
if err != nil {
return sdk.Coins{}, err
}
totalClaimable = totalClaimable.Add(claimable...)
}
return totalClaimable, nil
}

// ClaimCoins remove claimable amount entry and transfer it to user's account
func (k Keeper) ClaimCoinsForAction(ctx sdk.Context, addr sdk.AccAddress, action types.Action, airdropIdentifier string) (sdk.Coins, error) {
isPassed := k.IsInitialPeriodPassed(ctx, airdropIdentifier)
Expand Down Expand Up @@ -519,6 +557,15 @@ func (k Keeper) ClaimCoinsForAction(ctx sdk.Context, addr sdk.AccAddress, action
return claimableAmount, err
}

airdrop := k.GetAirdropByIdentifier(ctx, airdropIdentifier)
if airdrop == nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid airdrop identifier: ClaimCoinsForAction")
}
err = k.AfterClaim(ctx, airdropIdentifier, claimableAmount.AmountOf(airdrop.ClaimDenom).Int64())
if err != nil {
return nil, err
}

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeClaim,
Expand Down Expand Up @@ -564,6 +611,44 @@ func (k Keeper) CreateAirdropAndEpoch(ctx sdk.Context, distributor string, denom
return k.SetParams(ctx, params)
}

// IncrementClaimedSoFar increments ClaimedSoFar for a single airdrop
func (k Keeper) IncrementClaimedSoFar(ctx sdk.Context, identifier string, amount int64) error {
params, err := k.GetParams(ctx)
if err != nil {
panic(err)
}

if amount < 0 {
return types.ErrInvalidAmount
}

newAirdrops := []*types.Airdrop{}
for _, airdrop := range params.Airdrops {
if airdrop.AirdropIdentifier == identifier {
airdrop.ClaimedSoFar += amount
}
newAirdrops = append(newAirdrops, airdrop)
}
params.Airdrops = newAirdrops
return k.SetParams(ctx, params)
}

// ResetClaimedSoFar resets ClaimedSoFar for a all airdrops
func (k Keeper) ResetClaimedSoFar(ctx sdk.Context) error {
params, err := k.GetParams(ctx)
if err != nil {
panic(err)
}

newAirdrops := []*types.Airdrop{}
for _, airdrop := range params.Airdrops {
airdrop.ClaimedSoFar = 0
newAirdrops = append(newAirdrops, airdrop)
}
params.Airdrops = newAirdrops
return k.SetParams(ctx, params)
}

// DeleteAirdropAndEpoch deletes existing airdrop and corresponding epoch.
func (k Keeper) DeleteAirdropAndEpoch(ctx sdk.Context, identifier string) error {
params, err := k.GetParams(ctx)
Expand Down
82 changes: 39 additions & 43 deletions x/claim/keeper/claim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,19 @@ func (suite *KeeperTestSuite) TestAirdropFlow() {

addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
addr2 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
addr3 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
weight := sdk.NewDecWithPrec(50, 2)

claimRecords := []types.ClaimRecord{
{
Address: addr1.String(),
Weight: sdk.NewDecWithPrec(50, 2), // 50%
Weight: weight, // 50%
ActionCompleted: []bool{false, false, false},
AirdropIdentifier: types.DefaultAirdropIdentifier,
},
{
Address: addr2.String(),
Weight: weight, // 50%
ActionCompleted: []bool{false, false, false},
AirdropIdentifier: types.DefaultAirdropIdentifier,
},
Expand All @@ -182,37 +190,41 @@ func (suite *KeeperTestSuite) TestAirdropFlow() {

coins, err := suite.app.ClaimKeeper.GetUserTotalClaimable(suite.ctx, addr1, "stride")
suite.Require().NoError(err)
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 100_000_000)).String())
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 50_000_000)).String())

coins, err = suite.app.ClaimKeeper.GetUserTotalClaimable(suite.ctx, addr2, "stride")
suite.Require().NoError(err)
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 50_000_000)).String())

coins, err = suite.app.ClaimKeeper.GetUserTotalClaimable(suite.ctx, addr3, "stride")
suite.Require().NoError(err)
suite.Require().Equal(coins, sdk.Coins{})

// get rewards amount for free
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr1, types.ACTION_FREE, "stride")
suite.Require().NoError(err)
claimableAmountForFree := sdk.NewDecWithPrec(20, 2).
Mul(sdk.NewDec(100_000_000)).
Mul(weight).
RoundInt64() // remaining balance is 100000000, claim 20% for free
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForFree)).String())

// get rewards amount for stake
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr1, types.ACTION_DELEGATE_STAKE, "stride")
suite.Require().NoError(err)
claimableAmountForStake := sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(20, 2)).
claimableAmountForStake := sdk.NewDecWithPrec(20, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance is 100000000*(80/100), claim 20% for stake
Mul(weight).
RoundInt64() // remaining balance is 90000000, claim 20% for stake
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForStake)).String())

// get rewards amount for liquid stake
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr1, types.ACTION_LIQUID_STAKE, "stride")
suite.Require().NoError(err)
claimableAmountForLiquidStake := sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(80, 2)).
Mul(sdk.NewDecWithPrec(60, 2)).
claimableAmountForLiquidStake := sdk.NewDecWithPrec(60, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance = 100000000*(80/100)*(80/100), claim 60% for liquid stake
Mul(weight).
RoundInt64() // remaining balance = 80000000, claim 60% for liquid stake
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForLiquidStake)).String())

// get balance after all claim
Expand All @@ -226,15 +238,14 @@ func (suite *KeeperTestSuite) TestAirdropFlow() {

// check if claims don't vest after initial period of 3 months
suite.ctx = suite.ctx.WithBlockTime(time.Now().Add(types.DefaultVestingInitialPeriod))
suite.app.ClaimKeeper.ClearClaimedStatus(suite.ctx, "stride")
err = suite.app.ClaimKeeper.ResetClaimStatus(suite.ctx, "stride")
suite.Require().NoError(err)
_, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr1, types.ACTION_LIQUID_STAKE, "stride")
suite.Require().NoError(err)
claimableAmountForLiquidStake2 := sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(80, 2)).
Mul(sdk.NewDecWithPrec(40, 2)).
Mul(sdk.NewDecWithPrec(60, 2)).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance = 100000000*(80/100)*(80/100)*(40/100), claim 60% for liquid stake
claimableAmountForLiquidStake2 := sdk.NewDecWithPrec(60, 2).
Mul(sdk.NewDec(50_000_000)).
Mul(weight).
RoundInt64() // remaining balance = 50000000*(60/100), claim 60% for liquid stake

coins = suite.app.BankKeeper.GetAllBalances(suite.ctx, addr1)
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForFree+claimableAmountForStake+claimableAmountForLiquidStake+claimableAmountForLiquidStake2)).String())
Expand Down Expand Up @@ -309,8 +320,7 @@ func (suite *KeeperTestSuite) TestMultiChainAirdropFlow() {
coins1, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr1, types.ACTION_DELEGATE_STAKE, "osmosis")
suite.Require().NoError(err)

claimableAmountForStake := sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(20, 2)).
claimableAmountForStake := sdk.NewDecWithPrec(20, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance is 100000000*(80/100), claim 20% for stake
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForStake)).String())
Expand All @@ -323,9 +333,7 @@ func (suite *KeeperTestSuite) TestMultiChainAirdropFlow() {
coins1, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr1, types.ACTION_LIQUID_STAKE, "osmosis")
suite.Require().NoError(err)

claimableAmountForLiquidStake := sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(80, 2)).
Mul(sdk.NewDecWithPrec(60, 2)).
claimableAmountForLiquidStake := sdk.NewDecWithPrec(60, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance = 100000000*(80/100)*(80/100), claim 60% for liquid stake
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForLiquidStake)).String())
Expand Down Expand Up @@ -357,55 +365,43 @@ func (suite *KeeperTestSuite) TestMultiChainAirdropFlow() {
//*********************** End of Stride, Osmosis airdrop *************************

// claim airdrops for juno users after ending stride airdrop
// get rewards amount for free (juno user)
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx.WithBlockTime(time.Now().Add(time.Hour)), addr2, types.ACTION_FREE, "juno")
suite.Require().NoError(err)
claimableAmountForFree = sdk.NewDecWithPrec(20, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance is 100000000, claim 20% for free
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForFree)).String())

// get rewards amount for stake (juno user)
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx.WithBlockTime(time.Now().Add(time.Hour)), addr2, types.ACTION_DELEGATE_STAKE, "juno")
suite.Require().NoError(err)
claimableAmountForStake = sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(20, 2)).
claimableAmountForStake = sdk.NewDecWithPrec(20, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance is 100000000*(80/100), claim 20% for stake
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForStake)).String())

// get rewards amount for liquid stake (juno user)
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx.WithBlockTime(time.Now().Add(time.Hour)), addr2, types.ACTION_LIQUID_STAKE, "juno")
suite.Require().NoError(err)
claimableAmountForLiquidStake = sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(80, 2)).
Mul(sdk.NewDecWithPrec(60, 2)).
claimableAmountForLiquidStake = sdk.NewDecWithPrec(60, 2).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance = 100000000*(80/100)*(80/100), claim 60% for liquid stake
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForLiquidStake)).String())

// get balance after all claim
coins = suite.app.BankKeeper.GetAllBalances(suite.ctx, addr2)
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForFree+claimableAmountForStake+claimableAmountForLiquidStake)).String())
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForStake+claimableAmountForLiquidStake)).String())

// after 3 years, juno users should be still able to claim
suite.ctx = suite.ctx.WithBlockTime(time.Now().Add(types.DefaultAirdropDuration))
suite.app.ClaimKeeper.ClearClaimedStatus(suite.ctx, "juno")
err = suite.app.ClaimKeeper.ResetClaimStatus(suite.ctx, "juno")
suite.Require().NoError(err)
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx, addr2, types.ACTION_FREE, "juno")
suite.Require().NoError(err)

claimableAmountForFree = sdk.NewDecWithPrec(80, 2).
Mul(sdk.NewDecWithPrec(80, 2)).
Mul(sdk.NewDecWithPrec(40, 2)).
Mul(sdk.NewDecWithPrec(20, 2)).
Mul(sdk.NewDec(100_000_000)).
RoundInt64() // remaining balance = 100000000*(80/100)*(80/100)*(40/100), claim 20% for free
claimableAmountForFree = sdk.NewDecWithPrec(20, 2).
Mul(sdk.NewDec(20_000_000)).
RoundInt64() // remaining balance = 20000000*(20/100), claim 20% for free
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, claimableAmountForFree)).String())

// after 3 years + 1 hour, juno users shouldn't be able to claim anymore
suite.ctx = suite.ctx.WithBlockTime(time.Now().Add(time.Hour).Add(types.DefaultAirdropDuration))
suite.app.ClaimKeeper.EndBlocker(suite.ctx)
suite.app.ClaimKeeper.ClearClaimedStatus(suite.ctx, "juno")
err = suite.app.ClaimKeeper.ResetClaimStatus(suite.ctx, "juno")
suite.Require().NoError(err)
coins, err = suite.app.ClaimKeeper.ClaimCoinsForAction(suite.ctx.WithBlockTime(time.Now().Add(time.Hour).Add(types.DefaultAirdropDuration)), addr2, types.ACTION_FREE, "juno")
suite.Require().NoError(err)
suite.Require().Equal(coins.String(), sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)).String())
Expand Down
5 changes: 4 additions & 1 deletion x/claim/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf
}

func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochInfo epochstypes.EpochInfo) {
k.ClearClaimedStatus(ctx, epochInfo.Identifier)
err := k.ResetClaimStatus(ctx, epochInfo.Identifier)
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to reset claim status for epoch %s: %s", epochInfo.Identifier, err.Error()))
}
}

// ________________________________________________________________________________________
Expand Down
2 changes: 1 addition & 1 deletion x/claim/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (server msgServer) ClaimFreeAmount(goCtx context.Context, msg *types.MsgCla
return nil, err
}

coins, err := server.keeper.ClaimCoinsForAction(ctx, addr, types.ACTION_FREE, msg.AirdropIdentifier)
coins, err := server.keeper.ClaimAllCoinsForAction(ctx, addr, types.ACTION_FREE)
if err != nil {
return nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions x/claim/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ var (
"airdrop with same identifier already exists")
ErrDistributorAlreadyExists = sdkerrors.Register(ModuleName, 1107,
"airdrop with same distributor already exists")
ErrInvalidAmount = sdkerrors.Register(ModuleName, 1108,
"cannot claim negative tokens")
)
Loading

0 comments on commit 8ebccb4

Please sign in to comment.