Source: Zero Time Technology
Event background
2023-11-13 18:51:57 (UTC) An attack on OKC Token occurred on the chain. Hackers made immediate gains through the flawed MinerPool
Hacker attack transaction:
0xd85c603f71bb84437bc69b21d785f982f7630355573566fa365dbee4cd236f08
Hacker attack contract 1:
0xD5d8c2fd8A743A89BC497B2F180C52d719a007B9
Hacker attack contract 2: strong>
0x617432Fc98c1fFaAB62B8cB94Cef6D75ABD95598
Hacker attack contract 3:
0x28e7c8337373C81bAF0A4FE88ee6E33d3C23E974
Attacker address:
0xbbcc139933D1580e7c40442E09263e90E6F1D66D
Vulnerable contract:
0x36016C4F0E0177861E6377f73C380c70138E13EE (Miner Pool )
Attack Analysis
By analyzing the transaction data on the chain, we conduct Organize and summarize.
The hacker first raised funds for the attack through multiple flash loans, borrowing a total of 2,753,399 USDT Token.
130,000 USDT Token was immediately converted into a minimum unit of USDT Token and 27,264 OKC Token.
Since PancakeSwapv2 uses AMM (constant function market maker), in this model, the product of the quantities of the two tokens in the trading pool is a constant . It can be represented by the following formula:
Where:
• x is the number of the first token in the trading pool.
• y is the number of the second token in the trading pool.
• k is a constant that represents 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 amount (dx) of one token in the trading pool while decreasing the amount of the other token. quantity (dy) to maintain invariance. This process changes the relative prices of the tokens.
Suppose the trader wants to exchange token A for token B, then the constant product formula should remain true before and after the transaction:
Since k is constant, this means that x·y before and after the transaction Are the same. However, because the trader increases the quantity of Token A (dx) and decreases the quantity of Token B (dy), this will cause the price of Token B to increase.
The instant price of a token can be calculated by calculating the ratio of the number of two tokens in the pool. If token A is x and token B is y, then the price of token B relative to token A is y/x. After the transaction, the amount of token B decreases and the amount of token A increases, so the new price becomes (y-dy)/(x+dy). Since the numerator decreases and the denominator increases, the ratio becomes smaller, meaning the price of Token B increases.
In the case of large transactions, dx and dy can be very large, which can lead to significant price changes. This is because in order to keep k constant, a large amount of dy must be removed from the pool to compensate for the increase in dx. The huge impact of this large transaction on the number of tokens in the pool resulted in significant price changes.
So the attacker used a large amount of flash loan funds to buy OKC, which resulted in a reduction in the number of OKC, thus raising the price of OKC Token, raising the price of 1 OKC = 0.3 USDT to 1 OKC = 68.9 USDT.
Later the attacker created two contract addresses and sent 0.01 OKC and 0.0001 USDT and a minimum unit of OKC to the two addresses respectively.
Then the hacker uses the main The attack contract added liquidity operations to the PancakePair_USDT_OKC pool and obtained approximately 225,705 LP Tokens.
All LP Tokens are then transferred to 0x28e7c8337373C81bAF0A4FE88ee6E33d3C23E974 created by the attacker. The attack contract then immediately calls the processLPReward function in the vulnerable contract to allocate rewards to the lpHolder address stored in the contract. Although the attacker's operation here is only to transfer money to the MinerPool contract, the contract calls the processLPReward function in the callback function that accepts the transfer.
According to the picture below, we know that the attack contract 0x28e7c8337373C81bAF0A4FE88ee6E33d3C23E974 received 77,890 OKC Tokens in the reward collection.
The attacker then transferred out the LP Token of the attack contract 0x28e7..E974 and destroyed it to remove the liquidity, obtaining 1,884,223 USDT Token and 27,264 OKC Token.
And transfer all the tokens in the other two attack contracts to the main attack contract
0xD5d8c2fd8A743A89BC497B2F180C52d719a007B9, respectively: 272 and 77,890 OKC Tokens.
The hacker exchanged all OKC, about 104,610 OKC Token, for about 136,518 USDT Token. At this time, the hacker held a total of about 2,759,918 USDT Token.
Finally, the hacker returned all the principal and interest of the flash loan, leaving approximately 6,268 USDT Tokens, all of which were transferred to the attacker’s address
0xbbcc139933D1580e7c40442E09263e90E6F1D66D.
Vulnerability analysis
Through attack analysis, it is known that the hackers’ main profit funds are from the processLPReward function in the MinerPool contract. The logic of this function is mainly to obtain lpHolder and calculate the LP value based on its LP. The amount will be rewarded directly in proportion.
We can take a look at the execution logic in the third attack contract created by the attacker:
From the logic here, we can see that extcodesize( is used in the addHolder function ) to calculate the current size of the address and determine whether the address is a contract address. However, when the attacker creates the contract through CREATE2, since the contract is initialized, the address size is still 0, so the attacker calls the address in its constructor. The function bypasses the contract call restrictions.
It called the addHolder function during the transfer to add the contract address to the lpHolder list, so the contract can obtain timely OKC rewards by receiving rewards.
According to the analysis of the processLPReward function code logic, it can be seen from the figure below that although the locking time for receiving rewards is set, the LP holding time is not set Verification or restrictions are implemented, causing hackers to obtain a large amount of temporary funds through flash loans, convert them into LP, and destroy them immediately after receiving the rewards.
Summary
Simply put, the hacker borrowed a large amount of USDT through lightning loans and exchanged a large amount of OKC, thus raising the price of OKC. And because the OKC project does not set lock-up requirements for LP reward issuance, the hacker immediately withdrew the liquidity after obtaining the reward, thereby obtaining the liquidity provider reward issued by the project party. And sell the OKC Token rewarded by the OKC project party. The final profit was 6,268 USDT.