Reproduced Exploit
OctoDeFi — anyone sets the deposit fee to 100% and takes the deposit
setFunctionFeeConfig is external and has no onlyOwner. The percentage cap is 10000 bps, so 100% is a legal value. The caller writes that fee for the deposit selector, then deposits the user's 100e18. The vault pays the whole amount to the executor. The control reverts the setter for a non-owner, an…
Chain
Other
Category
access-control
Date
Jul 2025
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 61597-missing-access-control-on-critical-feecontroller-setters-cyf. Standalone Foundry PoC and full write-up: 61597-missing-access-control-on-critical-feecontroller-setters-cyf_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/access-control/missing-modifier
Key info#
| Protocol | OctoDeFi |
| Finding | Cyfrin, AuditVault 61597 |
| Vulnerable code | FeeController.setFunctionFeeConfig |
| Harm | The executor sets the fee to 100% and takes 100e18 of the next deposit. |
| Chain | local synthetic |
TL;DR#
setFunctionFeeConfig is external and has no onlyOwner. The percentage cap is 10000 bps, so 100% is a legal value. The caller writes that fee for the deposit selector, then deposits the user's 100e18. The vault pays the whole amount to the executor. The control reverts the setter for a non-owner, and the same deposit leaves 100e18 in the vault.
The vulnerable code#
function setFunctionFeeConfig(bytes4 _selector, FeeType _feeType, uint256 _feePercentage) external {
if (_feePercentage > maxFeeLimits[_feeType]) {
revert FeePercentageExceedLimit();
}
// @> VULN: no onlyOwner. The caller sets the deposit fee to 100%.
functionFeeConfigs[_selector] = FeeConfig(_feeType, _feePercentage);
}
The fix is onlyOwner on the setter.
Root cause#
The admin setter checks the percentage against maxFeeLimits and does not check the caller. 10000 is inside the cap.
Preconditions#
maxFeeLimits[Percent] is 10000. The depositor holds 100e18 and has approved the vault. The caller is not the owner. One block.
Attack walkthrough#
- The depositor is minted 100e18 and approves the vault.
- The caller writes
deposit.selectorto fee type Percent and 10000 bps. - The stored fee reads back as 10000.
depositpulls 100e18 and computesfee = amount * 10000 / 10000.- The vault transfers 100e18 to the executor. The vault and the depositor both end at 0.
Diagrams#
Impact#
The executor takes 100e18 of the deposit. The depositor is left with 0. With onlyOwner, the setter reverts and the deposit stays in the vault.
Remediation#
Add onlyOwner to setFunctionFeeConfig, setTokenGetter, and setGlobalTokenGetter.
How to reproduce#
cd 61597-missing-access-control-on-critical-feecontroller-setters-cyf_exp
forge test -vv
Sources#
- AuditVault finding: https://github.com/Auditware/AuditVault/blob/main/findings/61597-missing-access-control-on-critical-feecontroller-setters-cyf.md
- Cyfrin report: https://github.com/solodit/solodit_content/blob/main/reports/Cyfrin/2025-07-17-cyfrin-octodefi-v2.0.md
- Fix: https://github.com/octodefi/strategy-builder-plugin/pull/12
- Vulnerable function:
FeeController.setFunctionFeeConfig, as quoted in the finding.
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 61597-missing-access-control-on-critical-feecontroller-setters-cyf_exp (evm-hack-registry mirror).
- AuditVault finding: 61597-missing-access-control-on-critical-feecontroller-setters-cyf.
Alerts & third-party analyses
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.