Summary
We notice a hack incidence on BSC mainnet in transaction https://bscscan.com/tx/0x477f9ee698ac8ae800ffa012ab52fd8de39b58996245c5e39a4233c1ae5f1baa
Attacker depolyed attack smart contract (https://bscscan.com/address/0x20dcf125f0563417d257b98a116c3fea4f0b2db2) and take out a flash loan in DODO X. Callback function DPPFlashLoanCall in attacker’s smart contract using 300,000 BSC-USD swap 2,320.81 EAC in Pancakeswap, then attacker call EAC project’s own contract (https://bscscan.com/address/0xa08a40e0f11090dcb09967973df82040bff63561) swap 14,300 BSC-USD to 35.15 EAC(the price BEP20-EAC significant increase after that). Then attacker swapped 2,320.81 EAC to 306,376.85 BSC-USD and pay back for loan in last step. Attacker get 6,376.85 BSC-USD finally.
Technical Detail
We checked BEP20-EAC smart contract first.
function _transfer(
address from,
address to,
uint256 amount
) internal override {
require(!_isExcludedFromVip[from], "ERC20: transfer from the zero address");
require(amount > 0);
if(_isExcludedFromVipFees[from] || _isExcludedFromVipFees[to]) {
super._transfer(from, to, amount);
return;
}
// min hold = 10 ** 16
amount = balanceOf(from) - amount > 100 ? amount:amount - MIN_HOLD;
uint _amount = amount;
if (_isPair[from]) { // buyer will pay 3%
uint fund = (amount * 3)/100;
_amount -= fund;
super._transfer(from, fundReward, fund);
EACFund(fundReward).PlanA();
}
if (_isPair[to]) { // seller will pay 2% and burn 1%
uint fund = (amount * 2)/100;
uint burn = amount/100;
_amount -= fund;
super._transfer(from, fundReward, fund);
if (totalSupply()-balanceOf(BURN_ADDRESS) > MIN_SUPPLY) {
_amount -= burn;
super._transfer(from, BURN_ADDRESS, burn);
}
EACFund(fundReward).PlanA();
}
super._transfer(from, to, _amount);
}
We found buyer wil pay 3% fee, seller will pay 2% fee and burn 1% amount.
The first step: Attack take a flash loan and trade to EAC
Balance of the PancakeSwap V2 pair BSC-USD/EAC
+--------------------------+------------------------+
| token0(BSC-USDT) | token1(EAC) |
+--------------------------+------------------------+
| 139983368763169741310420 | 3511794965051261266932 |
+--------------------------+------------------------+
PancakeSwap V2 using Constant Product Market Maker (CPMM) Model (x * y = k) and procotol fee is 0.25% . Therefore we can use x EAC swap to y BSC-USD.
token0 * token1 = (toekn0 + x * 99.75%) * (token1 - y)
Given that x=300000000000000008388608(300,000 BSC-USD)( from flash loan), we can get y=2392588355139810114426(2,392.58 EAC). Therefore, the attacker trade 300,000 BSC-USD to 2,392.58 EAC. Consequently, the BEP20-EAC price at that moment is 125.39 BSC-USD. Due to 3% fee, the actual amount of BEP20-EAC received by the attacker is 2320810704485615810994 (2320.81 EAC).
The second step: Attacker exploited a vulnerability in the EAC project’s contract to inflate the price.
Balance of the PancakeSwap V2 pair BSC-USD/EAC
+--------------------------+------------------------+
| token0(BSC-USDT) | token1(EAC) |
+--------------------------+------------------------+
| 439983368763169749699028 | 1119206609911451152506 |
+--------------------------+------------------------+
PancakeSwap V2 using Constant Product Market Maker (CPMM) Model (x * y = k) and procotol fee is 0.25% . Therefore we can use x EAC swap to y BSC-USD.
token0 * token1 = (toekn0 + x * 99.75%) * (token1 - y)
Given that x=14300000000000000000000(balance of the EAC project contract), we can get y=35145242871934291346(35.15 EAC). So, the attacker trade 14,300 BSC-USD to 35.15 EAC. The BEP20-EAC price at the moment is increasing significantly to 406.83 BSC-USD.
The final step: Attacker sell all EAC they have
Balance of the PancakeSwap V2 BSC-USD/EAC pair
+---------------------------+------------------------+
| token0(BSC-USDT) | token1(EAC) |
+---------------------------+------------------------+
| 454283368763169749699028 | 1084061367039516861160 |
+---------------------------+------------------------+
PancakeSwap V2 using Constant Product Market Maker (CPMM) Model (x * y = k) and procotol fee is 0.25% . Therefore we can use x EAC swap to y BSC-USD.
token0 * token1 = (toekn0 - x) * (token1 + y * 0.9975)
Due to the minimum holding requirement is 10¹⁶ , and a 2% selling fee along with an additional 1% for burning, the amount of EAC that the attacker can sell is (2320810704485615810994 - 10¹⁶) * 0.97 = 2251176683351047336666(2251.18 EAC).
Given y=2251176683351047336666(2251.18 EAC), we can get x=306376847071465747097472(30,6376.85 BSC-USD). Therefore, the attacker traded 2,251.18 EAC for 306,376.85 BSC-USD, the EAC price at that moment is 136.10 BSC-USD. After payed back for loan, attacker got 6,376.85 BSC-USDT through price manipulation.
Fix
After attack, EAC team transparence contract upgrade new logic contract https://bscscan.com/address/0x2deb06785a9392c9f7fdc959d429bb0f5774610f and fixed this vulnerability. We can find an addtional permession check in new logic contract.
Root Cause Analysis
- Lack of liquidity: Lack of liquidity in CPMM model, the price can be easily manipulation by attacker.
- Lack of permession check: Attacker can do what they want.
Relate address
`0x64f291DE10eCd36D5f7b64aaEbC70943CFACE28E` PANCAKE SWAP PAIR BUSD-EAC / LP TOKEN
`0xa0FFe0603E1329948E4623f5E9965C6E866Fb4CA` PANCAKE SWAP PAIR stEAC-EAC
`0x55d398326f99059fF775485246999027B3197955` USDT ERC20
`0x10ED43C718714eb63d5aA57B78B54704E256024E` PANCAKE ROUTER
`0x26d0c625e5F5D6de034495fbDe1F6e9377185618` DODO POOL
`0xa08a40e0F11090Dcb09967973DF82040bFf63561` PROXY
`0x64f291DE10eCd36D5f7b64aaEbC70943CFACE28E` EAC ERC20
`0x89e75e1fcf32b8d2b6c7d3a40c5bbf8fddb93b08` stEAC ERC20
`0x20dcf125f0563417d257b98a116c3fea4f0b2db2` HACKER CONTRACT
`0x27e981348c2d1f5b2227c182a9d0ed46eed84946` ATTACKER
`0xb803ed66ab449d80ed12cacf83eae5147fdc6922` PROXY LOGIC
`0x7c8f0f09f1605237d3a5160e78b04cccec6d7971` FUNDATION PLAN A
`0x6901c75c9a0b18687bd6f5764fe7fdd1dbcc316c` PANCAKE SWAP PAIR BUSD-EAC LP TOKEN