@@ -56,34 +56,37 @@ func (k Keeper) Buy(ctx sdk.Context, planId string, buyer sdk.AccAddress, amount
56
56
return err
57
57
}
58
58
59
- // validate we have enough tokens to sell
59
+ // validate the IRO have enough tokens to sell
60
60
// protocol will apply max limit (99.9%) to enforce initial token liquidity
61
61
maxSellAmt := plan .TotalAllocation .Amount .ToLegacyDec ().Mul (AllocationSellLimit ).TruncateInt ()
62
62
if plan .SoldAmt .Add (amountTokensToBuy ).GT (maxSellAmt ) {
63
63
return types .ErrInsufficientTokens
64
64
}
65
65
66
- // Calculate cost over fixed price curve
66
+ // Calculate cost for buying amountTokensToBuy over fixed price curve
67
67
cost := plan .BondingCurve .Cost (plan .SoldAmt , plan .SoldAmt .Add (amountTokensToBuy ))
68
-
69
- // validate cost is positive
70
68
if ! cost .IsPositive () {
71
69
return errorsmod .Wrapf (types .ErrInvalidCost , "cost: %s" , cost .String ())
72
70
}
73
71
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
+
74
77
// Validate expected out amount
75
- if cost .GT (maxCost ) {
78
+ if totalCost . Amount .GT (maxCost ) {
76
79
return errorsmod .Wrapf (types .ErrInvalidExpectedOutAmount , "maxCost: %s, cost: %s" , maxCost .String (), cost .String ())
77
80
}
78
81
79
82
// Charge taker fee
80
- costC , err : = k .chargeTakerFee (ctx , sdk . NewCoin ( appparams . BaseDenom , cost ) , buyer )
83
+ err = k .chargeTakerFee (ctx , takerFeeCoin , buyer )
81
84
if err != nil {
82
85
return err
83
86
}
84
87
85
88
// 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 ))
87
90
if err != nil {
88
91
return err
89
92
}
@@ -126,25 +129,31 @@ func (k Keeper) Sell(ctx sdk.Context, planId string, seller sdk.AccAddress, amou
126
129
127
130
// Calculate cost over fixed price curve
128
131
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
+
129
138
// 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 ())
132
141
}
133
142
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 )
136
145
if err != nil {
137
146
return err
138
147
}
139
148
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 )) )
142
151
if err != nil {
143
152
return err
144
153
}
145
154
146
155
// 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 ))
148
157
if err != nil {
149
158
return err
150
159
}
@@ -180,28 +189,22 @@ func (k Keeper) validateIROTradeable(ctx sdk.Context, plan types.Plan, trader st
180
189
return nil
181
190
}
182
191
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
+ }
197
195
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 )
199
202
}
200
203
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
202
205
// 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 )
206
209
return sdk .NewCoin (amt .Denom , newAmt ), sdk .NewCoin (amt .Denom , takerFeeAmt )
207
210
}
0 commit comments