#7: ParaSpace Incident: A Race Against Time to Thwart the Industry's Most Critical Attack Yet

#7: ParaSpace Incident: A Race Against Time to Thwart the Industry's Most Critical Attack Yet

On March 17, 2023, due to a vulnerability in the price oracle, Paraspace became the target of a hacker attack. After the hacker's three failed attempts, the BlockSec Phalcon system intervened timely, saving over 5 million dollars worth of ETH through a rescue operation. Details and anecdotes about the rescue can be found at this link.

Click here to read the tweet
Click here to read the tweet

Background

ParaSpace (now known as Parallel Finance) is an NFT lending platform that allows you to utilize NFTs and ERC-20 tokens as collateral. By depositing these assets into ParaSpace, users can borrow ERC-20 tokens, offering the opportunity to generate returns on NFTs without the need to sell them.

One of the interesting features of ParaSpace is ApeStaking, which enables the auto-compounding of APE rewards. Users who engage in ApeStaking on the ParaSpace platform receive cAPE—a cToken representation of APE—which they can then contribute to the lending pool. Specifically, ParaSpace allows cAPE to be used as collateral for borrowing assets like USDC and WETH. Users can deposit cAPE tokens to obtain pcAPE shares. The collateral value is calculated by multiplying the amount of pcAPE with the rebasingIndex of the pcAPE token, as folllows:

  function _scaledBalanceOf(address user, uint256 rebasingIndex)
      internal
      view
      returns (uint256)
  {
      return super.scaledBalanceOf(user).rayMul(rebasingIndex);
  }

The pcAPE token's rebasingIndex is determined by the lastRebasingIndex function, which, in turn, invokes the getPooledApeByShares() function. The latter calculates the index using the formula sharesAmount.mul(_getTotalPooledApeBalance()).div(totalShares). The function _getTotalPooledApeBalance() represents the total value of APE tokens in the pools, while totalShares refers to the total supply of cAPE tokens.

  function lastRebasingIndex() internal view override returns (uint256) {
    return ICApe(_underlyingAsset).getPooledApeByShares(WadRayMath.RAY);
  }

  function getPooledApeByShares(uint256 sharesAmount)
      public
      view
      returns (uint256)
  {
      uint256 totalShares = _getTotalShares();
      if (totalShares == 0) {
          return 0;
      } else {
          return
              sharesAmount.mul(_getTotalPooledApeBalance()).div(totalShares);
      }
  }

The _getTotalPooledApeBalance() function is designed to provide the total sum of stakeAmount, rewardAmount, and bufferBalance as sourced from the ApeCoinStaking contract. More precisely, stakeAmount refers to the number of APE tokens that have been staked in the cAPE position within the ApeCoinStaking contract.

  function _getTotalPooledApeBalance()
      internal
      view
      override
      returns (uint256)
  {
      (uint256 stakedAmount, ) = apeStaking.addressPosition(address(this));
      uint256 rewardAmount = apeStaking.pendingRewards(
          APE_COIN_POOL_ID,
          address(this),
          0
      );
      return stakedAmount + rewardAmount + bufferBalance;

Vulnerability Analysis

Unfortunately, the earlier mentioned rebasingIndex is vulnerable to manipulation, which can artificially inflate the collateral value of the cAPE token.

Specifically, within the ApeCoinStaking contract, the depositApeCoin() function is designed to increase the stakedAmount for a given position. An exploit can occur if APE tokens are deposited into the cAPE position using the depositApeCoin() function, as this action can lead to an inflated output from the _getTotalPooledApeBalance() function, resulting in a distorted rebasingIndex.

  function depositApeCoin(uint256 _amount, address _recipient) public {
      if (_amount < MIN_DEPOSIT) revert DepositMoreThanOneAPE();
      updatePool(APECOIN_POOL_ID);

      Position storage position = addressPosition[_recipient];
      _deposit(APECOIN_POOL_ID, position, _amount);

      apeCoin.transferFrom(msg.sender, address(this), _amount);

      emit Deposit(msg.sender, _amount, _recipient);
  }

  function _deposit(uint256 _poolId, Position storage _position, uint256 _amount) private {
    Pool storage pool = pools[_poolId];
    _position.stakedAmount += _amount;
    pool.stakedAmount += _amount.toUint96();
    _position.rewardsDebt += (_amount * pool.accumulatedRewardsPerShare).toInt256();
  }

Attack Analysis

With the vulnerability identified, the mechanics of the attack become relatively straightforward. The attacker inflated the collateral value by depositing APE tokens through the depositApeCoin function, setting cAPE as the recipient, and then proceeded to borrow more tokens.

Take BlockSec's blocking transaction as an example, there are five key steps:

  • Obtaining a flash loan of approximately 47,352 wstETH. Supplying about 46,018 wstETH to borrow cAPE through the creation of multiple contracts.
  • Depositing approximately 12,880,000 cAPE to the protocol as collateral.
  • Trading about 1,205 wstETH for roughly 492,124 APE and withdraw 1,839,999 cAPE to APE tokens.
  • Depositing 2,332,214 APE tokens into the cAPE position by invoking ApeCoinStaking.depositApeCoin(), which changes the protocol's APE stakedAmount from 851,662 to 3,183,876, an increase of approximately 373%.
  • Leveraging the inflated collateral to borrow substantial amounts of various assets (i,e USDC, WETH) for profit.

Summary

In the ParaSpace incident, the price of pcAPE was manipulated by the attacker using a flashloan, exploiting the use of spot prices for calculation. This incident highlights the critical need for vigilance when incorporating price oracles into DeFi protocols, underscoring the necessity of ensuring that a protocol's price oracle is resistant to manipulation.

Moreover, given the escalating prevalence of security breaches in Web3, it is crucial for protocols to establish threat monitoring and prevention systems that remain active throughout their operational phases, not merely rely on pre-launch code audits. As demonstrated by the ParaSpace incident, BlockSec's Phalcon, which is capable of automatically blocking crypto hacks, managed to intervene ahead of the attacker, successfully safeguarding user assets.

Read other articles in this series:

Sign up for the latest updates
#1 Cetus Incident: One Unchecked Shift Drains $223M in the Largest DeFi Hack of 2025

#1 Cetus Incident: One Unchecked Shift Drains $223M in the Largest DeFi Hack of 2025

Cetus Protocol, the largest concentrated-liquidity DEX on Sui, was exploited on May 22, 2025, resulting in an estimated ~$223M loss across multiple liquidity pools. The attacker leveraged a flaw in checked_shlw(), a custom overflow-prevention helper used in fixed-point u256 math, where an incorrect constant and comparison failed to block unsafe left shifts and caused silent truncation of high bits during liquidity delta calculations. By crafting specific liquidity and tick/price-range parameters, the exploit made required deposits appear near-zero while minting an oversized liquidity position, which was later withdrawn to drain real pool reserves.

#2 Bybit Incident: A Web2 Breach Enables the Largest Crypto Hack in History

#2 Bybit Incident: A Web2 Breach Enables the Largest Crypto Hack in History

The largest crypto hack ever, the February 21, 2025 Bybit breach stole about $1.5B after attackers used social engineering to compromise a Safe{Wallet} workflow, injected malicious JavaScript into an AWS S3 bucket, tampered with the transaction signing process, and upgraded Bybit’s Safe{Wallet} contract to a malicious implementation that drained funds across multiple chains.

Weekly Web3 Security Incident Roundup | Jan 25 – Feb 1, 2026

Weekly Web3 Security Incident Roundup | Jan 25 – Feb 1, 2026

During the week of January 25 to February 1, 2026, six blockchain security incidents were reported with total losses of ~$18.05M. These involved improper input validation, token design flaws, key compromises, and business logic errors across DeFi protocols on multiple chains. The primary causes included unchecked user inputs enabling arbitrary calls, flawed burn mechanisms allowing price manipulation, compromised developer tools, and missing solvency checks in lending functions.