Sécurité·9 min de lecture·Par Solingo

Attaques par Flash Loan Expliquées — Comment des Millions Sont Volés

Explorez comment les attaques par flash loan exploitent les protocoles DeFi via la manipulation d'oracle et les attaques de gouvernance. Apprenez les stratégies de prévention avec les oracles TWAP et Chainlink.

# Attaques par Flash Loan Expliquées — Comment des Millions Sont Volés

Les flash loans sont l'une des fonctionnalités les plus innovantes de la DeFi — et l'un de ses vecteurs d'attaque les plus exploités. En 2021 seulement, plus de 300 millions de dollars ont été volés via des attaques par flash loan.

Bien qu'étant une primitive DeFi légitime, les flash loans amplifient les vulnérabilités existantes, permettant aux attaquants de manipuler les marchés, les oracles, et la gouvernance avec zéro capital initial.

Dans cet article, nous allons disséquer comment fonctionnent les attaques par flash loan, examiner des exploits réels, et apprendre des stratégies de défense éprouvées.

Que Sont les Flash Loans ?

Un flash loan est un prêt non collatéralisé qui doit être emprunté et remboursé dans une seule transaction.

Caractéristiques Clés

  • Pas de collatéral requis — n'importe qui peut emprunter des millions instantanément
  • Transaction atomique — prêt + opérations + remboursement se produisent en un bloc
  • Liquidité instantanée — accès à un capital massif sans le posséder
  • Zéro risque pour le prêteur — si non remboursé, toute la transaction revert

Exemple (Flash Loan Aave)

interface IFlashLoanReceiver {

function executeOperation(

address[] calldata assets,

uint256[] calldata amounts,

uint256[] calldata premiums,

address initiator,

bytes calldata params

) external returns (bool);

}

contract FlashLoanUser is IFlashLoanReceiver {

ILendingPool public lendingPool;

function executeFlashLoan(address asset, uint256 amount) external {

address[] memory assets = new address[](1);

assets[0] = asset;

uint256[] memory amounts = new uint256[](1);

amounts[0] = amount;

uint256[] memory modes = new uint256[](1);

modes[0] = 0; // Pas de dette

lendingPool.flashLoan(

address(this),

assets,

amounts,

modes,

address(this),

"",

0

);

}

function executeOperation(

address[] calldata assets,

uint256[] calldata amounts,

uint256[] calldata premiums,

address initiator,

bytes calldata params

) external override returns (bool) {

// Vous avez maintenant amounts[0] de assets[0]

// Faire quelque chose avec les fonds flash loaned

// ... votre logique ici ...

// Rembourser prêt + frais

uint256 amountOwed = amounts[0] + premiums[0];

IERC20(assets[0]).approve(address(lendingPool), amountOwed);

return true;

}

}

Pourquoi les Flash Loans Sont Dangereux

Les flash loans eux-mêmes ne sont pas malveillants, mais ils amplifient les vulnérabilités existantes en fournissant :

  • Capital illimité — exploiter de petites inefficacités à échelle massive
  • Exécution atomique — attaques multi-protocoles complexes en une transaction
  • Zéro risque — si l'attaque échoue, la transaction revert (pas de perte pour l'attaquant)
  • Vecteurs d'Attaque par Flash Loan

    1. Manipulation d'Oracle

    Type d'attaque le plus courant. Manipuler les oracles de prix pour exploiter les protocoles qui s'y fient.

    Pattern d'Oracle Vulnérable

    contract VulnerableLending {
    

    IERC20 public tokenA;

    IUniswapV2Pair public pair; // TokenA/WETH

    // VULNÉRABLE : Utilisation du prix spot du DEX

    function getPrice() public view returns (uint256) {

    (uint112 reserve0, uint112 reserve1,) = pair.getReserves();

    return (reserve1 * 1e18) / reserve0; // Prix instantané

    }

    function borrow(uint256 amount) external {

    uint256 collateralRequired = (amount * getPrice()) / 1e18;

    require(tokenA.balanceOf(msg.sender) >= collateralRequired);

    // L'utilisateur peut emprunter basé sur prix manipulé

    // ...

    }

    }

    Scénario d'Attaque

    contract OracleAttack {
    

    function attack() external {

    // 1. Flash loan grande quantité de TokenA

    uint256 loanAmount = 1000000 * 1e18;

    flashLoan(address(tokenA), loanAmount);

    }

    function executeOperation(/*...*/) external {

    // 2. Dumper TokenA sur DEX, crasher le prix

    tokenA.approve(address(router), loanAmount);

    router.swapExactTokensForTokens(

    loanAmount,

    0,

    path,

    address(this),

    block.timestamp

    );

    // Le prix est maintenant artificiellement bas

    // 3. Emprunter montant massif du protocole de prêt

    // (qui pense que le collatéral vaut plus à cause du prix TokenA bas)

    lendingProtocol.borrow(exploitAmount);

    // 4. Swap de retour pour restaurer le prix

    router.swapExactTokensForTokens(/*...*/);

    // 5. Rembourser flash loan

    tokenA.transfer(lender, loanAmount + fee);

    // L'attaquant garde les fonds sur-empruntés

    }

    }

    Exemple réel : Harvest Finance (2020) — 24M$ volés via manipulation de prix sur les pools Curve.

    2. Attaques de Gouvernance

    Flash loan de tokens de gouvernance massifs pour passer des propositions malveillantes.

    Gouvernance Vulnérable

    contract VulnerableDAO {
    

    IERC20 public govToken;

    struct Proposal {

    address target;

    bytes data;

    uint256 forVotes;

    uint256 againstVotes;

    bool executed;

    }

    mapping(uint256 => Proposal) public proposals;

    // VULNÉRABLE : Snapshot au moment du vote, pas de création de proposition

    function vote(uint256 proposalId, bool support) external {

    uint256 votes = govToken.balanceOf(msg.sender);

    if (support) {

    proposals[proposalId].forVotes += votes;

    } else {

    proposals[proposalId].againstVotes += votes;

    }

    }

    function execute(uint256 proposalId) external {

    Proposal storage prop = proposals[proposalId];

    require(prop.forVotes > prop.againstVotes);

    require(!prop.executed);

    prop.executed = true;

    (bool success,) = prop.target.call(prop.data);

    require(success);

    }

    }

    Attaque

    function governanceAttack() external {
    

    // 1. Flash loan tokens de gouvernance

    flashLoan(address(govToken), 51% of supply);

    // 2. Créer proposition malveillante

    dao.propose(address(treasury), abi.encodeWithSignature(

    "transfer(address,uint256)",

    attacker,

    treasury.balance

    ));

    // 3. Voter avec tokens flash loaned

    dao.vote(proposalId, true);

    // 4. Exécuter immédiatement (si pas de timelock)

    dao.execute(proposalId);

    // 5. Rembourser flash loan

    govToken.transfer(lender, amount + fee);

    }

    Exemple réel : Beanstalk (2022) — 182M$ volés via prise de contrôle de gouvernance avec tokens flash loaned.

    3. Amplification de Réentrance

    Les flash loans fournissent du capital pour des attaques de réentrance sur des protocoles mal protégés.

    function amplifiedReentrancy() external {
    

    // 1. Flash loan montant important

    flashLoan(10000 ether);

    // 2. Déposer au protocole vulnérable

    vulnerable.deposit{value: 10000 ether}();

    // 3. Exploiter réentrance pour retirer répétitivement

    vulnerable.withdraw(10000 ether);

    // La réentrance draine plus que déposé

    // 4. Rembourser flash loan

    lender.transfer(10000 ether + fee);

    // Garder l'excès

    }

    4. Manipulation de Liquidation

    Manipuler les prix de collatéral pour déclencher des liquidations de masse, puis acheter le collatéral pas cher.

    Attaques par Flash Loan Réelles

    Harvest Finance (Octobre 2020)

    • Volé : 24M$
    • Méthode : Manipulation de prix pool Curve
    • Flash loan de : Uniswap (pas de frais à l'époque)
    • Résultat : Le protocole a survécu mais les utilisateurs ont perdu des fonds

    PancakeBunny (Mai 2021)

    • Volé : 45M$
    • Méthode : Manipulation d'oracle de prix sur PancakeSwap
    • Impact : Token BUNNY a chuté de 96%

    Cream Finance (Août 2021)

    • Volé : 18.8M$
    • Méthode : Flash loan + manipulation oracle de prix sur token AMP
    • Répétition : Cream a été hacké 3 fois en 2021

    Beanstalk (Avril 2022)

    • Volé : 182M$
    • Méthode : Attaque de gouvernance par flash loan
    • Loans de : Aave (1B$ emprunté)
    • Exécution : Proposition malveillante passée, trésorerie drainée

    Euler Finance (Mars 2023)

    • Volé : 197M$ (retourné plus tard)
    • Méthode : Flash loan + attaque par donation pour manipuler le tracking de dette
    • Plus gros hack DeFi de 2023

    Stratégies de Prévention

    1. Oracles TWAP (Time-Weighted Average Price)

    N'utilisez pas les prix spot. Utilisez des moyennes pondérées dans le temps qui ne peuvent être manipulées en une seule transaction.

    contract TWAPOracle {
    

    IUniswapV2Pair public pair;

    uint256 public priceAverage;

    uint256 public lastUpdate;

    uint32 public constant PERIOD = 10 minutes;

    function update() external {

    uint32 timeElapsed = uint32(block.timestamp - lastUpdate);

    require(timeElapsed >= PERIOD, "Too soon");

    (uint256 price0Cumulative, uint256 price1Cumulative,) =

    UniswapV2OracleLibrary.currentCumulativePrices(address(pair));

    priceAverage = (price0Cumulative - price0CumulativeOld) / timeElapsed;

    lastUpdate = block.timestamp;

    price0CumulativeOld = price0Cumulative;

    }

    function getPrice() external view returns (uint256) {

    return priceAverage; // Résistant à la manipulation

    }

    }

    Pourquoi ça marche : Les attaques par flash loan se produisent en une transaction. TWAP nécessite des changements de prix sur plusieurs blocs.

    Utilisez des oracles de prix décentralisés, externes, qui ne peuvent être manipulés via des trades on-chain.

    import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
    
    

    contract SecureLending {

    AggregatorV3Interface internal priceFeed;

    constructor(address _priceFeed) {

    priceFeed = AggregatorV3Interface(_priceFeed);

    }

    function getLatestPrice() public view returns (int) {

    (

    uint80 roundID,

    int price,

    uint startedAt,

    uint timeStamp,

    uint80 answeredInRound

    ) = priceFeed.latestRoundData();

    require(timeStamp > 0, "Round not complete");

    return price;

    }

    }

    Avantages :

    • Données agrégées de multiples sources
    • Mis à jour off-chain (non manipulable via flash loans)
    • Battle-tested sur des milliards en TVL

    3. Gouvernance par Snapshot

    Pour les DAOs, utilisez des snapshots basés sur les blocs pris avant le début du vote.

    contract SecureGovernance {
    

    mapping(uint256 => uint256) public proposalSnapshots;

    function propose(/*...*/) external returns (uint256) {

    uint256 proposalId = proposalCount++;

    // Snapshot AVANT le début du vote

    proposalSnapshots[proposalId] = block.number;

    return proposalId;

    }

    function vote(uint256 proposalId, bool support) external {

    // Utiliser le solde au bloc du snapshot

    uint256 votes = govToken.balanceOfAt(

    msg.sender,

    proposalSnapshots[proposalId]

    );

    // Les flash loans après création de proposition ne comptent pas

    }

    }

    4. Délais d'Exécution

    Ajouter des timelocks pour empêcher l'exécution instantanée.

    contract TimelockDAO {
    

    uint256 public constant DELAY = 2 days;

    struct Proposal {

    uint256 eta; // Temps d'exécution le plus tôt

    // ...

    }

    function queue(uint256 proposalId) external {

    require(proposalPassed(proposalId));

    proposals[proposalId].eta = block.timestamp + DELAY;

    }

    function execute(uint256 proposalId) external {

    require(block.timestamp >= proposals[proposalId].eta);

    // Exécuter

    }

    }

    Les flash loans doivent être remboursés en une transaction, donc ils ne peuvent pas attendre 2 jours.

    5. Détection de Flash Loan

    Bloquer l'utilisation de flash loan pour les fonctions sensibles.

    contract FlashLoanProtected {
    

    mapping(address => uint256) private balanceSnapshot;

    modifier noFlashLoan() {

    uint256 balanceBefore = balanceSnapshot[msg.sender];

    // Première interaction dans cette transaction

    if (balanceBefore == 0) {

    balanceSnapshot[msg.sender] = token.balanceOf(msg.sender);

    } else {

    // Le solde ne devrait pas spike dans la même transaction

    require(

    token.balanceOf(msg.sender) <= balanceBefore * 2,

    "Flash loan detected"

    );

    }

    _;

    }

    function sensitiveAction() external noFlashLoan {

    // Protégé

    }

    }

    Note : Ceci peut avoir des faux positifs, utiliser avec précaution.

    Résumé des Bonnes Pratiques

    Pour les Protocoles de Prêt

    ✅ Utiliser Chainlink ou oracles TWAP, jamais les prix spot

    ✅ Implémenter des vérifications de santé sur les changements de prix

    ✅ Ajouter des circuit breakers pour conditions de marché anormales

    ✅ Nécessiter des délais multi-blocs pour les changements de position importants

    Pour les DAOs

    ✅ Snapshot des soldes à la création de proposition

    ✅ Ajouter des timelocks (minimum 24-48 heures)

    ✅ Nécessiter un quorum de holders long-terme

    ✅ Utiliser la délégation de vote pour empêcher les attaques de gouvernance de dernière minute

    Pour Tous les Protocoles DeFi

    ✅ Auditer toutes les dépendances de prix

    ✅ Tester avec des scénarios d'attaque par flash loan

    ✅ Monitorer les patterns de transaction inhabituels

    ✅ Avoir des mécanismes de pause d'urgence

    ✅ Maintenir des programmes de bug bounty

    Conclusion

    Les flash loans sont une primitive DeFi puissante qui démocratise l'accès au capital — mais ils démocratisent aussi l'accès aux exploits.

    Les attaques ne sont pas causées par les flash loans eux-mêmes, mais par des vulnérabilités sous-jacentes que les flash loans amplifient :

    • Oracles faibles (utiliser TWAP ou Chainlink)
    • Gouvernance instantanée (ajouter snapshots et timelocks)
    • Réentrance (utiliser des guards)
    • Liquidations non protégées (ajouter des délais)

    Le bottom line : Si votre protocole peut être exploité avec assez de capital, supposez que quelqu'un va flash loan ce capital.

    Pratiquez la défense contre les flash loans sur Solingo — nos exercices simulent des attaques réelles incluant manipulation d'oracle et prises de contrôle de gouvernance, avec implémentation de défense étape par étape.

    Prêt à mettre en pratique ?

    Applique ces concepts avec des exercices interactifs sur Solingo.

    Commencer gratuitement