@@ -257,45 +257,80 @@ 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- // wantedStorageRewards are the amounts based on the current storage cost we want to pay out, this can be more
271- // than we have available in totalPayout
272- wantedStorageRewards := sdk .NewCoins ()
273- // storageCostPerCoin is the storage cost in $USD for each coin. This implies that each coin contributes the same
274- // amount of value to the storage rewards
275- storageCostPerCoin := k .GetStorageCost (ctx , bundleProposal .StorageProviderId ).MulInt64 (int64 (bundleProposal .DataSize )).QuoInt64 (int64 (totalPayout .Len ()))
276- for _ , coin := range totalPayout {
277- weight := whitelist [coin .Denom ].CoinWeight
278- if weight .IsZero () {
279- continue
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 found , _ := totalPayout .Find (globalTypes .Denom ); found && ! kyveWeight .IsZero () {
276+ kyveAmount := sdk .NewCoins (sdk .NewCoin (globalTypes .Denom , storageCost .Mul (kyveCurrencyUnit ).Quo (kyveWeight ).TruncateInt ()))
277+ bundleReward .UploaderStorageCost = totalPayout .Min (kyveAmount )
278+ totalPayout = totalPayout .Sub (bundleReward .UploaderStorageCost ... )
279+ if totalPayout .IsZero () {
280+ return
280281 }
281282
282- // currencyUnit is the amount of base denoms of the currency
283- currencyUnit := math .LegacyNewDec (10 ).Power (uint64 (whitelist [coin .Denom ].CoinDecimals ))
284- // amount is the value of storageCostPerCoin in the base denomination of the currency. We calculate this
285- // by multiplying first with the amount of base denoms of the currency and then divide this by the $USD
286- // value per currency unit which is the weight.
287- amount := storageCostPerCoin .Mul (currencyUnit ).Quo (weight ).TruncateInt ()
288- wantedStorageRewards = wantedStorageRewards .Add (sdk .NewCoin (coin .Denom , amount ))
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 (kyveWeight ).Quo (kyveCurrencyUnit )
287+
288+ if storageCost .GTE (storageCostPaidUsd ) {
289+ storageCost = storageCost .Sub (storageCostPaidUsd )
290+ } else {
291+ storageCost = math .LegacyZeroDec ()
292+ }
289293 }
290294
291- // we take the min here since there can be the case where we want to charge more coins for the storage
292- // reward than we have left in the total payout
293- bundleReward .UploaderStorageCost = totalPayout .Min (wantedStorageRewards )
295+ kyveCoinFound , kyveCoin := totalPayout .Find (globalTypes .Denom )
296+ remainingCoins := totalPayout
297+ if kyveCoinFound {
298+ remainingCoins = totalPayout .Sub (kyveCoin )
299+ }
300+
301+ if ! storageCost .IsZero () && int64 (remainingCoins .Len ()) > 0 {
302+ // wantedStorageRewards are the amounts based on the current storage cost we want to pay out, this can be more
303+ // than we have available in totalPayout
304+ wantedStorageRewards := sdk .NewCoins ()
305+ // storageCostPerCoin is the storage cost in $USD for each coin. This implies that each coin contributes the same
306+ // amount of value to the storage rewards
307+ storageCostPerCoin := storageCost .QuoInt64 (int64 (remainingCoins .Len ()))
308+ for _ , coin := range remainingCoins {
309+ weight := whitelist [coin .Denom ].CoinWeight
310+ // skip the native kyve denom since we already subtracted it above
311+ if coin .Denom == globalTypes .Denom || weight .IsZero () {
312+ continue
313+ }
294314
295- // the remaining total payout is split between the uploader and his delegators.
296- totalPayout = totalPayout .Sub (bundleReward .UploaderStorageCost ... )
297- if totalPayout .IsZero () {
298- return
315+ // currencyUnit is the amount of base denoms of the currency
316+ currencyUnit := math .LegacyNewDec (10 ).Power (uint64 (whitelist [coin .Denom ].CoinDecimals ))
317+ // amount is the value of storageCostPerCoin in the base denomination of the currency. We calculate this
318+ // by multiplying first with the amount of base denoms of the currency and then divide this by the $USD
319+ // value per currency unit which is the weight.
320+ amount := storageCostPerCoin .Mul (currencyUnit ).Quo (weight ).TruncateInt ()
321+ wantedStorageRewards = wantedStorageRewards .Add (sdk .NewCoin (coin .Denom , amount ))
322+ }
323+
324+ // we take the min here since there can be the case where we want to charge more coins for the storage
325+ // reward than we have left in the total payout
326+ multiCoinStorageCostReward := totalPayout .Min (wantedStorageRewards )
327+ bundleReward .UploaderStorageCost = bundleReward .UploaderStorageCost .Add (multiCoinStorageCostReward ... )
328+
329+ // the remaining total payout is split between the uploader and his delegators.
330+ totalPayout = totalPayout .Sub (multiCoinStorageCostReward ... )
331+ if totalPayout .IsZero () {
332+ return
333+ }
299334 }
300335
301336 commission := k .stakerKeeper .GetValidatorPoolCommission (ctx , bundleProposal .Uploader , poolId )
0 commit comments