Our team at SlowMist discovered that HT tokens were routinely withdrawn without swapping within the XSquid and HT token pools on Mdex. After investigation, it is concluded that this incident was caused by the XSquids project token contract issue and has nothing to do with the security of the MDEX platform. We investigated this incident and presented the following brief analysis.
Using the XSquid token to map the deflationary token model is a critical component of this attack. Deflation usually occurs after transfer. The attacker can withdraw from the pool because the balanceOf function received by the contract does not match the reserve balance obtained through the Mdex Xsquid/HT pool.
We can see via the on-chain analysis that the Mdex pair pool transferred 0.003 WHT tokens to the attacker, and there are numerous transactions like this one.
Let’s delve a little more into the specifics of this transaction. We are looking at the Xsquid and HT pools within the Mdex contract. Before the swap to Xsquid, the contract balance in the pool_reserve0 with the getReserves function is 1010.505640800917497232. However, using the balanceOf function of the XSquid contract returns 1010.5060773394782, indicating a significant imbalance.
We can use the balanc0f function to discover the vulnerability because no new funds were contributed to the contract after the most recent update. We begin by tracing all branches associated with line 715 of the Xsquid contract.
We can see that the balance0f function obtained its value from the tokenFromReflection function, which derives from the rAmount.div(currentRate). The currentRate variable is returned by the _getRate function, generated from the _getCurrentSupply function.
Following the contract step by step, we discovered that the total tokens using the _tTotal function do not change; the change to the _getCurrentSupply function is due to the value changing in the _Total function. Looking at the contract, we can see that XSquid is following the deflationary token method. Every time _rTotal is calculated, _reflectFee will deflate and reduce the value of _rTotal, causing the currentRate to decrease. While the rAmount.div(currentRate) increases, this causes the obtained balance0f to be greater than the value obtained by the getReserves function.
This creates an illusion to the contract, believing that more XSquid was deposited into the pool. The attacker only needs to execute the swap function from the Mdex pair contract to receive the excess funds based on the difference calculated in the process or to execute the skim function to withdraw the tokens directly. The contract should sync at the end of each transfer to update the reserve to match the balance to prevent these exploits.
The fundamental problem with this attack is that the deflation token method and the smart contract are not compatible. The security problems caused by this are already old problems that have recurred in multiple Swap projects. The SlowMist security team reminds everyone that DeFi project is becoming more complex and requires multiple contracts. Projects should take precautions when implementing deflationary projects and always ensure no exploits when interacting with other smart contracts.