Skip to content

Commit

Permalink
Merge pull request #14 from neutral-protocol/chores
Browse files Browse the repository at this point in the history
Small chores
  • Loading branch information
0xmichalis authored Nov 27, 2023
2 parents fec047c + 2bb04f1 commit e920562
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 84 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ jobs:
forge build --sizes --via-ir
id: build

- name: Check formatting
run: forge fmt --check
id: fmt

- name: Run Forge tests
run: |
forge test -vvv --via-ir
Expand Down
23 changes: 8 additions & 15 deletions src/FeeCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator {
/// @param shares The share of the fee each recipient should receive.
function feeSetup(address[] memory recipients, uint256[] memory shares) external {
require(recipients.length == shares.length, "Recipients and shares arrays must have the same length");
require(recipients.length > 0, "Recipients and shares arrays must not be empty");

uint256 totalShares = 0;
for (uint256 i = 0; i < shares.length; i++) {
Expand All @@ -55,6 +54,7 @@ contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator {
/// @return feesDenominatedInPoolTokens The amount of fees each recipient should receive.
function calculateDepositFees(address tco2, address pool, uint256 depositAmount)
external
view
override
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens)
{
Expand Down Expand Up @@ -86,27 +86,27 @@ contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator {
restFee -= feesDenominatedInPoolTokens[i];
}

require(restFee >= 0);
recipients = _recipients;
feesDenominatedInPoolTokens[0] += restFee; //we give rest of the fee (if any) to the first recipient
}

/// @notice Calculates the redemption fees for a given amount.
/// @param tco2 The address of the TCO2 token.
/// @param pool The address of the pool.
/// @param depositAmount The amount to be redeemed.
/// @param redemptionAmount The amount to be redeemed.
/// @return recipients The addresses of the fee recipients.
/// @return feesDenominatedInPoolTokens The amount of fees each recipient should receive.
function calculateRedemptionFee(address tco2, address pool, uint256 depositAmount)
function calculateRedemptionFees(address tco2, address pool, uint256 redemptionAmount)
external
view
override
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens)
{
require(depositAmount > 0, "depositAmount must be > 0");
require(redemptionAmount > 0, "redemptionAmount must be > 0");

uint256 totalFee = getRedemptionFee(depositAmount, getTokenBalance(pool, tco2), getTotalSupply(pool));
uint256 totalFee = getRedemptionFee(redemptionAmount, getTokenBalance(pool, tco2), getTotalSupply(pool));

require(totalFee <= depositAmount, "Fee must be lower or equal to redemption amount");
require(totalFee <= redemptionAmount, "Fee must be lower or equal to redemption amount");
require(totalFee > 0, "Fee must be greater than 0");

return distributeFeeAmongShares(totalFee);
Expand Down Expand Up @@ -216,14 +216,7 @@ contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator {
SD59x18 i_b = tb * (db + redemptionFeeShift).log10();
SD59x18 fee_float = redemptionFeeScale * (i_b - i_a) + redemptionFeeConstant * amount_float;

if (fee_float < zero) {
if (fee_float / amount_float < sd(1e-6 * 1e18)) {
//fee_float=zero_signed;//if the fee is negative but is less than 0.0001% of amount than it's basically 0
require(fee_float > zero, "Fee must be greater than 0");
} else {
require(fee_float > zero, "Total failure. Fee must be greater than 0 or at least close to it.");
}
}
require(fee_float > zero, "Fee must be greater than 0");

uint256 fee = intoUint256(fee_float);
return fee;
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IRedemptionFeeCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface IRedemptionFeeCalculator {
/// @param depositAmount The amount to be redeemed.
/// @return recipients The addresses of the fee recipients.
/// @return feesDenominatedInPoolTokens The amount of fees each recipient should receive.
function calculateRedemptionFee(address tco2, address pool, uint256 depositAmount)
function calculateRedemptionFees(address tco2, address pool, uint256 depositAmount)
external
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens);
}
109 changes: 41 additions & 68 deletions test/FeeCalculator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ contract MockPool is IERC20 {
return true;
}

function balanceOf(address account) external view returns (uint256) {
function balanceOf(address account) external pure returns (uint256) {
return 0;
}
}
Expand Down Expand Up @@ -65,7 +65,7 @@ contract MockToken is IERC20 {
return true;
}

function totalSupply() external view returns (uint256) {
function totalSupply() external pure returns (uint256) {
return 0;
}
}
Expand Down Expand Up @@ -96,6 +96,13 @@ contract FeeCalculatorTest is Test {
feeCalculator.feeSetup(recipients, feeShares);
}

function testFeeSetupEmpty() public {
address[] memory recipients = new address[](0);
uint256[] memory feeShares = new uint256[](0);
vm.expectRevert("Total shares must equal 100");
feeCalculator.feeSetup(recipients, feeShares);
}

function testCalculateDepositFeesNormalCase() public {
// Arrange
// Set up your test data
Expand Down Expand Up @@ -125,7 +132,7 @@ contract FeeCalculatorTest is Test {

// Act
(address[] memory recipients, uint256[] memory fees) =
feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount);
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);

// Assert
assertEq(recipients[0], feeRecipient);
Expand All @@ -143,7 +150,7 @@ contract FeeCalculatorTest is Test {

// Act
(address[] memory recipients, uint256[] memory fees) =
feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount);
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);

// Assert
assertEq(recipients[0], feeRecipient);
Expand All @@ -163,7 +170,7 @@ contract FeeCalculatorTest is Test {

// Act
(address[] memory recipients, uint256[] memory fees) =
feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount);
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);

// Assert
assertEq(recipients[0], feeRecipient);
Expand All @@ -180,16 +187,8 @@ contract FeeCalculatorTest is Test {
mockToken.setTokenBalance(address(mockPool), 1e6 * 1e18);

// Act
try feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
assertEq(fees[0], 0);
fail("Exception should be thrown");
} catch Error(string memory reason) {
assertEq("Fee must be greater than 0", reason);
}
vm.expectRevert("Fee must be greater than 0");
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);
}

function testCalculateRedemptionFees_CurrentSlightLessThanTotal_AmountSuperSmall_ShouldResultInException() public {
Expand All @@ -203,16 +202,8 @@ contract FeeCalculatorTest is Test {
mockToken.setTokenBalance(address(mockPool), 11102230246251565403820829061134812052); //1.11e37

// Act
try feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
assertEq(fees[0], 0);
fail("Exception should be thrown");
} catch Error(string memory reason) {
assertEq("Fee must be greater than 0", reason);
}
vm.expectRevert("Fee must be greater than 0");
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);
}

function testCalculateDepositFeesNormalCase_TwoFeeRecipientsSplitEqually() public {
Expand Down Expand Up @@ -305,16 +296,8 @@ contract FeeCalculatorTest is Test {
mockToken.setTokenBalance(address(mockPool), 1e4 * 1e18);

// Act
try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
assertEq(fees[0], depositAmount);
fail("Exception should be thrown");
} catch Error(string memory reason) {
assertEq("Fee must be greater than 0", reason);
}
vm.expectRevert("Fee must be greater than 0");
feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount);
}

function testCalculateDepositFees_DepositOfHundredWei_ShouldThrowError() public {
Expand All @@ -330,16 +313,8 @@ contract FeeCalculatorTest is Test {
mockToken.setTokenBalance(address(mockPool), 1e4 * 1e18);

// Act
try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
assertEq(fees[0], depositAmount);
fail("Exception should be thrown");
} catch Error(string memory reason) {
assertEq("Fee must be greater than 0", reason);
}
vm.expectRevert("Fee must be greater than 0");
feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount);
}

function testCalculateDepositFees_FuzzyExtremelySmallDepositsToLargePool_ShouldThrowError(uint256 depositAmount)
Expand All @@ -358,16 +333,8 @@ contract FeeCalculatorTest is Test {
mockPool.setTotalSupply(1e12 * 1e18);
mockToken.setTokenBalance(address(mockPool), 1e9 * 1e18);

try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
assertEq(fees[0], depositAmount);
fail("Exception should be thrown");
} catch Error(string memory reason) {
assertEq("Fee must be greater than 0", reason);
}
vm.expectRevert("Fee must be greater than 0");
feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount);
}

function testCalculateDepositFees_DepositOfHundredThousandsPartOfOne_NonzeroFee() public {
Expand Down Expand Up @@ -526,16 +493,8 @@ contract FeeCalculatorTest is Test {
mockToken.setTokenBalance(address(mockPool), 500 * 1e18);

// Act
try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
assertEq(fees[0], 0);
fail("Exception should be thrown");
} catch Error(string memory reason) {
assertEq("depositAmount must be > 0", reason);
}
vm.expectRevert("depositAmount must be > 0");
feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount);
}

function testCalculateDepositFees_EmptyPool_FeeCappedAt10Percent() public {
Expand Down Expand Up @@ -574,6 +533,20 @@ contract FeeCalculatorTest is Test {
assertEq(fees[0], 35999999999999999154);
}

function testCalculateRedemptionFees_ZeroDeposit_ExceptionShouldBeThrown() public {
// Arrange
// Set up your test data
uint256 redemptionAmount = 0;

// Set up mock pool
mockPool.setTotalSupply(1000 * 1e18);
mockToken.setTokenBalance(address(mockPool), 500 * 1e18);

// Act
vm.expectRevert("redemptionAmount must be > 0");
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);
}

function testCalculateRedemptionFees_TotalEqualCurrent_FeeCappedAt10Percent() public {
// Arrange
// Set up your test data
Expand All @@ -585,7 +558,7 @@ contract FeeCalculatorTest is Test {

// Act
(address[] memory recipients, uint256[] memory fees) =
feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount);
feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount);

// Assert
assertEq(recipients[0], feeRecipient);
Expand Down Expand Up @@ -717,7 +690,7 @@ contract FeeCalculatorTest is Test {
uint256 multipleTimesRedemptionFailedCount = 0;

// Act
try feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemptionAmount) returns (
try feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
oneTimeFee = fees[0];
Expand All @@ -739,7 +712,7 @@ contract FeeCalculatorTest is Test {

for (uint256 i = 0; i < numberOfRedemptions; i++) {
uint256 redemption = equalRedemption + (i == 0 ? restRedemption : 0);
try feeCalculator.calculateRedemptionFee(address(mockToken), address(mockPool), redemption) returns (
try feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemption) returns (
address[] memory recipients, uint256[] memory fees
) {
feeFromDividedRedemptions += fees[0];
Expand Down

0 comments on commit e920562

Please sign in to comment.