Normal behavior: a proxy deployment is initialized by the legitimate deployer so that OwnableUpgradeable records the deployer as owner().
Specific issue: ThunderLoan.initialize(address tswapAddress) (ThunderLoan.sol:139) is publicly callable by any address exactly once, and the proxy deployment and the initialize() call are separate transactions. An attacker watching the mempool front-runs the deployer's initialize() with a higher gas price, becomes the recorded owner() via the __Ownable_init() chain, and keeps every owner-gated power — including _authorizeUpgrade() at line 280.
Likelihood:
The deployment transaction and the initialize() transaction are separate, so a front-run window exists by construction; the attacker only needs to watch the mempool and pay a higher gas price.
initialize() has no access control and no deployer whitelist, so the front-run always succeeds within the window.
Impact:
Full protocol takeover: the attacker-owner can call setAllowedToken, updateFlashLoanFee, deleteAllowedToken and _authorizeUpgrade() (line 280) to install a malicious implementation.
All depositor funds can be drained through the malicious implementation or through fee/allowlist manipulation.
Explanation: deploy the implementation and an ERC1967Proxy with empty init data (proxy left uninitialized); before the legitimate deployer acts, an attacker EOA calls initialize(attackerTSwap) on the proxy — the call succeeds and the attacker becomes owner(); the attacker then calls upgradeToAndCall(maliciousImpl, "") through _authorizeUpgrade() and drains the pool. PoC requires forge verification.
Explanation: performing proxy deployment and initialize() in a single atomic transaction (factory or deployer contract) removes the front-run window entirely; asserting owner() == expectedDeployer right after deployment catches any misconfiguration before the protocol goes live.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.