Skip to content

Commit a757be7

Browse files
committed
Update handling of rebate leftover. use leftover for extra rewards instead of burning
* if 2 reserves are fee accountd but only 1 reserve entitled for rebate, there is some leftover of rebate amount. current: leftover rebate will be burnt fix: leftover rebate will be added to reward amount
1 parent 0c5799b commit a757be7

File tree

3 files changed

+49
-32
lines changed

3 files changed

+49
-32
lines changed

contracts/sol6/Dao/KyberFeeHandler.sol

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ contract KyberFeeHandler is IKyberFeeHandler, Utils5, DaoOperator, ReentrancyGua
6161

6262
struct BRRWei {
6363
uint256 rewardWei;
64-
uint256 rebateWei;
64+
uint256 fullRebateWei;
65+
uint256 paidRebateWei;
6566
uint256 burnWei;
6667
}
6768

@@ -203,22 +204,29 @@ contract KyberFeeHandler is IKyberFeeHandler, Utils5, DaoOperator, ReentrancyGua
203204
uint256 epoch;
204205

205206
// Decoding BRR data
206-
(brrAmounts.rewardWei, brrAmounts.rebateWei, epoch) = getRRWeiValues(networkFee);
207+
(brrAmounts.rewardWei, brrAmounts.fullRebateWei, epoch) = getRRWeiValues(networkFee);
207208

208-
brrAmounts.rebateWei = updateRebateValues(brrAmounts.rebateWei, rebateWallets, rebateBpsPerWallet);
209+
brrAmounts.paidRebateWei = updateRebateValues(
210+
brrAmounts.fullRebateWei, rebateWallets, rebateBpsPerWallet
211+
);
212+
brrAmounts.rewardWei = brrAmounts.rewardWei.add(
213+
brrAmounts.fullRebateWei.sub(brrAmounts.paidRebateWei)
214+
);
209215

210216
rewardsPerEpoch[epoch] = rewardsPerEpoch[epoch].add(brrAmounts.rewardWei);
211217

212218
// update total balance of rewards, rebates, fee
213-
totalPayoutBalance = totalPayoutBalance.add(platformFee).add(brrAmounts.rewardWei).add(brrAmounts.rebateWei);
219+
totalPayoutBalance = totalPayoutBalance.add(
220+
platformFee).add(brrAmounts.rewardWei).add(brrAmounts.paidRebateWei
221+
);
214222

215-
brrAmounts.burnWei = networkFee.sub(brrAmounts.rewardWei).sub(brrAmounts.rebateWei);
223+
brrAmounts.burnWei = networkFee.sub(brrAmounts.rewardWei).sub(brrAmounts.paidRebateWei);
216224
emit FeeDistributed(
217225
ETH_TOKEN_ADDRESS,
218226
platformWallet,
219227
platformFee,
220228
brrAmounts.rewardWei,
221-
brrAmounts.rebateWei,
229+
brrAmounts.paidRebateWei,
222230
rebateWallets,
223231
rebateBpsPerWallet,
224232
brrAmounts.burnWei

test/sol6/kyberFeeHandler.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -540,11 +540,16 @@ contract('KyberFeeHandler', function(accounts) {
540540

541541
expectedTotalReward = expectedTotalReward.add(sendVal.mul(currentRewardBps).div(BPS));
542542
expectedRebate = sendVal.mul(currentRebateBps).div(BPS);
543+
let totalPaidRebate = new BN(0);
543544

544545
for(let i = 0; i < rebateBpsPerWallet.length; i++) {
545-
expectedTotalRebate.iadd((new BN(rebateBpsPerWallet[i])).mul(expectedRebate).div(BPS));
546+
let paidRebate = (new BN(rebateBpsPerWallet[i])).mul(expectedRebate).div(BPS);
547+
expectedTotalRebate.iadd(paidRebate);
548+
totalPaidRebate = totalPaidRebate.add(paidRebate);
546549
}
547550

551+
//whatever wasn't paid for rebates to wallets due to rounding errors, will be added to reward amount
552+
expectedTotalReward = expectedTotalReward.add(expectedRebate.sub(totalPaidRebate));
548553
expectedTotalPayOut = expectedTotalReward.add(expectedTotalRebate);
549554
totalPayOutBalance = await feeHandler.totalPayoutBalance();
550555
Helper.assertEqual(expectedTotalPayOut, totalPayOutBalance);
@@ -744,9 +749,7 @@ contract('KyberFeeHandler', function(accounts) {
744749
rebateWallets, rebateBpsPerWallet
745750
);
746751

747-
expectedRewardPerEpoch = expectedRewardPerEpoch.add(sendVal.mul(currentRewardBps).div(BPS));
748-
rewardPerEpoch = await feeHandler.rewardsPerEpoch(currentEpoch);
749-
Helper.assertEqual(expectedRewardPerEpoch, rewardPerEpoch);
752+
//above function also validates reward per eopch.
750753
});
751754

752755
it("test reward per eopch updated when epoch advances", async() => {
@@ -770,14 +773,9 @@ contract('KyberFeeHandler', function(accounts) {
770773
Helper.assertEqual(0, rewardPerEpoch);
771774

772775
sendVal = oneEth.div(new BN(333));
773-
expectedRebates = await callHandleFeeAndVerifyValues(
774-
sendVal, zeroAddress, 0, currentRebateBps, currentRewardBps, currentEpoch,
775-
rebateWallets, rebateBpsPerWallet
776-
);
776+
expectedRebates = await callHandleFeeAndVerifyValues(sendVal, zeroAddress, 0, currentRebateBps, currentRewardBps, currentEpoch,rebateWallets, rebateBpsPerWallet);
777777

778-
expectedRewardPerEpoch = sendVal.mul(currentRewardBps).div(BPS);
779-
rewardPerEpoch = await feeHandler.rewardsPerEpoch(currentEpoch);
780-
Helper.assertEqual(expectedRewardPerEpoch, rewardPerEpoch);
778+
//above function also validates reward per eopch.
781779
});
782780

783781
it("claim reward and see total payout balance updated.", async() => {
@@ -2027,12 +2025,18 @@ async function callHandleFeeAndVerifyValues(sendValWei, platformWallet, platFeeW
20272025

20282026
//validate values
20292027
let expectedRebates = [];
2028+
let totalRebateWei = feeAmountBRR.mul(rebateBps).div(BPS);
2029+
let paidRebatesWei = new BN(0);
20302030
for (let i = 0; i < rebateWalletArr.length; i++) {
2031-
expectedRebates[i] = currentRebatesArr[i].add(feeAmountBRR.mul(rebateBps).div(BPS).mul(rebateBpsArr[i]).div(BPS));
2031+
let walletRebateWei = totalRebateWei.mul(rebateBpsArr[i]).div(BPS)
2032+
expectedRebates[i] = currentRebatesArr[i].add(walletRebateWei);
2033+
paidRebatesWei = paidRebatesWei.add(walletRebateWei);
20322034
let actualRebate = await feeHandler.rebatePerWallet(rebateWalletArr[i]);
20332035
Helper.assertEqual(actualRebate, expectedRebates[i]);
20342036
}
20352037

2038+
const extraRewardFromUnpaidRebate = totalRebateWei.sub(paidRebatesWei);
2039+
expectedRewardForEpoch = expectedRewardForEpoch.add(extraRewardFromUnpaidRebate);
20362040
const actualFeeWallet = await feeHandler.feePerPlatformWallet(platformWallet);
20372041
Helper.assertEqual(actualFeeWallet, expectedPlatWalletFee);
20382042

test/sol6/kyberNetwork.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,7 @@ contract('KyberNetwork', function(accounts) {
24572457
reserveInstances = {};
24582458
});
24592459

2460-
async function assertFeeHandlerUpdate(tradeWei, platfromFeeBps, feeAccountedBps, rebatePerWallet){
2460+
async function assertFeeHandlerUpdate(tradeWei, platfromFeeBps, feeAccountedBps, rebateEntitledBps, rebatePerWallet){
24612461
platformFeeWei = tradeWei.mul(platfromFeeBps).div(BPS);
24622462
Helper.assertEqual(await feeHandler.feePerPlatformWallet(platformWallet), beforePlatformFee.add(platformFeeWei), "unexpected rebate value");
24632463
networkFeeWei = tradeWei.mul(networkFeeBps).div(BPS).mul(feeAccountedBps).div(BPS);
@@ -2470,7 +2470,10 @@ contract('KyberNetwork', function(accounts) {
24702470
Helper.assertApproximate(await feeHandler.rebatePerWallet(rebateWallet), beforeBalance, "unexpected rebate value");
24712471
}
24722472
}
2473-
totalPayout = platformFeeWei.add(networkFeeWei.mul(rewardInBPS).div(BPS)).add(rebateWei);
2473+
2474+
let rebateLeftOver = feeAccountedBps == zeroBN? zeroBN : networkFeeWei.mul(feeAccountedBps.sub(rebateEntitledBps)).div(feeAccountedBps).mul(rebateInBPS).div(BPS);
2475+
let rewardWei = (networkFeeWei.mul(rewardInBPS).div(BPS)).add(rebateLeftOver);
2476+
totalPayout = platformFeeWei.add(rewardWei.add(rebateWei));
24742477
Helper.assertApproximate(await feeHandler.totalPayoutBalance(), beforeTotalBalancePayout.add(totalPayout), "unexpected payout balance");
24752478
}
24762479

@@ -2489,7 +2492,7 @@ contract('KyberNetwork', function(accounts) {
24892492
let expectedRebate = new BN(tradeEventArgs.ethWeiValue).mul(networkFeeBps).div(BPS).mul(rebateInBPS).div(BPS);
24902493
let rebatePerWallet = {}
24912494
rebatePerWallet[rebateWallet] = expectedRebate;
2492-
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, BPS, rebatePerWallet);
2495+
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, BPS, BPS, rebatePerWallet);
24932496
});
24942497

24952498
it("t2e trade. see fee in fee handler.", async() => {
@@ -2508,7 +2511,7 @@ contract('KyberNetwork', function(accounts) {
25082511
let expectedRebate = new BN(tradeEventArgs.ethWeiValue).mul(networkFeeBps).div(BPS).mul(rebateInBPS).div(BPS);
25092512
let rebatePerWallet = {}
25102513
rebatePerWallet[rebateWallet] = expectedRebate;
2511-
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, BPS, rebatePerWallet);
2514+
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, BPS, BPS, rebatePerWallet);
25122515
});
25132516

25142517
it("check that reserve rebate amount is correct", async() => {
@@ -2525,6 +2528,7 @@ contract('KyberNetwork', function(accounts) {
25252528
await srcToken.transfer(network.address, srcQty);
25262529
hint = await nwHelper.getHint(rateHelper, matchingEngine, reserveInstances, SPLIT_HINTTYPE, numReserves,
25272530
srcToken.address, destToken.address, srcQty);
2531+
25282532
txResult = await network.tradeWithHintAndFee(networkProxy, srcToken.address, srcQty, destToken.address, taker,
25292533
maxDestAmt, minConversionRate, platformWallet, platformFee, hint, {from: networkProxy});
25302534

@@ -2534,9 +2538,12 @@ contract('KyberNetwork', function(accounts) {
25342538
let feeAccountedBps = new BN(2).mul(BPS);
25352539
let entitledRebateBps = BPS;
25362540
let networkFeeWei = new BN(tradeEventArgs.ethWeiValue).mul(networkFeeBps).div(BPS).mul(new BN(2));
2537-
let expectedRebateWei = networkFeeWei.mul(entitledRebateBps).div(feeAccountedBps).mul(rebateInBPS).div(BPS);;
2541+
let expectedRebateWei = networkFeeWei.mul(entitledRebateBps).div(feeAccountedBps).mul(rebateInBPS).div(BPS);
2542+
25382543
rebatePerWallet[rebateWallets[0]] = expectedRebateWei;
2539-
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, BPS.mul(new BN(2)), rebatePerWallet);
2544+
rebatePerWallet[rebateWallets[1]] = zeroBN;
2545+
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, feeAccountedBps,
2546+
entitledRebateBps, rebatePerWallet);
25402547
// revert changes
25412548
await storage.setEntitledRebatePerReserveType(true, true, true, true, true, true, {from: admin});
25422549
});
@@ -2550,27 +2557,25 @@ contract('KyberNetwork', function(accounts) {
25502557
let txResult = await network.tradeWithHintAndFee(networkProxy, ethAddress, srcQty, srcToken.address, taker,
25512558
maxDestAmt, minConversionRate, platformWallet, zeroBN, '0x', {from: networkProxy, value: srcQty});
25522559
let tradeEventArgs = nwHelper.getTradeEventArgs(txResult);
2553-
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, zeroBN, zeroBN, {});
2560+
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, zeroBN, zeroBN, zeroBN, {});
25542561

25552562
// revert changes
25562563
await storage.setFeeAccountedPerReserveType(true, true, true, true, true, true, { from: admin });
25572564
await storage.setEntitledRebatePerReserveType(true, true, true, true, true, true, {from: admin});
25582565
});
25592566

2560-
it("should have no rebate fee if entitled rebate data is set to false", async() => {
2567+
it("should have no rebate if entitled rebate data is set to false", async() => {
25612568
await storage.setFeeAccountedPerReserveType(true, true, true, true, true, true, {from: admin});
25622569
// set entitled rebate data to false
25632570
await storage.setEntitledRebatePerReserveType(false, false, false, false, false, false, {from: admin});
2564-
2565-
// let payoutBalance0 = await feeHandler.totalPayoutBalance();
2571+
25662572
let srcQty = oneEth;
25672573

25682574
let txResult = await network.tradeWithHintAndFee(networkProxy, ethAddress, srcQty, srcToken.address, taker,
25692575
maxDestAmt, minConversionRate, platformWallet, zeroBN, '0x', {from: networkProxy, value: srcQty});
2570-
// let payoutBalance1 = await feeHandler.totalPayoutBalance();
2571-
// Helper.assertEqual(payoutBalance0, payoutBalance1);
2576+
25722577
let tradeEventArgs = nwHelper.getTradeEventArgs(txResult);
2573-
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, zeroBN, BPS, {});
2578+
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, zeroBN, BPS, zeroBN, {});
25742579

25752580
// reset fees
25762581
await storage.setFeeAccountedPerReserveType(true, true, true, true, true, true, { from: admin });
@@ -2586,7 +2591,7 @@ contract('KyberNetwork', function(accounts) {
25862591
let txResult = await network.tradeWithHintAndFee(networkProxy, ethAddress, srcQty, srcToken.address, taker,
25872592
maxDestAmt, minConversionRate, platformWallet, platformFee, '0x', {from: networkProxy, value: srcQty});
25882593
let tradeEventArgs = nwHelper.getTradeEventArgs(txResult);
2589-
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, zeroBN, {});
2594+
await assertFeeHandlerUpdate(tradeEventArgs.ethWeiValue, platformFee, zeroBN, zeroBN, {});
25902595

25912596
// reset fees
25922597
await storage.setFeeAccountedPerReserveType(true, true, true, true, true, true, { from: admin });

0 commit comments

Comments
 (0)