Skip to content

Commit

Permalink
Merge pull request #55 from neutral-protocol/fix/decimals-adjust
Browse files Browse the repository at this point in the history
feat: allow for different decimals between fee token and underlying
  • Loading branch information
sirnicolaz authored May 21, 2024
2 parents 09f9cdd + 57c38e9 commit 4857231
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 2 deletions.
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);
}
}

0 comments on commit 4857231

Please sign in to comment.