Understanding the TIME Token Exploit

4 min read

Learn how the TIME token was exploited, resulting in a loss of 94 ETH worth $200,000.

TL;DR#

On December 6, 2023, the TIME token was exploited due to a smart contract vulnerability, which resulted in a loss of 94 ETH, worth approximately $200,000.

Vulnerability Assessment#

The root cause of the exploit is a price manipulation attack caused by a public burn issue.

Steps#

Step 1:

We attempt to analyze one of the attack transactions executed by the exploiter.

Step 2:

The vulnerability was rooted in the vulnerable Forwarder contract, which is designed to execute transactions from arbitrary sender addresses.

Step 3:

Essentially, the exploit was successful due to the discrepancy between two functions: the execute method from the Forwarder contract and the multicall method from the TokenERC20 contract.

function execute(ForwardRequest calldata req, bytes calldata signature) public payable returns (bool, bytes memory) {
  require(verify(req, signature), "MinimalForwarder: signature does not match request");
  _nonces[req.from] = req.nonce + 1;

  // solhint-disable-next-line avoid-low-level-calls
  (bool success, bytes memory result) = req.to.call{gas: req.gas, value: req.value}(abi.encodePacked(req.data, req.from));

  if (!success) {
    // Next 5 lines from https://ethereum.stackexchange.com/a/83577
    if (result.length < 68) revert("Transaction reverted silently");
    assembly {
      result := add(result, 0x04)
    }
    revert(abi.decode(result, (string)));
  }
  // Check gas: https://ronan.eth.link/blog/ethereum-gas-dangers/
  assert(gasleft() > req.gas / 63);
  return (success, result);
}

Step 4:

The Forwarder contract appends a `req.from` address parameter at the end of `req.data` call. However, when the multicall function is called, it processes the parameters but excludes `req.from` before executing the actual call.

/**
 * @dev Receives and executes a batch of function calls on this contract.
 */
function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
  results = new bytes[](data.length);
  for (uint256 i = 0; i < data.length; i++) {
    results[i] = _functionDelegateCall(address(this), data[i]);
  }
  return results;
}

Step 5:

When the burn function is invoked, it attempts to extract `req.from` from the calldata, assuming it is provided by a TrustedForwarder.

function burn(uint256 amount) public virtual {
  _burn(_msgSender(), amount);
}

function _burn(address account, uint256 amount) internal virtual {
  require(account != address(0), "ERC20: burn from the zero address");

  _beforeTokenTransfer(account, address(0), amount);

  uint256 accountBalance = _balances[account];
  require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
  unchecked {
    _balances[account] = accountBalance - amount;
  }
  _totalSupply -= amount;

  emit Transfer(account, address(0), amount);

  _afterTokenTransfer(account, address(0), amount);
}

Step 6:

As the `req.from` parameter is excluded, the function erroneously uses the last 20 bits of `req.data`, which can be easily manipulated by the attacker.

Step 7:

The attacker was thus able to drain funds from the DEX by burning most of the TIME tokens to inflate the token price and thus take away their share of rewards.

undefined

Step 8:

The TokenERC20 contract is deployed by Thirdweb, as viewed in this transaction. On December 5th, 2023, the team issued a community alert regarding the security vulnerability in one of the most commonly used web-based open-source libraries, following the issue disclosure within the team on November 20, 2023. The team has outlined the mitigation steps for the vulnerable contract in this blog.

Solution#

To address smart contract vulnerabilities in scenarios like the TIME Token exploit, it's important to review and update the contract's code, particularly focusing on areas where data is handled and processed. Ensuring that functions interact correctly and data is verified and processed securely is key. Additionally, implementing comprehensive testing and regular audits can help identify potential weaknesses. It's also crucial to establish ongoing monitoring and response mechanisms to detect and address anomalies quickly. Finally, fostering a culture of security awareness and best practices among developers and users is essential for long-term resilience.

Users who deployed impacted pre-built smart contracts before November 22, 2023, at 7 PM PST need to take specific mitigation steps to address the smart contract vulnerability identified by Thirdweb. These steps generally involve locking the contract, taking a snapshot, and migrating to a new contract without the vulnerability. The exact steps vary based on the nature of the contract. Thirdweb has developed a mitigation tool to guide users through this process. It's crucial for smart contract owners to act promptly to prevent exploitation of the vulnerability.

However, despite the best security measures, vulnerabilities can still be exploited. This is where Neptune Mutual comes into play. In the event of security incidents like the Stake exploit, having a dedicated cover pool with Neptune Mutual could have significantly reduced the aftermath. Neptune Mutual offers coverage to users who suffer losses due to smart contract vulnerabilities through its parametric policies.

Users who purchase our parametric cover policies do not need to provide evidence of their loss to receive payouts. Once an incident is confirmed and resolved through our incident resolution system, payouts can be claimed immediately.

Furthermore, our services, which extend across various blockchain networks like EthereumArbitrum, and the BNB chain, are dedicated to catering to a wide range of DeFi users. In times of uncertainty, having the backing of Neptune Mutual can provide peace of mind to DeFi participants, knowing that their investments are safeguarded.

Reference Source BlockSec

By

Tags