The distributeFees function is designed to distribute fees between the liquidation pool and the protocol. It calculates the fees for the pool based on the poolFeePercentage and then calls approve on the EUROs token to allow the pool to pull the calculated fee amount. If the approve call fails, the contract does not revert or handle the failure, and it proceeds to transfer the remaining EUROs balance to the protocol address. This could result in the pool not receiving its intended fees.
Deploy the LiquidationPoolManager contract.
Simulate a scenario where the approve function of the EUROs token contract reverts or returns false (e.g., due to a bug or change in the token contract).
Call distributeFees from any account.
Observe that the approve call fails, but the contract still attempts to transfer the remaining EUROs balance to the protocol.
function distributeFees() public {
IERC20 eurosToken = IERC20(EUROs);
uint256 _feesForPool = eurosToken.balanceOf(address(this)) * poolFeePercentage / HUNDRED_PC;
if (_feesForPool > 0) {
eurosToken.approve(pool, _feesForPool); // No check for return value
LiquidationPool(pool).distributeFees(_feesForPool);
}
eurosToken.transfer(protocol, eurosToken.balanceOf(address(this)));
}
If the approve call fails and is not handled, the pool will not be able to claim the fees it is entitled to, resulting in a loss of funds for the pool. This could disrupt the intended economic mechanisms of the contract and erode trust in the system.
Ensure that the return value of the approve call is checked and handled appropriately. If the approve call fails, the function should revert to prevent any further actions that could lead to a loss of funds. The following code snippet demonstrates how to add this check:
function distributeFees() public {
IERC20 eurosToken = IERC20(EUROs);
uint256 _feesForPool = eurosToken.balanceOf(address(this)) * poolFeePercentage / HUNDRED_PC;
if (_feesForPool > 0) {
require(eurosToken.approve(pool, _feesForPool), "Approval failed"); // Check for return value
LiquidationPool(pool).distributeFees(_feesForPool);
}
eurosToken.transfer(protocol, eurosToken.balanceOf(address(this)));
}
By adding the require statement, the contract will revert if the approve call fails, ensuring that the pool will not miss out on receiving its fees and preventing the potential loss of funds.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.