Skip to content

Flawed Migration Contracts

id: LS20H
title: Flawed Migration Contracts 
baseSeverity: H
category: migration
language: solidity
blockchain: [ethereum]
impact: Users can lose funds or mint duplicate tokens during token/system upgrades
status: draft
complexity: medium
attack_vector: internal
mitigation_difficulty: medium
versions: [">=0.6.0", "<latest"]
cwe: CWE-640
swc: SWC-135

๐Ÿ“ Description

  • Flawed migration contracts refer to unsafe upgrade/migration logic used when moving from one token, staking contract, or protocol version to another.
  • If migration contracts are poorly designed, they may:
  • Allow multiple migrations for the same user,
  • Fail to track migration status or amounts properly,
  • Introduce supply mismatches due to incorrect mint/burn logic
  • Be vulnerable to reentrancy or replay attacks.
  • Migration contracts are especially risky if they combine minting, user-supplied approvals, and off-chain indexed logic (like Merkle roots) without robust validation.

๐Ÿšจ Vulnerable Code

contract BrokenMigrator {
    mapping(address => bool) public migrated;

    function migrate(address user, uint256 amount) external {
        // โŒ Does not check if amount has already been migrated
        oldToken.transferFrom(user, address(this), amount);
        _mint(user, amount);
    }
}

๐Ÿงช Exploit Scenario

Step-by-step impact:

  1. A user migrates 100 tokens using the flawed migrate() function.
  2. The contract does not mark the user or amount as migrated.
  3. The same user (or attacker) repeats the call with the same allowance.
  4. New tokens are minted again, doubling the balance without burning old tokens.

Assumptions:

  • No tracking of per-user migration status or per-amount claim.
  • Minting logic is tied only to transferFrom() without verification.

โœ… Fixed Code

contract SafeMigrator {
    mapping(address => uint256) public migratedAmount;

    function migrate(address user, uint256 amount) external {
        require(amount > 0, "Zero migration");
        require(migratedAmount[user] == 0, "Already migrated");

        oldToken.transferFrom(user, address(this), amount);
        migratedAmount[user] = amount;
        _mint(user, amount);
    }
}

๐Ÿงญ Contextual Severity

- context: "Migration allows minting based on unverified or reentrant state"
  severity: H
  reasoning: "Leads to fund inflation or protocol state corruption"
- context: "Only admin-initiated migrations, manually validated"
  severity: M
  reasoning: "Risk is lower but still present in poorly tested flows"
- context: "State-proof-based or Merkle-audited migration"
  severity: L
  reasoning: "Risk minimal with verified snapshot-based migration"

๐Ÿ›ก๏ธ Prevention

Primary Defenses

  • Track per-user claim or migration status with mappings (hasClaimed, migratedAmount, etc.).
  • Use one-time Merkle proofs for scalable off-chain tracking with on-chain verification.
  • Burn or lock migrated tokens to avoid dual liquidity and supply inflation.

Additional Safeguards

  • Use nonReentrant modifier if external calls are made during migration.
  • Emit Migrated(address, amount) events for off-chain indexing.
  • Include total migrated accounting to reconcile old vs new supply.

Detection Methods

  • Slither: migration-untracked, double-mint, missing-claim-status detectors.
  • Manual audits of minting and migration logic with user-supplied inputs.
  • Integration and fuzz tests simulating repeated migration attempts.

๐Ÿ•ฐ๏ธ Historical Exploits

  • Name: KiloEx TrustedForwarder Exploit
  • Date: April 13, 2025
  • Loss: Approximately $7 million
  • Post-mortem: Link to post-mortem

๐Ÿ“š Further Reading


โœ… Vulnerability Report

id: LS20H
title: Flawed Migration Contracts 
severity: H
score:
impact: 5         
exploitability: 3 
reachability: 4   
complexity: 2     
detectability: 5  
finalScore: 4.1

๐Ÿ“„ Justifications & Analysis

  • Impact: High โ€” duplicate claims or wrong balances undermine protocol integrity.
  • Exploitability: Medium โ€” requires flawed checks, but no signature needed.
  • Reachability: Found in a large number of token/staking upgrade contracts.
  • Complexity: Easy to introduce; mitigated with proper state tracking.
  • Detectability: High โ€” visible with tests, audit rules, and user simulations.