# Moonbeam Missing Call Check Bugfix Review

Moonbeam custom precompiles failed to reject DELEGATECALL, letting a malicious contract impersonate its caller and drain approved native tokens via transferFrom.

- Payout: $1,050,000
- Severity: critical
- Program: Moonbeam
- Credited: pwning.eth
- Disclosed: 2022-07-28
- Write-up quality: 8/10
- Original: https://immunefi.com/blog/bug-fix-reviews/moonbeam-missing-call-check-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-moonbeam-missing-call-check-bugfix-review
- Tags: domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** Frontier EVM custom precompiled contracts (ERC-20 precompile over Substrate balances pallet)
**Root cause:** The EVM precompile dispatch had no check distinguishing DELEGATECALL from CALL/STATICCALL, so a delegatecall into a custom precompile executed in the caller's storage context and inherited the caller's msg.sender.
**Steps:**
1. Deploy malicious contract whose fallback/function calls the ERC-20 precompile's approve() with attacker as spender and max value.
2. Get a victim contract that makes arbitrary external calls (e.g. flashloan callback) to invoke the malicious contract, so the precompile sees the victim as msg.sender.
3. Precompile records max allowance from victim to attacker.
4. Attacker calls asset.transferFrom(victim, beneficiary, amount) to move native MOVR/GLMR.
**How found:** Researcher reasoned about EVM call semantics: DELEGATECALL preserves the original msg.sender and does not carry msg.value, and noticed the precompile had no logic to detect DELEGATECALL vs static CALL, so caller identity could be spoofed.
**Exploitation:** Attacker relies on a victim contract performing a user-controllable external call (flashloan callback, arbitrary-call DEX) to reach the malicious contract; the delegatecall into the precompile inherits the victim's msg.sender, granting max allowance, then transferFrom drains the victim's native token balance to the attacker's beneficiary.
**Escalation:** Any contract allowing arbitrary external calls (flashloan/callback patterns) becomes a victim, enabling theft of native assets across Moonbeam/Moonriver up to ~$100m.
**Insight:** For custom precompiles/native bridges, check whether the dispatch layer distinguishes CALL vs DELEGATECALL vs STATICCALL; a precompile that trusts msg.sender without that check lets any contract impersonate its caller via delegatecall, especially exploitable through arbitrary-call/flashloan callback surfaces.
