Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow for different decimals between fee token and underlying #55

Merged
merged 3 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/FlatFeeCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ contract FlatFeeCalculator is IFeeCalculator, Ownable {

uint256 public feeBasisPoints = 300;

/// @dev The scale between the decimals of the fee token and the underlying token.
/// For example, if the fee token has 18 decimals and the underlying token has 18 decimals, the
/// decimals scale is 1e0.
/// If the fee token has 18 decimals and the underlying token has 0 decimals, the decimals scale is 1e18
uint256 public feeToUnderlyingDecimalsScale = 1e18;

address[] private _recipients;
uint256[] private _shares;

Expand All @@ -32,6 +38,12 @@ contract FlatFeeCalculator is IFeeCalculator, Ownable {

constructor() Ownable() {}

function setFeeToUnderlyingDecimalsScale(uint256 _feeToUnderlyingDecimalsScale) external onlyOwner {
require(_feeToUnderlyingDecimalsScale > 0, "Fee to underlying decimals scale must be greater than 0");

feeToUnderlyingDecimalsScale = _feeToUnderlyingDecimalsScale;
}

/// @notice Sets the fee basis points.
/// @dev Can only be called by the current owner.
/// @param _feeBasisPoints The new fee basis points.
Expand Down Expand Up @@ -161,9 +173,10 @@ contract FlatFeeCalculator is IFeeCalculator, Ownable {
function _calculateFee(uint256 requestedAmount) internal view returns (FeeDistribution memory) {
require(requestedAmount > 0, "requested amount must be > 0");

uint256 feeAmount = requestedAmount * feeBasisPoints / 10000;
uint256 adjustedAmount = requestedAmount * feeToUnderlyingDecimalsScale;
uint256 feeAmount = adjustedAmount * feeBasisPoints / 10000;

require(feeAmount <= requestedAmount, "Fee must be lower or equal to requested amount");
require(feeAmount <= adjustedAmount, "Fee must be lower or equal to requested amount");
require(feeAmount > 0, "Fee must be greater than 0");

return calculateFeeShares(feeAmount);
Expand Down
102 changes: 102 additions & 0 deletions test/FlatFeeCalculatorFuzzy/FlatFeeCalculator.fuzzy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ contract FlatFeeCalculatorTestFuzzy is Test {
uint256[] memory feeShares = new uint256[](1);
feeShares[0] = 100;
feeCalculator.feeSetup(recipients, feeShares);
feeCalculator.setFeeToUnderlyingDecimalsScale(1);
}

function testFeeSetupEmpty() public {
Expand Down Expand Up @@ -151,6 +152,21 @@ contract FlatFeeCalculatorTestFuzzy is Test {
assertEq(feeDistribution.shares[0], expected);
}

function testCalculateDepositFee_withFeeToUnderlyingScale_TCO2(uint256 depositAmount) public {
// Arrange
vm.assume(depositAmount > 1);
vm.assume(depositAmount < 1e18);

uint256 feeToUnderlyingDecimalsScale = 1e18;
feeCalculator.setFeeToUnderlyingDecimalsScale(feeToUnderlyingDecimalsScale);
// Act
FeeDistribution memory feeDistribution = feeCalculator.calculateDepositFees(empty, empty, depositAmount);

uint256 expected = depositAmount * feeToUnderlyingDecimalsScale * feeCalculator.feeBasisPoints() / 10000;

assertEq(feeDistribution.shares[0], expected);
}

function testCalculateDepositFee_ERC1155(uint256 depositAmount) public {
// Arrange
vm.assume(depositAmount > 100);
Expand All @@ -163,6 +179,21 @@ contract FlatFeeCalculatorTestFuzzy is Test {
assertEq(feeDistribution.shares[0], expected);
}

function testCalculateDepositFee_withFeeToUnderlyingScale_ERC1155(uint256 depositAmount) public {
// Arrange
vm.assume(depositAmount > 1);
vm.assume(depositAmount < 1e18);

uint256 feeToUnderlyingDecimalsScale = 1e18;
feeCalculator.setFeeToUnderlyingDecimalsScale(feeToUnderlyingDecimalsScale);
// Act
FeeDistribution memory feeDistribution = feeCalculator.calculateDepositFees(empty, empty, 0, depositAmount);

uint256 expected = depositAmount * feeToUnderlyingDecimalsScale * feeCalculator.feeBasisPoints() / 10000;

assertEq(feeDistribution.shares[0], expected);
}

function testCalculateRedemptionAmount_TCO2(
uint256 redemptionAmount1,
uint256 redemptionAmount2,
Expand Down Expand Up @@ -193,6 +224,39 @@ contract FlatFeeCalculatorTestFuzzy is Test {
assertEq(feeDistribution.shares[0], expected);
}

function testCalculateRedemptionAmount_withFeeToUnderlyingScale_TCO2(
uint256 redemptionAmount1,
uint256 redemptionAmount2,
uint256 redemptionAmount3
) public {
// Arrange
vm.assume(redemptionAmount1 > 100);
vm.assume(redemptionAmount1 < 1e18 * 1e18);
vm.assume(redemptionAmount2 > 100);
vm.assume(redemptionAmount2 < 1e18 * 1e18);
vm.assume(redemptionAmount3 > 100);
vm.assume(redemptionAmount3 < 1e18 * 1e18);

uint256 feeToUnderlyingDecimalsScale = 1e18;
feeCalculator.setFeeToUnderlyingDecimalsScale(feeToUnderlyingDecimalsScale);
// Act
address[] memory tco2s = new address[](3);
tco2s[0] = empty;
tco2s[1] = empty;
tco2s[2] = empty;
uint256[] memory redemptionAmounts = new uint256[](3);
redemptionAmounts[0] = redemptionAmount1;
redemptionAmounts[1] = redemptionAmount2;
redemptionAmounts[2] = redemptionAmount3;

FeeDistribution memory feeDistribution = feeCalculator.calculateRedemptionFees(empty, tco2s, redemptionAmounts);

uint256 expected = (redemptionAmount1 + redemptionAmount2 + redemptionAmount3) * feeToUnderlyingDecimalsScale
* feeCalculator.feeBasisPoints() / 10000;

assertEq(feeDistribution.shares[0], expected);
}

function testCalculateRedemptionAmount_ERC1155(
uint256 redemptionAmount1,
uint256 redemptionAmount2,
Expand Down Expand Up @@ -227,4 +291,42 @@ contract FlatFeeCalculatorTestFuzzy is Test {

assertEq(feeDistribution.shares[0], expected);
}

function testCalculateRedemptionAmount_withFeeToUnderlyingScale_ERC1155(
uint256 redemptionAmount1,
uint256 redemptionAmount2,
uint256 redemptionAmount3
) public {
// Arrange
vm.assume(redemptionAmount1 > 100);
vm.assume(redemptionAmount1 < 1e18 * 1e18);
vm.assume(redemptionAmount2 > 100);
vm.assume(redemptionAmount2 < 1e18 * 1e18);
vm.assume(redemptionAmount3 > 100);
vm.assume(redemptionAmount3 < 1e18 * 1e18);

uint256 feeToUnderlyingDecimalsScale = 1e18;
feeCalculator.setFeeToUnderlyingDecimalsScale(feeToUnderlyingDecimalsScale);
// Act
address[] memory erc1155s = new address[](3);
erc1155s[0] = empty;
erc1155s[1] = empty;
erc1155s[2] = empty;
uint256[] memory tokenIds = new uint256[](3);
tokenIds[0] = 1;
tokenIds[1] = 2;
tokenIds[2] = 3;
uint256[] memory redemptionAmounts = new uint256[](3);
redemptionAmounts[0] = redemptionAmount1;
redemptionAmounts[1] = redemptionAmount2;
redemptionAmounts[2] = redemptionAmount3;

FeeDistribution memory feeDistribution =
feeCalculator.calculateRedemptionFees(empty, erc1155s, tokenIds, redemptionAmounts);

uint256 expected = (redemptionAmount1 + redemptionAmount2 + redemptionAmount3) * feeToUnderlyingDecimalsScale
* feeCalculator.feeBasisPoints() / 10000;

assertEq(feeDistribution.shares[0], expected);
}
}
Loading