Skip to content

Commit

Permalink
squash! chore(FeesManager): add FeesManager contract coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
gitmp01 committed Jul 28, 2024
1 parent 400b7b4 commit 065afa2
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 5 deletions.
10 changes: 6 additions & 4 deletions solidity/src/FeesManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ contract FeesManager is IFeesManager, Ownable {
using SafeERC20 for IERC20;
uint16 public currentEpoch;

bytes32 public WITHDRAW_ROLE;
bytes32 public UPGRADE_ROLE;
bytes32 public SET_FEE_ROLE;

mapping(uint16 => mapping(address => uint256))
public depositedAmountByEpoch;
mapping(uint16 => mapping(address => mapping(address => uint256)))
Expand All @@ -26,6 +22,7 @@ contract FeesManager is IFeesManager, Ownable {
mapping(address => Fee) public feeInfoByAsset;

event FeeUpdated(address token, uint256 minFee, uint16 basisPoints);
event NewEpochStarted(uint16 epoch);

error InvalidToken();
error InvalidFromAddress();
Expand Down Expand Up @@ -82,11 +79,16 @@ contract FeesManager is IFeesManager, Ownable {
address[] calldata nodes,
uint256[] calldata amounts
) external onlyOwner {
if (nodes.length != amounts.length)
revert DifferentLength(nodes.length, amounts.length);

currentEpoch += 1;
for (uint i = 0; i < nodes.length; i++) {
stakedAmountByEpoch[currentEpoch][nodes[i]] = amounts[i];
totalStakedAmountByEpoch[currentEpoch] += amounts[i];
}

emit NewEpochStarted(currentEpoch);
}

/// @inheritdoc IFeesManager
Expand Down
2 changes: 1 addition & 1 deletion solidity/src/xerc20/XERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit {
feesManager = newAddress;
} else if (msg.sender != feesManager) revert OnlyFeesManager();

if (newAddress.code.length == 0) revert NotAContract(feesManager);
if (newAddress.code.length == 0) revert NotAContract(newAddress);

feesManager = newAddress;

Expand Down
168 changes: 168 additions & 0 deletions solidity/test/forge/FeesManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,37 @@ contract FeesManagerTest is Test, Helper {
vm.stopPrank();
}

function test_constructor_nodesAndStakedAmountsSetCorrectly() public view {
uint16 epoch = 0;
for (uint i = 0; i < nodes.length; i++) {
assertEq(
feesManager.stakedAmountByEpoch(epoch, nodes[i]),
stakedAmounts[i]
);
}

assertEq(feesManager.totalStakedAmountByEpoch(epoch), totalStaked);
}

function test_constructor_RevertWhen_nodesAndAmountsHaveDifferentLength()
public
{
uint16 epoch = 0;
uint256 lenX = 2;
uint256 lenY = 1;
address[] memory x = new address[](lenX);
uint256[] memory y = new uint256[](lenY);
vm.prank(owner);
vm.expectRevert(
abi.encodeWithSelector(
FeesManager.DifferentLength.selector,
lenX,
lenY
)
);
new FeesManager(epoch, x, y);
}

function test_setFees_EmitFeesUpdatedEvent() public {
uint256 minAmount = 0;
uint16 basisPoints = 2000;
Expand Down Expand Up @@ -181,6 +212,19 @@ contract FeesManagerTest is Test, Helper {
assertEq(userBalancePre - userBalancePost, fees);
assertEq(xerc20.balanceOf(address(feesManager)), fees);
assertEq(xerc20.balanceOf(address(feesManager)), fees);
assertEq(
feesManager.depositedAmountByEpoch(epoch, address(xerc20)),
fees
);

vm.startPrank(user);
xerc20.approve(address(feesManager), fees);
feesManager.depositFee(address(xerc20), fees);

assertEq(
feesManager.depositedAmountByEpoch(epoch, address(xerc20)),
fees * 2
);
}

function testFuzz_calculateFee_returnTheCorrectFees(
Expand Down Expand Up @@ -279,4 +323,128 @@ contract FeesManagerTest is Test, Helper {
feesManager.claimFeeByEpoch(address(xerc20), epoch);
vm.stopPrank();
}

function test_registerAndAdvanceEpoch_RevertWhen_callerIsNotTheOwner()
public
{
vm.prank(evil);
_expectOwnableUnauthorizedAccountRevert(evil);
feesManager.registerAndAdvanceEpoch(nodes, stakedAmounts);
}

function test_registerAndAdvanceEpoch_RevertWhen_nodesAndAmountsHaveDifferentLength()
public
{
uint256 lenX = 2;
uint256 lenY = 1;
address[] memory x = new address[](lenX);
uint256[] memory y = new uint256[](lenY);
vm.prank(owner);
vm.expectRevert(
abi.encodeWithSelector(
FeesManager.DifferentLength.selector,
lenX,
lenY
)
);

feesManager.registerAndAdvanceEpoch(x, y);
}

function test_registerAndAdvanceEpoch_EmitNewEpochStartedEvent() public {
address[] memory newNodes = new address[](3);
uint256[] memory newStakedAmounts = new uint256[](3);

newNodes[0] = node2;
newNodes[1] = node4;
newNodes[2] = node5;
newStakedAmounts[0] = stakedAmount2;
newStakedAmounts[1] = stakedAmount4;
newStakedAmounts[2] = stakedAmount5;

address[] memory nodesWithoutStaking = new address[](3);
nodesWithoutStaking[0] = node0;
nodesWithoutStaking[1] = node1;
nodesWithoutStaking[2] = node3;

uint256 newTotalStakedAmount = stakedAmount2 +
stakedAmount4 +
stakedAmount5;
uint16 expectedEpoch = feesManager.currentEpoch() + 1;

vm.prank(owner);
vm.expectEmit(address(feesManager));
emit FeesManager.NewEpochStarted(expectedEpoch);
feesManager.registerAndAdvanceEpoch(newNodes, newStakedAmounts);

assertEq(feesManager.currentEpoch(), expectedEpoch);

for (uint i = 0; i < newNodes.length; i++) {
assertEq(
feesManager.stakedAmountByEpoch(expectedEpoch, newNodes[i]),
newStakedAmounts[i]
);
}

for (uint i = 0; i < nodesWithoutStaking.length; i++) {
assertEq(
feesManager.stakedAmountByEpoch(
expectedEpoch,
nodesWithoutStaking[i]
),
0
);
}

assertEq(
feesManager.totalStakedAmountByEpoch(expectedEpoch),
newTotalStakedAmount
);
}

function test_setFeesManagerForXERC20_onlyFeesManagerCanChangeTheAddress()
public
{
vm.expectEmit(address(xerc20));
emit XERC20.FeesManagerChanged(address(feesManager));
xerc20.setFeesManager(address(feesManager));

vm.startPrank(owner);
vm.expectRevert(XERC20.OnlyFeesManager.selector);
xerc20.setFeesManager(address(0));

address notAContract = vm.addr(2222);
vm.expectRevert(
abi.encodeWithSelector(XERC20.NotAContract.selector, notAContract)
);
feesManager.setFeesManagerForXERC20(address(xerc20), notAContract);

uint16 epoch = 0;
FeesManager newFeesManager = new FeesManager(
epoch,
nodes,
stakedAmounts
);
vm.expectEmit(address(xerc20));
emit XERC20.FeesManagerChanged(address(newFeesManager));
feesManager.setFeesManagerForXERC20(
address(xerc20),
address(newFeesManager)
);

// Try to reset the original fees manager
vm.expectRevert(XERC20.OnlyFeesManager.selector);
feesManager.setFeesManagerForXERC20(
address(xerc20),
address(feesManager)
);
}

function test_setFeesManagerForXERC20_RevertWhen_callerIsNotOwner() public {
xerc20.setFeesManager(address(feesManager));

vm.prank(evil);
_expectOwnableUnauthorizedAccountRevert(evil);
feesManager.setFeesManagerForXERC20(address(xerc20), address(0));
}
}

0 comments on commit 065afa2

Please sign in to comment.