Skip to content

Commit 63850d5

Browse files
committed
fixed taker fee
1 parent 16f1d74 commit 63850d5

File tree

2 files changed

+37
-33
lines changed

2 files changed

+37
-33
lines changed

ibctesting/genesis_transfer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ func (s *transferGenesisSuite) TestIRO() {
163163
transfersEnabled = s.hubApp().RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()).GenesisState.TransfersEnabled
164164
s.Require().False(transfersEnabled)
165165

166+
/* ------------------------------- happy case ------------------------------- */
166167
// genesis transfer, should pass and enable bridge
167168
msg = s.transferMsg(amt, denom, true)
168169
res, err = s.rollappChain().SendMsgs(msg)

x/iro/keeper/trade.go

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -56,34 +56,37 @@ func (k Keeper) Buy(ctx sdk.Context, planId string, buyer sdk.AccAddress, amount
5656
return err
5757
}
5858

59-
// validate we have enough tokens to sell
59+
// validate the IRO have enough tokens to sell
6060
// protocol will apply max limit (99.9%) to enforce initial token liquidity
6161
maxSellAmt := plan.TotalAllocation.Amount.ToLegacyDec().Mul(AllocationSellLimit).TruncateInt()
6262
if plan.SoldAmt.Add(amountTokensToBuy).GT(maxSellAmt) {
6363
return types.ErrInsufficientTokens
6464
}
6565

66-
// Calculate cost over fixed price curve
66+
// Calculate cost for buying amountTokensToBuy over fixed price curve
6767
cost := plan.BondingCurve.Cost(plan.SoldAmt, plan.SoldAmt.Add(amountTokensToBuy))
68-
69-
// validate cost is positive
7068
if !cost.IsPositive() {
7169
return errorsmod.Wrapf(types.ErrInvalidCost, "cost: %s", cost.String())
7270
}
7371

72+
totalCost, takerFeeCoin := k.AddTakerFee(sdk.NewCoin(appparams.BaseDenom, cost), k.GetParams(ctx).TakerFee)
73+
if !totalCost.IsPositive() || !takerFeeCoin.IsPositive() {
74+
return errorsmod.Wrapf(types.ErrInvalidCost, "totalCost: %s, takerFeeCoin: %s", totalCost.String(), takerFeeCoin.String())
75+
}
76+
7477
// Validate expected out amount
75-
if cost.GT(maxCost) {
78+
if totalCost.Amount.GT(maxCost) {
7679
return errorsmod.Wrapf(types.ErrInvalidExpectedOutAmount, "maxCost: %s, cost: %s", maxCost.String(), cost.String())
7780
}
7881

7982
// Charge taker fee
80-
costC, err := k.chargeTakerFee(ctx, sdk.NewCoin(appparams.BaseDenom, cost), buyer)
83+
err = k.chargeTakerFee(ctx, takerFeeCoin, buyer)
8184
if err != nil {
8285
return err
8386
}
8487

8588
// send DYM from buyer to the plan. DYM sent directly to the plan's module account
86-
err = k.BK.SendCoins(ctx, buyer, plan.GetAddress(), sdk.NewCoins(costC))
89+
err = k.BK.SendCoins(ctx, buyer, plan.GetAddress(), sdk.NewCoins(totalCost))
8790
if err != nil {
8891
return err
8992
}
@@ -126,25 +129,31 @@ func (k Keeper) Sell(ctx sdk.Context, planId string, seller sdk.AccAddress, amou
126129

127130
// Calculate cost over fixed price curve
128131
cost := plan.BondingCurve.Cost(plan.SoldAmt.Sub(amountTokensToSell), plan.SoldAmt)
132+
133+
totalCost, takerFeeCoin := k.SubtractTakerFee(sdk.NewCoin(appparams.BaseDenom, cost), k.GetParams(ctx).TakerFee)
134+
if !totalCost.IsPositive() || !takerFeeCoin.IsPositive() {
135+
return errorsmod.Wrapf(types.ErrInvalidCost, "totalCost: %s, takerFeeCoin: %s", totalCost.String(), takerFeeCoin.String())
136+
}
137+
129138
// Validate expected out amount
130-
if cost.LT(minCost) {
131-
return errorsmod.Wrapf(types.ErrInvalidMinCost, "minCost: %s, cost: %s", minCost.String(), cost.String())
139+
if totalCost.Amount.LT(minCost) {
140+
return errorsmod.Wrapf(types.ErrInvalidMinCost, "minCost: %s, cost: %s", minCost.String(), totalCost.String())
132141
}
133142

134-
// send allocated tokens from seller to the plan
135-
err = k.BK.SendCoinsFromAccountToModule(ctx, seller, types.ModuleName, sdk.NewCoins(sdk.NewCoin(plan.TotalAllocation.Denom, amountTokensToSell)))
143+
// Charge taker fee
144+
err = k.chargeTakerFee(ctx, takerFeeCoin, seller)
136145
if err != nil {
137146
return err
138147
}
139148

140-
// Charge taker fee
141-
costC, err := k.chargeTakerFee(ctx, sdk.NewCoin(appparams.BaseDenom, cost), seller)
149+
// send allocated tokens from seller to the plan
150+
err = k.BK.SendCoinsFromAccountToModule(ctx, seller, types.ModuleName, sdk.NewCoins(sdk.NewCoin(plan.TotalAllocation.Denom, amountTokensToSell)))
142151
if err != nil {
143152
return err
144153
}
145154

146155
// send DYM from the plan to the seller. DYM managed by the plan's module account
147-
err = k.BK.SendCoins(ctx, plan.GetAddress(), seller, sdk.NewCoins(costC))
156+
err = k.BK.SendCoins(ctx, plan.GetAddress(), seller, sdk.NewCoins(totalCost))
148157
if err != nil {
149158
return err
150159
}
@@ -180,28 +189,22 @@ func (k Keeper) validateIROTradeable(ctx sdk.Context, plan types.Plan, trader st
180189
return nil
181190
}
182191

183-
func (k Keeper) chargeTakerFee(ctx sdk.Context, cost sdk.Coin, sender sdk.AccAddress) (sdk.Coin, error) {
184-
newAmt, takerFeeCoin := k.calcTakerFee(cost, k.GetParams(ctx).TakerFee)
185-
if newAmt.IsZero() {
186-
return sdk.Coin{}, errorsmod.Wrapf(types.ErrInvalidCost, "no tokens left after taker fee")
187-
}
188-
189-
if takerFeeCoin.IsZero() {
190-
return sdk.Coin{}, errorsmod.Wrapf(types.ErrInvalidCost, "taker fee is zero")
191-
}
192-
193-
err := k.BK.SendCoinsFromAccountToModule(ctx, sender, txfeestypes.ModuleName, sdk.NewCoins(takerFeeCoin))
194-
if err != nil {
195-
return sdk.Coin{}, err
196-
}
192+
func (k Keeper) chargeTakerFee(ctx sdk.Context, takerFee sdk.Coin, sender sdk.AccAddress) error {
193+
return k.BK.SendCoinsFromAccountToModule(ctx, sender, txfeestypes.ModuleName, sdk.NewCoins(takerFee))
194+
}
197195

198-
return newAmt, nil
196+
// AddTakerFee returns the remaining amount after subtracting the taker fee and the taker fee amount
197+
// returns (1 + takerFee) * tokenIn, takerFee * tokenIn
198+
func (k Keeper) AddTakerFee(amt sdk.Coin, takerFee sdk.Dec) (sdk.Coin, sdk.Coin) {
199+
takerFeeAmt := math.LegacyNewDecFromInt(amt.Amount).Mul(takerFee).TruncateInt()
200+
newAmt := amt.Amount.Add(takerFeeAmt)
201+
return sdk.NewCoin(amt.Denom, newAmt), sdk.NewCoin(amt.Denom, takerFeeAmt)
199202
}
200203

201-
// Returns remaining amount in to swap, and takerFeeCoins.
204+
// SubtractTakerFee returns the remaining amount after subtracting the taker fee and the taker fee amount
202205
// returns (1 - takerFee) * tokenIn, takerFee * tokenIn
203-
func (k Keeper) calcTakerFee(amt sdk.Coin, takerFee sdk.Dec) (sdk.Coin, sdk.Coin) {
204-
newAmt := math.LegacyNewDecFromInt(amt.Amount).MulTruncate(sdk.OneDec().Sub(takerFee)).TruncateInt()
205-
takerFeeAmt := amt.Amount.Sub(newAmt)
206+
func (k Keeper) SubtractTakerFee(amt sdk.Coin, takerFee sdk.Dec) (sdk.Coin, sdk.Coin) {
207+
takerFeeAmt := math.LegacyNewDecFromInt(amt.Amount).Mul(takerFee).TruncateInt()
208+
newAmt := amt.Amount.Sub(takerFeeAmt)
206209
return sdk.NewCoin(amt.Denom, newAmt), sdk.NewCoin(amt.Denom, takerFeeAmt)
207210
}

0 commit comments

Comments
 (0)