#9: MEV Bot 0xd61492: From Predator to Prey in an Ingenious Exploit

On August 3, 2023, an MEV Bot on Arbitrum was attacked, resulting in $800K in loss. The root cause of this attack was **Insufficient User Input Verification**.

#9: MEV Bot 0xd61492: From Predator to Prey in an Ingenious Exploit

On August 3, 2023, an MEV Bot on Arbitrum was attacked, resulting in $800K in loss. The root cause of this attack was Insufficient User Input Verification.

Considering the intricate interactions between MEV Bots and their contracts unverified, it reveals that not being open-source does not guarantee security, especially for DeFi protocols.

Background

MEV Bot

MEV Bot (Maximum Extractable Value Bot) is designed to identify and execute profitable opportunities on the blockchain. It operates by analyzing pending transactions (i.e., those in the mempool) or on-chain states to generate profits through arbitrage.

Unlike typical front-running and sandwich attack MEV Bots, the MEV Bot targeted in this attack focused on executing strategies such as triangular arbitrage and debt liquidation. These bots themselves help to stabilize prices for AMMs and assist lending protocols with liquidation to ensure smooth operation, constituting an essential part of the healthy functioning of the DeFi ecosystem.

Flashloan

Flashloan represents a unique innovation within the DeFi ecosystem – a form of uncollateralized lending. You can borrow up to a billion dollars through Flashloan without any collateral, provided that the loan is repaid within the same transaction. If the loan is not repaid within that transaction, it will be reversed, as if the transaction never happened.

This mechanism is commonly used for arbitrage or leveraging other DeFi strategies to exploit temporary market inefficiencies.

The Vulnerability

In Short Version

The insufficient validation of user-input parameters enabled the attacker to introduce a FakeFlashloanProvider. The vault contract utilized this provider to initiate a flashloan. Subsequently, perhaps to settle the flashloan, the vault contract approved tokens to the FakeFlashloanProvider, leading to the unauthorized transfer of assets out of the vault.

In Detail Version

The exploited contract is:

  • Vault: The victim contract 0xd614927acfb9744441180c2525faf4cedb70207f serves as a "Vault", providing reserves and facilitating flashloan from other protocols like AAVE and Balancer.
  • Arbitrage Bot: The vulnerable contract 0x8db0efee6a7622cd9f46a2cf1aedc8505341a1a7, functioning as an "Arbitrage Bot", holds the borrower role in the "Vault" contract.

The function 0x0582f20f() in the "Arbitrage Bot" is the main entry point for launching arbitrages. It first invokes the borrow() in the "Vault" to acquire the original principal, then executes arbitrage logic through a delegatecall to an external contract specified in the calldata and with no validation.

function 0x0582f20f(...) {
  ...
  v67, /* uint256 */ v68 = address(0xd614927acfb9744441180c2525faf4cedb70207f).borrow(address(v39), address(v9[0]), v29).gas(msg.gas);
  ...
  // 0x4da91757 = swap(address,address,address,uint256,uint256,uint256,address)
  MEM[MEM[64] + 32] = uint224(address(MEM[0 + v4[v69]])) | 0x4da9175700000000000000000000000000000000000000000000000000000000;
  v82 = address(v76 >> 96).delegatecall(MEM[(MEM[64]) len 228], MEM[(MEM[64]) len 0]).gas(msg.gas);
  ...
  v189 = v170.refund(0x410085df, address(v9[0]), address(v39), v68, address(v9[0]), v29, v186, 4 + MEM[64] + (varg2.length << 5) - (4 + MEM[64]) + 192).gas(msg.gas);
  ...
}

Subsequently, it invokes the 0x512b7351() in the "Vault", launching a flashloan to the attacker's FakeFlashloanProvider contract.

The function 0x512b7351() requires msg.sender to be in the allowlist, but it was successfully bypassed by the previous delegatecall, circumventing the check. This is a very critical step

function 0x512b7351(...) public nonPayable { 
    ...
    if (_borrow[msg.sender] >= 1) {
        v0 = !_refund;
    }
    require(v0, Error('BBVault: FORBIDDEN'));
    ...
    v38 = v23.length;
    v39 = v23.data;
    _refund = keccak256(v23);
    ...
    <FakeFalshloanProvider>.flashloan(...);
    ...
}

During the flashloan callback, the executeOperation() in the "Vault" first transfers the borrowed assets to the "Arbitrage Bot" MEVBot 0x8db0ef, then calls its 0x7fe3ba8b().

function executeOperation(...) {
  ...
  require(_refund == keccak256(v3.data), Error('BBVault: STATUS'));

  Token.transfer(ArbitrageBot, amountBorrowed);
  <ArbitrageBot>.call(0x7fe3ba8b...);
  
}

The "Arbitrage Bot" trusting this external call, transfers the received assets back to the FakeFlashloanProvider . However, the "Vault" fails to recognize this and still grants approval to the FakeFlashloanProvider for repaying the flashloan at the end of the executeOperation().

The Attack Process

Attack Tx: 0x864c8cfb8c54d3439613e6bd0d81a5ea2c5d0ad25c9af11afd190e5ea4dcfc1f

The attacker invokes the 0x0582f20f() of the "Arbitrage Bot", which in turn performs a delegate call to the attacker's contract.

The hack_contract_2 then call the victim's function 0x512b7351(). The 0x512b7351() requires msg.sender to be in the allowlist, but it was successfully bypassed by the previous delegatecall, circumventing the check.

The victim then calls the attacker's FakeFlashloanProvider contract, transferring all the flashloaned assets to the victim and calling the executeOperation() of the victim.

The 0x7fe3ba8b() of the Arbitrage Bot again performs a delegatecall to the attacker's contract, this time transferring all the assets back to the attacker. **At this point, the assets lent by the attacker’s Flashloan Provider have been repayed. **

The victim("Vault") approves tokens to the FakeFlashloanProvider, possibly with the intention of repay the flashloan.

The attacker exploits this approval to profit, using transferFrom to drain funds from the victim.

Security Recommendations

Non-open-source code does not guarantee security

Believing that non-open-source and obfuscated code ensures security is a misconception. This MEV Bot incident reveals that secrecy doesn't safeguard against exploits and may give developers a false sense of security.

Rigorous Input Validation

It's crucial to meticulously validate all contract interactions and calldata, especially when dealing with standard interfaces like flashloan and swap callbacks. Ensuring data integrity and security should be a priority in contract design and implementation.

Read other articles in this series:

Sign up for the latest updates