DEV Community

THE CODE DOCTOR
THE CODE DOCTOR

Posted on

03.DEFI ATTACKS - Falsche Slippagekalkulation

Die Slippage-Parameter sollten in etwa als "minTokensOut" definiert sein – also die minimale Anzahl an Token, die der Nutzer bei einem Swap akzeptieren würde. Alles, was davon abweicht, sollte als Warnsignal betrachtet werden, da dies höchstwahrscheinlich einen fehlerhaften Slippage-Parameter darstellt.

Zur Veranschaulichung könnte man sich diesen vereinfachten Code aus OpenZeppelins Audit von Origin Dollar ansehen. Hierbei wird gezeigt, dass falsche oder ungenaue Slippage-Parameter potenziell zu einem ungewollten Verlust von Vermögenswerten führen können, wenn der minimale Token-Ausgang nicht korrekt festgelegt ist.

function withdraw(address _recipient, address _asset, uint256 _amount
) external onlyVault nonReentrant {
    // ...

    // Calculate how much of the pool token we need to withdraw
    (uint256 contractPTokens, , uint256 totalPTokens) = _getTotalPTokens();

    uint256 poolCoinIndex = _getPoolCoinIndex(_asset);
    // Calculate the max amount of the asset we'd get if we withdrew all the
    // platform tokens
    ICurvePool curvePool = ICurvePool(platformAddress);
    uint256 maxAmount = curvePool.calc_withdraw_one_coin(
        totalPTokens,
        int128(poolCoinIndex)
    );

    // Calculate how many platform tokens we need to withdraw the asset amount
    uint256 withdrawPTokens = totalPTokens.mul(_amount).div(maxAmount);

    // Calculate a minimum withdrawal amount
    uint256 assetDecimals = Helpers.getDecimals(_asset);
    // 3crv is 1e18, subtract slippage percentage and scale to asset
    // decimals
    // @audit not using user-provided _amount, but calculating a non-sensical
    // value based on the LP tokens
    uint256 minWithdrawAmount = withdrawPTokens
        .mulTruncate(uint256(1e18).sub(maxSlippage))
        .scaleBy(int8(assetDecimals - 18));

    curvePool.remove_liquidity_one_coin(
        withdrawPTokens,
        int128(poolCoinIndex),
        minWithdrawAmount
    );

    // ...
}
Enter fullscreen mode Exit fullscreen mode

Und die korrigierte Version nach dem Audit:

curvePool.remove_liquidity_one_coin(
    withdrawPTokens,
    int128(poolCoinIndex),
    _amount
);
Enter fullscreen mode Exit fullscreen mode

Auditoren sollten sicherstellen, dass die Slippage-Parameter klar definiert sind und keine versteckten Risiken für den Benutzer darstellen.

Weitere Beispiele findest du in den folgenden Verweisen:
1 - [H-15] Wrong slippage protection on Token -> Token trades,
2 - Ineffective slippage mechanism when redeeming proportionally,
3 - Slippage/Minimum amount does not work during single-side redemption,
4 - Illuminate's PT doesn't respect users' slippage specifications for underlying,
5 - Oracle slippage rate is used for checking primary and secondary ratio,
6 - WithdrawPeriphery uses incorrect value for MAX_BPS which will allow much higher slippage than intended,
7 - ,
8 - [M-05] Wrong slippage check,
9 - IchiSpell applies slippage to sqrtPrice which is wrong and leads to unpredictable slippage.

Top comments (0)