OKC Project Hack Analysis

lunaray
5 min readDec 15, 2023

Incident Background

On November 13, 2023, at 18:51:57 (UTC), an attack targeting the OKC Token occurred on the blockchain. The hacker exploited a vulnerability in the MinerPool, gaining immediate profits.

Hacker’s attack transaction: 0xd85c603f71bb84437bc69b21d785f982f7630355573566fa365dbee4cd236f08

Hacker’s attack contracts:

  1. 0xD5d8c2fd8A743A89BC497B2F180C52d719a007B9
  2. 0x617432Fc98c1fFaAB62B8cB94Cef6D75ABD95598
  3. 0x28e7c8337373C81bAF0A4FE88ee6E33d3C23E974

Attacker’s address: 0xbbcc139933D1580e7c40442E09263e90E6F1D66D

Vulnerable contract: 0x36016C4F0E0177861E6377f73C380c70138E13EE (MinerPool)

Attack Analysis

By analyzing on-chain transaction data, we have organized and summarized the attacker’s transactions.

The hacker initially used multiple flash loans to gather funds for the attack, borrowing a total of 2,753,399 USDT tokens.

Subsequently, the hacker immediately exchanged 130,000 USDT tokens for a minimal unit of USDT and 27,264 OKC tokens.

PancakeSwapv2 utilizes an Automated Market Maker (AMM) model where the product of the quantities of the two tokens in the liquidity pool remains constant. It can be represented by the formula:

xy = k

Where:

  • x is the quantity of the first token in the pool.
  • y is the quantity of the second token in the pool.
  • k is a constant representing the product of the quantities of the two tokens in the pool.

When a trader wants to exchange one token for another, they increase the quantity of one token dx while decreasing the quantity of the other token (dy) to maintain the invariance of k. This process alters the relative price of the tokens.

(x+dx)⋅(ydy)=k

In significant transactions, dx and dy can be substantial, causing significant price changes. This is because a large dy must be removed from the pool to compensate for the increase in dx to keep k constant. Such large transactions have a profound impact on token quantities in the pool, resulting in significant price fluctuations.

Therefore, the attacker, by using a substantial flash loan, bought OKC, reducing the quantity of OKC and consequently raising the price of OKC from 1 OKC = 0.3 USDT to 1 OKC = 68.9 USDT.

The attacker then created two contract addresses and sent 0.01 OKC and 0.0001 USDT, and a minimal unit of OKC to each address.

Next, the hacker used the main attack contract to add liquidity to the PancakePair_USDT_OKC pool, obtaining approximately 225,705 LP tokens.

Subsequently, all LP tokens were transferred to the attack contract created at address 0x28e7c8337373C81bAF0A4FE88ee6E33d3C23E974, and the hacker immediately called the processLPReward function in the vulnerability contract, distributing rewards based on the lpHolder address stored in the contract. Although the attacker’s action was a transfer to the MinerPool contract, this contract invoked the processLPReward function in its transfer callback function.

According to the following graph, we learn that the attack contract 0x28e7c8337373C81bAF0A4FE88ee6E33d3C23E974 received 77,890 OKC tokens as a reward.

The attacker then withdrew the LP tokens from the attack contract 0x28e7..E974 and removed liquidity, gaining 1,884,223 USDT tokens and 27,264 OKC tokens.

All tokens from the other two attack contracts were transferred to the main attack contract 0xD5d8c2fd8A743A89BC497B2F180C52d719a007B9, comprising 272 and 77,890 OKC tokens, respectively.

The hacker exchanged all OKC tokens, approximately 104,610 OKC tokens, for around 136,518 USDT tokens. At this point, the hacker held approximately 2,759,918 USDT tokens.

Finally, the hacker repaid all the principal and interest from the flash loans, resulting in a remaining balance of approximately 6,268 USDT tokens, which were then transferred to the attacker's address at 0xbbcc139933D1580e7c40442E09263e90E6F1D66D.

Vulnerability Analysis

From the attack analysis, it is evident that the primary source of the hacker’s profit was the processLPReward function in the MinerPool contract. This function’s logic revolves around retrieving lpHolder and directly rewarding based on its LP quantity.

Let’s examine the execution logic in the third attack contract created by the attacker:

From this logic, it is clear that the addHolder function uses extcodesize() to calculate the current size of the address, determining if it is a contract address. However, when the attacker creates a contract using CREATE2, the address size remains 0 during initialization, allowing the attacker to bypass the contract call restriction in the constructor.

During the transfer, the addHolder function is called to add the contract address to the lpHolder list, enabling the contract to receive rewards by claiming them. This contract can receive rewards even though the MinerPool contract only receives transfers, thanks to the callback function invoking processLPReward.

Based on the analysis of the code logic in the processLPReward function, it is evident (as shown in the following graph) that although a lock-up period for reward withdrawal is set, no verification or restriction is placed on the LP holding time. This allows the hacker to obtain

Summary

In essence, the hacker leveraged substantial flash loans to borrow a significant amount of USDT and exchanged it for a large quantity of OKC tokens, causing a surge in the price of OKC. Additionally, due to the absence of lock-up requirements for LP reward distribution in the OKC project, the hacker promptly withdrew liquidity after receiving rewards, thereby claiming the incentives intended for liquidity providers from the project. The hacker proceeded to sell the OKC tokens obtained as rewards from the OKC project. Ultimately, the profit amounted to 6,268 USDT.

--

--

lunaray

Lunaray takes a leading position in smart contract auditing and consulting service for blockchain security.