Skip to content

Commit

Permalink
Merge pull request #59 from 0xmichalis/do-not-throw-on-zero-fee
Browse files Browse the repository at this point in the history
[LILA-7980]  Do not throw on zero fee returned
  • Loading branch information
0xmichalis authored Oct 29, 2024
2 parents bf89dcc + 89e49a5 commit f9888eb
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 73 deletions.
6 changes: 4 additions & 2 deletions src/FeeCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract FeeCalculator is IFeeCalculator, Ownable {
/// @dev Version-related parameters. VERSION keeps track of production
/// releases. VERSION_RELEASE_CANDIDATE keeps track of iterations
/// of a VERSION in our staging environment.
string public constant VERSION = "1.1.0";
string public constant VERSION = "1.2.0";
uint256 public constant VERSION_RELEASE_CANDIDATE = 1;

SD59x18 private _zero = sd(0);
Expand Down Expand Up @@ -406,7 +406,9 @@ contract FeeCalculator is IFeeCalculator, Ownable {
uint256 feeAmount = calculator(requestedAmount, projectSupply, totalPoolSupply);

require(feeAmount <= requestedAmount, "Fee must be lower or equal to requested amount");
require(feeAmount != 0, "Fee must be greater than 0");
if (feeAmount == 0) {
return FeeDistribution(new address[](0), new uint256[](0));
}

return calculateFeeShares(feeAmount);
}
Expand Down
6 changes: 4 additions & 2 deletions src/FlatFeeCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract FlatFeeCalculator is IFeeCalculator, Ownable {
/// @dev Version-related parameters. VERSION keeps track of production
/// releases. VERSION_RELEASE_CANDIDATE keeps track of iterations
/// of a VERSION in our staging environment.
string public constant VERSION = "1.0.0";
string public constant VERSION = "1.1.0";
uint256 public constant VERSION_RELEASE_CANDIDATE = 2;

uint256 public feeBasisPoints = 300;
Expand Down Expand Up @@ -158,7 +158,9 @@ contract FlatFeeCalculator is IFeeCalculator, Ownable {
require(requestedAmount != 0, "requested amount must be > 0");

uint256 feeAmount = requestedAmount * feeBasisPoints / 10000;
require(feeAmount != 0, "Fee must be greater than 0");
if (feeAmount == 0) {
return FeeDistribution(new address[](0), new uint256[](0));
}

return calculateFeeShares(feeAmount);
}
Expand Down
16 changes: 10 additions & 6 deletions test/FeeCalculator/AbstractFeeCalculator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ abstract contract AbstractFeeCalculatorTest is Test {
assertEq(fees[0], 46413457506542766270);
}

function testCalculateDepositFees_DepositOfOneWei_ShouldThrowException() public {
function testCalculateDepositFees_DepositOfOneWei_ShouldNotThrowException() public {
// Arrange
// Set up your test data
uint256 depositAmount = 1;
Expand All @@ -264,11 +264,13 @@ abstract contract AbstractFeeCalculatorTest is Test {
setProjectSupply(address(mockToken), 1e4 * 1e18);

// Act
vm.expectRevert("Fee must be greater than 0");
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
FeeDistribution memory feeDistribution =
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
assertEq(feeDistribution.recipients.length, 0);
assertEq(feeDistribution.shares.length, 0);
}

function testCalculateDepositFees_DepositOfHundredWei_ShouldThrowError() public {
function testCalculateDepositFees_DepositOfHundredWei_ShouldNotThrowError() public {
//Note! This is a bug, where a very small deposit to a very large pool
//causes a == b because of precision limited by ratioDenominator in FeeCalculator

Expand All @@ -281,8 +283,10 @@ abstract contract AbstractFeeCalculatorTest is Test {
setProjectSupply(address(mockToken), 1e4 * 1e18);

// Act
vm.expectRevert("Fee must be greater than 0");
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
FeeDistribution memory feeDistribution =
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
assertEq(feeDistribution.recipients.length, 0);
assertEq(feeDistribution.shares.length, 0);
}

function testCalculateDepositFees_DepositOfHundredThousandsPartOfOne_NonzeroFee() public {
Expand Down
8 changes: 5 additions & 3 deletions test/FeeCalculatorFuzzy/AbstractFeeCalculator.fuzzy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ abstract contract AbstractFeeCalculatorTestFuzzy is Test {
uint256 total
) public virtual;

function testCalculateDepositFees_FuzzyExtremelySmallDepositsToLargePool_ShouldThrowError(uint256 depositAmount)
function testCalculateDepositFees_FuzzyExtremelySmallDepositsToLargePool_ShouldNotThrowError(uint256 depositAmount)
public
{
vm.assume(depositAmount <= 1e-14 * 1e18);
Expand All @@ -66,8 +66,10 @@ abstract contract AbstractFeeCalculatorTestFuzzy is Test {
mockPool.setTotalSupply(1e12 * 1e18);
setProjectSupply(address(mockToken), 1e9 * 1e18);

vm.expectRevert("Fee must be greater than 0");
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
FeeDistribution memory feeDistribution =
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
assertEq(feeDistribution.recipients.length, 0);
assertEq(feeDistribution.shares.length, 0);
}

function testCalculateRedemptionFeesFuzzy_RedemptionDividedIntoOneChunkFeesGreaterOrEqualToOneRedemption(
Expand Down
25 changes: 10 additions & 15 deletions test/FeeCalculatorFuzzy/FeeCalculatorERC1155.fuzzy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ contract FeeCalculatorERC1155TestFuzzy is AbstractFeeCalculatorTestFuzzy {
try feeCalculator.calculateDepositFees(address(mockPool), address(mockToken), 1, depositAmount) {}
catch Error(string memory reason) {
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}
}
Expand Down Expand Up @@ -95,9 +94,8 @@ contract FeeCalculatorERC1155TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
oneTimeRedemptionFailed = true;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}

Expand Down Expand Up @@ -125,9 +123,8 @@ contract FeeCalculatorERC1155TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
multipleTimesRedemptionFailedCount++;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}
}
Expand Down Expand Up @@ -168,9 +165,8 @@ contract FeeCalculatorERC1155TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
oneTimeDepositFailed = true;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}

Expand All @@ -192,9 +188,8 @@ contract FeeCalculatorERC1155TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
multipleTimesDepositFailedCount++;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}
}
Expand Down
25 changes: 10 additions & 15 deletions test/FeeCalculatorFuzzy/FeeCalculatorTCO2.fuzzy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ contract FeeCalculatorTCO2TestFuzzy is AbstractFeeCalculatorTestFuzzy {
try feeCalculator.calculateDepositFees(address(mockPool), address(mockToken), depositAmount) {}
catch Error(string memory reason) {
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}
}
Expand Down Expand Up @@ -90,9 +89,8 @@ contract FeeCalculatorTCO2TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
oneTimeRedemptionFailed = true;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}

Expand Down Expand Up @@ -120,9 +118,8 @@ contract FeeCalculatorTCO2TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
multipleTimesRedemptionFailedCount++;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}
}
Expand Down Expand Up @@ -163,9 +160,8 @@ contract FeeCalculatorTCO2TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
oneTimeDepositFailed = true;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}

Expand All @@ -187,9 +183,8 @@ contract FeeCalculatorTCO2TestFuzzy is AbstractFeeCalculatorTestFuzzy {
} catch Error(string memory reason) {
multipleTimesDepositFailedCount++;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount'"
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason)),
"error should be 'Fee must be lower or equal to requested amount'"
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ abstract contract AbstractFeeCalculatorLaunchParamsTest is Test {
assertEq(fees[0], 53013879215838797358);
}

function testCalculateDepositFees_DepositOfOneWei_ShouldThrowException() public {
function testCalculateDepositFees_DepositOfOneWei_ShouldNotThrowException() public {
// Arrange
// Set up your test data
uint256 depositAmount = 1;
Expand All @@ -157,11 +157,13 @@ abstract contract AbstractFeeCalculatorLaunchParamsTest is Test {
setProjectSupply(address(mockToken), 1e4 * 1e18);

// Act
vm.expectRevert("Fee must be greater than 0");
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
FeeDistribution memory feeDistribution =
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
assertEq(feeDistribution.recipients.length, 0);
assertEq(feeDistribution.shares.length, 0);
}

function testCalculateDepositFees_DepositOfHundredWei_ShouldThrowError() public {
function testCalculateDepositFees_DepositOfHundredWei_ShouldNotThrowError() public {
//Note! This is a bug, where a very small deposit to a very large pool
//causes a == b because of precision limited by ratioDenominator in FeeCalculator

Expand All @@ -174,8 +176,10 @@ abstract contract AbstractFeeCalculatorLaunchParamsTest is Test {
setProjectSupply(address(mockToken), 1e4 * 1e18);

// Act
vm.expectRevert("Fee must be greater than 0");
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
FeeDistribution memory feeDistribution =
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
assertEq(feeDistribution.recipients.length, 0);
assertEq(feeDistribution.shares.length, 0);
}

function testCalculateDepositFees_DepositOfHundredThousandsPartOfOne_NonzeroFee() public {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ abstract contract AbstractFeeCalculatorLaunchParamsTestFuzzy is Test {
uint256 total
) public virtual;

function testCalculateDepositFees_FuzzyExtremelySmallDepositsToLargePool_ShouldThrowError(uint256 depositAmount)
function testCalculateDepositFees_FuzzyExtremelySmallDepositsToLargePool_ShouldNotThrowError(uint256 depositAmount)
public
{
vm.assume(depositAmount <= 1e-14 * 1e18);
Expand All @@ -63,8 +63,10 @@ abstract contract AbstractFeeCalculatorLaunchParamsTestFuzzy is Test {
mockPool.setTotalSupply(1e12 * 1e18);
setProjectSupply(address(mockToken), 1e9 * 1e18);

vm.expectRevert("Fee must be greater than 0");
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
FeeDistribution memory feeDistribution =
calculateDepositFees(address(mockPool), address(mockToken), depositAmount);
assertEq(feeDistribution.recipients.length, 0);
assertEq(feeDistribution.shares.length, 0);
}

function testCalculateDepositFeesFuzzy_DepositDividedIntoOneChunkFeesGreaterOrEqualToOneDeposit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ contract FeeCalculatorLaunchParamsERC1155TestFuzzy is AbstractFeeCalculatorLaunc
try feeCalculator.calculateDepositFees(address(mockPool), address(mockToken), 1, depositAmount) {}
catch Error(string memory reason) {
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason))
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason))
|| keccak256(bytes("Deposit outside range")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount' or 'Deposit outside range'"
"error should be 'Fee must be lower or equal to requested amount' or 'Deposit outside range'"
);
}
}
Expand Down Expand Up @@ -80,10 +79,9 @@ contract FeeCalculatorLaunchParamsERC1155TestFuzzy is AbstractFeeCalculatorLaunc
} catch Error(string memory reason) {
oneTimeDepositFailed = true;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason))
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason))
|| keccak256(bytes("Deposit outside range")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount' or 'Deposit outside range'"
"error should be 'Fee must be lower or equal to requested amount' or 'Deposit outside range'"
);
}

Expand All @@ -105,10 +103,9 @@ contract FeeCalculatorLaunchParamsERC1155TestFuzzy is AbstractFeeCalculatorLaunc
} catch Error(string memory reason) {
multipleTimesDepositFailedCount++;
assertTrue(
keccak256(bytes("Fee must be greater than 0")) == keccak256(bytes(reason))
|| keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason))
keccak256(bytes("Fee must be lower or equal to requested amount")) == keccak256(bytes(reason))
|| keccak256(bytes("Deposit outside range")) == keccak256(bytes(reason)),
"error should be 'Fee must be greater than 0' or 'Fee must be lower or equal to requested amount' or 'Deposit outside range'"
"error should be 'Fee must be lower or equal to requested amount' or 'Deposit outside range'"
);
}
}
Expand Down
Loading

0 comments on commit f9888eb

Please sign in to comment.