Reproduced Exploit
TRZN — RM_UpdateReward has no access control
RM_UpdateReward is named for the risk manager. The stored risk manager is 0xbeef. The function does not read msg.sender. A caller sets reward to 1000, the vault's entire balance, and claim transfers it. The same call on a function that requires the risk manager reverts, and the 1000 tokens stay. ru…
Chain
Other
Category
access-control
Date
Jan 2024
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: 37230-function-rm-updatereward-in-vaulteth-v2-has-no-access-contro. Standalone Foundry PoC and full write-up: 37230-function-rm-updatereward-in-vaulteth-v2-has-no-access-contro_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/access-control/missing-modifier · vuln/access-control/missing-auth
Reproduction: a self-contained Foundry PoC that compiles and runs offline with only
forge-std— no fork and no RPC. Trace: output.txt. PoC: test/37230-function-rm-updatereward-in-vaulteth-v2-has-no-access-contro_exp.sol.
Key info#
| Impact | HIGH — any caller sets the claimable reward to 1000 and takes the vault's reward tokens |
| Protocol | TRZN VaultETH_V2.RM_UpdateReward |
| Vulnerable code | reward = newReward with no caller check |
| Bug class | Missing risk-manager authorization |
| Finding | Zokyo — TRZN Finance · id 37230 |
| Report | Zokyo TRZN Finance, 12 Jan 2024 |
| Source | AuditVault finding |
| Status | The report says the issue was resolved. Reproduced as a local synthetic. |
| Compiler | solc 0.8.27, cancun, via IR |
TL;DR#
RM_UpdateReward is named for the risk manager. The stored risk manager is 0xbeef. The function does not read msg.sender. A caller sets reward to 1000, the vault's entire balance, and claim transfers it. The same call on a function that requires the risk manager reverts, and the 1000 tokens stay. run() does not warp.
The vulnerable code#
function RM_UpdateReward(uint256 newReward) external {
// @> VULN: RM_UpdateReward has no risk-manager check
reward = newReward;
}
Root cause#
The report says any user can call a function that is supposed to be limited to risk managers. The reward value is what claim pays out of the vault.
Preconditions#
- The vault holds 1000 reward tokens funded for stakers.
- The caller is not the risk manager.
Attack walkthrough#
RM_UpdateReward(1000 ether)writesreward.claimcopiesreward, zeroes it, and transfers 1000 tokens to the caller.- The vault balance is 0.
Diagrams#
Impact#
Stakers lose the 1000 reward tokens. The caller did not stake and is not the risk manager.
Remediation#
Require msg.sender to be the risk manager before writing reward.
How to reproduce#
cd evm-hack-registry/37230-function-rm-updatereward-in-vaulteth-v2-has-no-access-contro_exp
forge test -vv
Sources#
- AuditVault finding 37230
- Zokyo, TRZN Finance, 12 January 2024,
VaultETH_V2.RM_UpdateReward
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 37230-function-rm-updatereward-in-vaulteth-v2-has-no-access-contro_exp (evm-hack-registry mirror).
- AuditVault finding: 37230-function-rm-updatereward-in-vaulteth-v2-has-no-access-contro.
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.