Skip to content

Commit

Permalink
Merge pull request #29 from neutral-protocol/refactor-interfaces
Browse files Browse the repository at this point in the history
Break down fee calculator interfaces
  • Loading branch information
0xmichalis authored Dec 20, 2023
2 parents fbcbc73 + 99f19a4 commit 306d97f
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 188 deletions.
44 changes: 20 additions & 24 deletions src/FeeCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
// If you encounter a vulnerability or an issue, please contact <info@neutralx.com>
pragma solidity ^0.8.13;

import "./interfaces/IDepositFeeCalculator.sol";
import "./interfaces/IRedemptionFeeCalculator.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import {SD59x18, sd, intoUint256} from "@prb/math/src/SD59x18.sol";

import "./interfaces/IFeeCalculator.sol";

/// @title FeeCalculator
/// @author Neutral Labs Inc.
/// @notice This contract calculates deposit and redemption fees for a given pool.
/// @dev It implements IDepositFeeCalculator and IRedemptionFeeCalculator interfaces.
contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator, Ownable {
/// @dev It implements the IFeeCalculator interface.
contract FeeCalculator is IFeeCalculator, Ownable {
SD59x18 private zero = sd(0);
SD59x18 private one = sd(1e18);

Expand Down Expand Up @@ -131,34 +131,32 @@ contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator, Ownab
_shares = shares;
}

/// @notice Calculates the deposit fees for a given amount.
/// @notice Calculates the deposit fee 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 deposited.
/// @return recipients The addresses of the fee recipients.
/// @return feesDenominatedInPoolTokens The amount of fees each recipient should receive.
/// @return feeAmount The fee to be charged in pool
/// tokens for this deposit.
function calculateDepositFees(address tco2, address pool, uint256 depositAmount)
external
view
override
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens)
returns (uint256 feeAmount)
{
require(depositAmount > 0, "depositAmount must be > 0");

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

require(totalFee <= depositAmount, "Fee must be lower or equal to deposit amount");
require(totalFee > 0, "Fee must be greater than 0");
feeAmount = getDepositFee(depositAmount, getTokenBalance(pool, tco2), getTotalSupply(pool));

return distributeFeeAmongShares(totalFee);
require(feeAmount <= depositAmount, "Fee must be lower or equal to deposit amount");
require(feeAmount > 0, "Fee must be greater than 0");
}

/// @notice Distributes the total fee among the recipients according to their shares.
/// @notice Calculates the total fee among the recipients according to their shares.
/// @param totalFee The total fee to be distributed.
/// @return recipients The addresses of the fee recipients.
/// @return feesDenominatedInPoolTokens The amount of fees each recipient should receive.
function distributeFeeAmongShares(uint256 totalFee)
private
function calculateFeeAmongShares(uint256 totalFee)
external
view
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens)
{
Expand All @@ -179,22 +177,20 @@ contract FeeCalculator is IDepositFeeCalculator, IRedemptionFeeCalculator, Ownab
/// @param tco2 The address of the TCO2 token.
/// @param pool The address of the pool.
/// @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.
/// @return feeAmount The fee to be charged in pool
/// tokens for this redemption.
function calculateRedemptionFees(address tco2, address pool, uint256 redemptionAmount)
external
view
override
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens)
returns (uint256 feeAmount)
{
require(redemptionAmount > 0, "redemptionAmount must be > 0");

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

require(totalFee <= redemptionAmount, "Fee must be lower or equal to redemption amount");
require(totalFee > 0, "Fee must be greater than 0");
feeAmount = getRedemptionFee(redemptionAmount, getTokenBalance(pool, tco2), getTotalSupply(pool));

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

/// @notice Gets the balance of the TCO2 token in a given pool.
Expand Down
21 changes: 0 additions & 21 deletions src/interfaces/IDepositFeeCalculator.sol

This file was deleted.

40 changes: 40 additions & 0 deletions src/interfaces/IFeeCalculator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2023 Neutral Labs Inc.
//
// SPDX-License-Identifier: UNLICENSED

// If you encounter a vulnerability or an issue, please contact <info@neutralx.com>
pragma solidity ^0.8.13;

/// @title IFeeCalculator
/// @author Neutral Labs Inc.
/// @notice This interface defines methods for calculating fees.
interface IFeeCalculator {
/// @notice Calculates the deposit fee 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 deposited.
/// @return feeAmount The fee to be charged in pool
/// tokens for this deposit.
function calculateDepositFees(address tco2, address pool, uint256 depositAmount)
external
returns (uint256 feeAmount);

/// @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 redemptionAmount The amount to be redeemed.
/// @return feeAmount The fee to be charged in pool
/// tokens for this redemption.
function calculateRedemptionFees(address tco2, address pool, uint256 redemptionAmount)
external
returns (uint256 feeAmount);

/// @notice Calculates the total fee among the recipients according to their shares.
/// @param totalFee The total fee to be distributed.
/// @return recipients The addresses of the fee recipients.
/// @return feesDenominatedInPoolTokens The amount of fees each recipient should receive.
function calculateFeeAmongShares(uint256 totalFee)
external
view
returns (address[] memory recipients, uint256[] memory feesDenominatedInPoolTokens);
}
21 changes: 0 additions & 21 deletions src/interfaces/IRedemptionFeeCalculator.sol

This file was deleted.

33 changes: 12 additions & 21 deletions test/FeeCalculator.fuzzy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,8 @@ contract FeeCalculatorTestFuzzy is Test {

// Act
try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount) returns (
address[] memory recipients, uint256[] memory fees
) {
// Assert
assertEq(recipients[0], feeRecipient);
} catch Error(string memory reason) {
uint256 feeAmount
) {} 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 deposit amount")) == keccak256(bytes(reason)),
Expand Down Expand Up @@ -124,12 +121,9 @@ contract FeeCalculatorTestFuzzy is Test {

// Act
try feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemptionAmount) returns (
address[] memory recipients, uint256[] memory fees
uint256 feeAmount
) {
oneTimeFee = fees[0];

// Assert
assertEq(recipients[0], feeRecipient);
oneTimeFee = feeAmount;
} catch Error(string memory reason) {
oneTimeRedemptionFailed = true;
assertTrue(
Expand All @@ -152,9 +146,9 @@ contract FeeCalculatorTestFuzzy is Test {
for (uint256 i = 0; i < numberOfRedemptions; i++) {
uint256 redemption = equalRedemption + (i == 0 ? restRedemption : 0);
try feeCalculator.calculateRedemptionFees(address(mockToken), address(mockPool), redemption) returns (
address[] memory recipients, uint256[] memory fees
uint256 feeAmount
) {
feeFromDividedRedemptions += fees[0];
feeFromDividedRedemptions += feeAmount;
total -= redemption;
current -= redemption;
mockPool.setTotalSupply(total);
Expand Down Expand Up @@ -210,12 +204,9 @@ contract FeeCalculatorTestFuzzy is Test {

// Act
try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount) returns (
address[] memory recipients, uint256[] memory fees
uint256 feeAmount
) {
oneTimeFee = fees[0];

// Assert
assertEq(recipients[0], feeRecipient);
oneTimeFee = feeAmount;
} catch Error(string memory reason) {
oneTimeDepositFailed = true;
assertTrue(
Expand All @@ -233,9 +224,9 @@ contract FeeCalculatorTestFuzzy is Test {
uint256 deposit = equalDeposit + (i == 0 ? restDeposit : 0);

try feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), deposit) returns (
address[] memory recipients, uint256[] memory fees
uint256 feeAmount
) {
feeFromDividedDeposits += fees[0];
feeFromDividedDeposits += feeAmount;
total += deposit;
current += deposit;
mockPool.setTotalSupply(total);
Expand Down Expand Up @@ -286,8 +277,8 @@ contract FeeCalculatorTestFuzzy is Test {
mockToken.setTokenBalance(address(mockPool), 100 * 1e18);

// Act
(address[] memory recipients, uint256[] memory fees) =
feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount);
uint256 feeAmount = feeCalculator.calculateDepositFees(address(mockToken), address(mockPool), depositAmount);
(address[] memory recipients, uint256[] memory fees) = feeCalculator.calculateFeeAmongShares(feeAmount);

// Assert
for (uint256 i = 0; i < recipients.length; i++) {
Expand Down
Loading

0 comments on commit 306d97f

Please sign in to comment.