@@ -257,25 +257,55 @@ func (k Keeper) calculatePayouts(ctx sdk.Context, poolId uint64, totalPayout sdk
257257 return
258258 }
259259
260- // subtract storage cost from remaining total payout. We split the storage cost between all coins and charge
261- // the amount per coin, the idea is that every coin should contribute the same USD value to the total storage
262- // reward. This is done by defining the storage cost as USD / byte and the coin weights as USD / coin denom .
260+ // subtract storage cost from remaining total payout. We first try to cover the storage cost with the
261+ // native $KYVE coin, if that is not enough the remaining USD value is split equally between the remaining
262+ // coins .
263263 //
264264 // If there is not enough of a coin available to cover the storage reward per coin we simply charge what is left,
265265 // so there can be the case that the storageRewards are less than what we actually wanted to pay out. This is
266266 // acceptable because this case is very rare, usually the minFundingAmount ensures that there are always enough
267267 // funds left of each coin, and in the case there are not enough the coins are removed and therefore for the
268268 // next bundle we split between the other remaining coins.
269269 whitelist := k .fundersKeeper .GetCoinWhitelistMap (ctx )
270+ storageCost := k .GetStorageCost (ctx , bundleProposal .StorageProviderId ).MulInt64 (int64 (bundleProposal .DataSize ))
271+
272+ kyveWeight := whitelist [globalTypes .Denom ].CoinWeight
273+ kyveCurrencyUnit := math .LegacyNewDec (10 ).Power (uint64 (whitelist [globalTypes .Denom ].CoinDecimals ))
274+
275+ if ! kyveWeight .IsZero () {
276+ kyveAmount := sdk .NewCoins (sdk .NewCoin (globalTypes .Denom , storageCost .Mul (kyveWeight ).Quo (kyveCurrencyUnit ).TruncateInt ()))
277+ bundleReward .UploaderStorageCost = totalPayout .Min (kyveAmount )
278+ totalPayout = totalPayout .Sub (bundleReward .UploaderStorageCost ... )
279+ if totalPayout .IsZero () {
280+ return
281+ }
282+
283+ // calculate how much of the storage reward was initially paid with native
284+ // kyve and give the remainder to the other coins
285+ storageCostPaid := bundleReward .UploaderStorageCost .AmountOf (globalTypes .Denom )
286+ storageCostPaidUsd := math .LegacyNewDec (storageCostPaid .Int64 ()).Mul (kyveCurrencyUnit ).Quo (kyveWeight )
287+
288+ if storageCost .GTE (storageCostPaidUsd ) {
289+ storageCost = storageCost .Sub (storageCostPaidUsd )
290+ }
291+ }
292+
293+ // get the amount of non-native $KYVE coins
294+ storageCostCoinsLength := int64 (totalPayout .Len ())
295+ if found , _ := totalPayout .Find (globalTypes .Denom ); found {
296+ storageCostCoinsLength --
297+ }
298+
270299 // wantedStorageRewards are the amounts based on the current storage cost we want to pay out, this can be more
271300 // than we have available in totalPayout
272301 wantedStorageRewards := sdk .NewCoins ()
273302 // storageCostPerCoin is the storage cost in $USD for each coin. This implies that each coin contributes the same
274303 // amount of value to the storage rewards
275- storageCostPerCoin := k . GetStorageCost ( ctx , bundleProposal . StorageProviderId ). MulInt64 ( int64 ( bundleProposal . DataSize )). QuoInt64 (int64 ( totalPayout . Len ()) )
304+ storageCostPerCoin := storageCost . QuoInt64 (storageCostCoinsLength )
276305 for _ , coin := range totalPayout {
277306 weight := whitelist [coin .Denom ].CoinWeight
278- if weight .IsZero () {
307+ // skip the native kyve denom since we already subtracted it above
308+ if coin .Denom == globalTypes .Denom || weight .IsZero () {
279309 continue
280310 }
281311
0 commit comments