Silo_Module::silo_execute will revert as approval is to the wrong contract
silo_execute approves actions[0].silo for the input asset, but the Silo router (not the silo itself) is the one that pulls tokens for the batched execution. As written, the first action of the bundle fails approval-side and the gas savings the function was meant to deliver are lost.
Description
D2 integrates with the lending protocol Silo via the Silo_Module, which facilitates communication with the Silo contract.
One of the functions in this module is Silo_Module::silo_execute, which allows bundling multiple calls and sending them to the Silo Router to optimize gas usage:
function silo_execute(ISiloRouter.Action[] calldata actions) external onlyRole(EXECUTOR_ROLE)nonReentrant {// @audit approval should be to `address(router)` as it is the one facilitating the actionsIERC20(actions[0].asset).approve(actions[0].silo, actions[0].amount);router.execute(actions);}
The issue here is that the approval is incorrectly granted to actions[0].silo, whereas it should be granted to router, as this is the contract responsible for handling all token transfers when router.execute(actions) is invoked.
The audit included a Foundry PoC (test_silo_execute) that builds a bundle of (deposit, borrow, repay, withdraw) actions and shows the execution fails on the deposit step due to insufficient allowance for the router.
Impact
The silo_execute function will fail due to the incorrect approval. While this does not affect the overall functionality of Silo_Module (since all necessary actions can still be executed separately), the gas savings intended by bundling transactions will be lost, leading to higher transaction costs.
Recommendation
Consider approving router instead:
- IERC20(actions[0].asset).approve(actions[0].silo, actions[0].amount);+ IERC20(actions[0].asset).approve(address(router), actions[0].amount);
Resolution
D2: Fixed in ea03f4d.
Cyfrin: Verified.