AES攻击事件分析

  • Drac
  • 更新于 2022-12-14 02:49
  • 阅读 3359

AES价格被操纵攻击事件分析

hackerdao攻击事件相似

skim函数

// force balances to match reserves
    function skim(address to) external lock {
        address _token0 = token0; // gas savings
        address _token1 = token1; // gas savings
        _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
        _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
    }

该函数的作用是提取lp合约地址中多余的代币转到指定的地址

sync函数

function sync() external lock {
        _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
    }
// update reserves and, on the first call per block, price accumulators
    function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
        require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'Pancake: OVERFLOW');
        uint32 blockTimestamp = uint32(block.timestamp % 2**32);
        uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
        if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
            // * never overflows, and + overflow is desired
            price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
            price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
        }
        reserve0 = uint112(balance0);
        reserve1 = uint112(balance1);
        blockTimestampLast = blockTimestamp;
        emit Sync(reserve0, reserve1);
    }

该函数的作用是更新reserve为balance的值。

攻击者地址:0x286e09932b8d096cba3423d12965042736b8f850

恶意合约地址:0x3cdfbee6ec194e5258d2f9557e2e41015fc8b6e8

攻击tx:0xca4d0d24aa448329b7d4eb81be653224a59e7b081fc7a1c9aad59c5a38d0ae19

通过blocksec的phalcon工具来分析攻击的tx: https://phalcon.blocksec.com/tx/bsc/0xca4d0d24aa448329b7d4eb81be653224a59e7b081fc7a1c9aad59c5a38d0ae19

攻击者通过部署恶意合约通过如下步骤完成套利攻击:

1.从dodo通过闪电贷借出836944 USDT

image.png

2.将其中的100000 USDT换成了AES,按照价格可以兑换2421667 AES,但是其中有72650发送到了address(0),最终获得2179500 AES。

image.png

我们查看一下transfer方法

image.png

一共有四种情况:

(1)如果from是代币合约地址,to是uniswapV2Pair(经过查询是AES-USDT),那么调用super._transfer函数转帐。super.方法名 是调用最近的父合约的方法。查看父合约的_transfer方法后,发现就是一个普通的转帐,没有任何其他费用。

image.png

(2)如果发起转帐的地址在automatedMarketMakerPairs数组中,那么调用buyTokenAndFees函数:

转帐数量的3%为burnAmount 从from地址的余额中扣除,这部分通过父函数的_burn方法发送到address(0)销毁。

转帐数量的1%添加到swapFeeTotal这个状态变量中。

转帐数量的10%为feeAmount 从转帐数量中扣除。

最终接收方收到的数量为转帐数量的90%,发送方的AES余额减少转帐数量的3%。

image.png

(3)如果接收转帐的地址在automatedMarketMakerPairs数组中,那么调用sellTokenAndFees函数:

转帐数量的3%从转帐数量中扣除。

转帐数量的1%添加到swapFeeTotal这个状态变量中。

转帐数量的3%为burnAmount 从from地址的余额中扣除,这部分通过父函数的_burn方法发送到address(0)销毁。

最终接收方收到转帐数量的97%

image.png

(4)除上面3种情况外的其他情况,都直接调用父函数的_transfer方法,不需要额外的手续费等。

100000 USDT换成了AES这个过程中,AES的from地址为AES-USDT的地址(0x40ed17221b3b2d8455f4f1a05cac6b77c5f707e3),该地址在automatedMarketMakerPairs数组中,因此转帐过程是上述第(2)种情况

image.png

3.攻击者将兑换得到的其中1089750个AES发送到AES-USDT地址,触发transferr中的第三种情况,AES-USDT地址收到1057057个AES。

image.png

4.攻击者调用skim方法,to地址设为AES-USDT地址,因为from地址为AES-USDT地址,在automatedMarketMakerPairs数组中,因此触发transfer方法中的第(2)种情况,在这种情况下AES-USDT地址的AES代币会被销毁转帐数量的3%。

image.png

5.攻击者又多次调用了skim方法,to地址设置为AES-USDT地址,导致AES-USDT地址的AES代币数量逐渐减少。

image.png

6.攻击者调用distributeFee方法,将AES-USDT地址的swapFeeTotal转出pair合约,该方法直接调用的父合约的_transfer方法,因此不存在额外的手续费。

image.png

image.png

7.攻击者调用sync方法来更新reserve的值,AES-USDT地址的AES只剩20246个了,因此每个AES代币的价格都提高了很多。

image.png

8.攻击者将139794个AES兑换为161608 USDT,购买AES花费100000 USDT,卖出AES获得161608 USDT,获利61608 USDT。

image.png

9.将闪电贷借来的USDT归还,攻击结束。

image.png

点赞 1
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Drac
Drac
江湖只有他的大名,没有他的介绍。