Skip to content

Commit 730483b

Browse files
test: Rounding error is not accumulated after many splits
1 parent c68956b commit 730483b

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

test/ATokenVaultRevenueSplitterOwner.t.sol

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,4 +564,83 @@ contract ATokenVaultRevenueSplitterOwnerTest is Test {
564564

565565
assertEq(address(revenueSplitterOwner).balance, 0);
566566
}
567+
568+
function test_splitRevenue_roundingErrorIsNotAccumulatedAfterManySplits() public {
569+
shareI = 9_000; // 90.00%
570+
shareII = 500; // 5.00%
571+
shareIII = 500; // 5.00%
572+
573+
recipients[0].shareInBps = shareI;
574+
recipients[1].shareInBps = shareII;
575+
recipients[2].shareInBps = shareIII;
576+
577+
revenueSplitterOwner = new ATokenVaultRevenueSplitterOwner(address(vault), owner, recipients);
578+
579+
uint256 accumulatedAmountToSplit;
580+
581+
MockDAI assetToSplit = new MockDAI();
582+
uint256 assetBalance = 4;
583+
uint256 amountToSplit = assetBalance - UNIT_OF_DUST; // = 3
584+
accumulatedAmountToSplit += amountToSplit;
585+
address[] memory assetsToSplit = new address[](1);
586+
assetsToSplit[0] = address(assetToSplit);
587+
588+
/// Split #1: Balance is 4, 3 units of asset to distribute, only recipientI gets revenue
589+
590+
assertEq(assetToSplit.balanceOf(address(revenueSplitterOwner)), 0, "Unexpected initial splitter balance");
591+
assetToSplit.mint(address(revenueSplitterOwner), assetBalance);
592+
assertEq(assetToSplit.balanceOf(address(revenueSplitterOwner)), 4, "Unexpected splitter balance");
593+
594+
revenueSplitterOwner.splitRevenue(assetsToSplit);
595+
596+
assertEq(assetToSplit.balanceOf(address(recipientI)), 2, "Unexpected recipientI balance after 1st split");
597+
assertEq(assetToSplit.balanceOf(address(recipientII)), 0, "Unexpected recipientII balance after 1st split");
598+
assertEq(assetToSplit.balanceOf(address(recipientIII)), 0, "Unexpected recipientIII balance after 1st split");
599+
600+
/// Split #2 - #10: Balance is 4 (2 new + 1 carried from previous rounding error split dust + 1 from the
601+
/// reserved unit to not fail in aToken transfers), 3 units of asset to distribute, only recipientI gets revenue
602+
for (uint256 i = 1; i <= 10; i++) {
603+
amountToSplit = 2;
604+
accumulatedAmountToSplit += amountToSplit;
605+
606+
assetToSplit.mint(address(revenueSplitterOwner), amountToSplit);
607+
608+
revenueSplitterOwner.splitRevenue(assetsToSplit);
609+
}
610+
assertEq(assetToSplit.balanceOf(address(recipientI)), 20, "Unexpected recipientI balance after 10th split");
611+
assertEq(assetToSplit.balanceOf(address(recipientII)), 1, "Unexpected recipientII balance after 10th split");
612+
assertEq(assetToSplit.balanceOf(address(recipientIII)), 1, "Unexpected recipientIII balance after 10th split");
613+
614+
// Split #11: 3 units of asset (2 new + 1 carried from previous split dust), all get revenue
615+
616+
amountToSplit = 2;
617+
accumulatedAmountToSplit += amountToSplit;
618+
619+
assetToSplit.mint(address(revenueSplitterOwner), amountToSplit);
620+
621+
revenueSplitterOwner.splitRevenue(assetsToSplit);
622+
623+
assertEq(assetToSplit.balanceOf(address(recipientI)), 22, "Unexpected recipientI balance after 11th split");
624+
assertEq(assetToSplit.balanceOf(address(recipientII)), 1, "Unexpected recipientII balance after 11th split");
625+
assertEq(assetToSplit.balanceOf(address(recipientIII)), 1, "Unexpected recipientIII balance after 11th split");
626+
627+
assertEq(accumulatedAmountToSplit, 25, "Unexpected accumulated amount to split");
628+
629+
// The accumulated split is the expected and does not have accumulated rounding errors
630+
assertEq(
631+
assetToSplit.balanceOf(address(recipientI)), accumulatedAmountToSplit * shareI / TOTAL_SHARE_IN_BPS,
632+
"Split has accumulated rounding error for recipientI"
633+
);
634+
assertEq(
635+
assetToSplit.balanceOf(address(recipientII)), accumulatedAmountToSplit * shareII / TOTAL_SHARE_IN_BPS,
636+
"Split has accumulated rounding error for recipientII"
637+
);
638+
assertEq(
639+
assetToSplit.balanceOf(address(recipientIII)), accumulatedAmountToSplit * shareIII / TOTAL_SHARE_IN_BPS,
640+
"Split has accumulated rounding error for recipientIII"
641+
);
642+
643+
// One unit of rounding error dust + one unit of reserved unit to not fail in aToken transfers
644+
assertEq(assetToSplit.balanceOf(address(revenueSplitterOwner)), 2, "Unexpected final splitter balance");
645+
}
567646
}

0 commit comments

Comments
 (0)