Mirror Protocol's short-farming lock contract (mirror-lock) tracked unlocked positions by a position_id key but never marked an entry as consumed after release_position transferred its collateral out. The CosmWasm handler read the position struct, dispatched the BankMsg::Send, and returned — without removing or flagging the storage entry. An attacker could therefore call release_position repeatedly on the same position_id, each call passing the maturity check and re-sending the same UST/aUST/mAsset collateral until the lock contract was drained. ~$90M flowed out across hundreds of duplicate-id calls starting 2021-10-08 and went unnoticed for seven months. The vulnerability class is missing state-mutation-after-effect in a withdrawal handler — the CosmWasm analogue of a missing `delete positions[id]` or `claimed[id] = true` write on an EVM withdraw function.
Classification: Smart Contract Language. Technique: Duplicate Call Exploit. Target type: DeFi Protocol. Affected chains: Terra. Implementation language: Rust.
- chain
- terra
- protocol
- Mirror
- bug_class
- logic
- date_occurred
- 2021-10-08
- loss_usd
- $90,000,000
- classification
- Smart Contract Language
- technique
- Duplicate Call Exploit
- target_type
- DeFi Protocol
- language
- Rust
- source_id
- dl:260