# TIME: ERC-2771 + Multicall address spoofing drains pair

TIME token's ERC-2771 forwarder plus Multicall let an attacker spoof _msgSender() as the pair address and burn tokens to inflate price, netting ~84.59 ETH.

- Payout: Real-world hack
- Severity: critical
- Program: TIME
- Analysis by: DeFiHackLabs
- Disclosed: 2023-12-06
- Write-up quality: 8/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-12/TIME_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20231206-time
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic vuln:signature-replay

**Target:** ERC-2771 trusted forwarder + Multicall token contract
**Root cause:** Multicall delegatecalls into the token, and ERC2771Context reads _msgSender() from the last 20 bytes of calldata; wrapping a call in a forwarded request lets the attacker append an arbitrary address (the TIME/WETH pair) as the spoofed sender.
**Steps:**
1. Flash/own 5 ETH, deposit to WETH, swap WETH->TIME via Uniswap V2 router.
2. Build multicall data containing `TIME.burn(62227259510e18, TIME_WETH_pair)` so the burn's second arg (pair address) becomes the trailing 20 bytes of calldata.
3. Wrap in ForwardRequest{from: recoverAddr, to: TIME, data: multicall(...)} and sign with recoverAddr's key (recovered from attack tx).
4. Call `Forwarder.execute(request, signature)`; ERC2771Context strips last 20 bytes and resolves _msgSender() to the pair address.
5. burn() executes as if called by the pair, burning TIME from the pair's balance and inflating TIME price.
6. TIME_WETH.sync(); swap TIME->WETH; withdraw ETH (~84.59 ETH profit).
**How found:** OpenZeppelin/thirdweb identified that combining Multicall's self-delegatecall with ERC2771Context's calldata-suffix sender extraction allows arbitrary _msgSender() spoofing; any function trusting _msgSender() (burn, transferFrom, onlyOwner) becomes attacker-controllable.
**Exploitation:** Attacker acquired TIME via router, then used a signed ERC-2771 forward request whose calldata ended with the TIME/WETH pair address. Multicall delegatecalled burn(), and ERC2771Context misattributed the caller as the pair, letting the attacker burn the pair's TIME reserves. Reserves were synced and the attacker swapped back to WETH, extracting ~84.59 ETH.
**Escalation:** Same integration pattern exploited across multiple thirdweb-forked contracts (Polygon USDC ~17,394, plus several ETH pools), coordinated mass exploitation.
**Insight:** When a contract both delegatecalls user data to itself and derives identity from calldata (ERC-2771, meta-tx, GSN), the trailing bytes are attacker-controlled — look for any state-changing function whose authorization or accounting depends on _msgSender(), especially burn/transferFrom against a pool address.
