Full Report
KaoyaSwap is a BSC Chain that is an AMM via exchange pools. A Fee-On-Transfer token is slightly different than the standard ERC20. Typically, they implement the ERC20 interface with the main difference being the receiver gets a smaller amount to pay for the costs of the transfer. Normally, the fees are on the cost of the sender. The function swapExactTokensForETHSupportingFeeOnTransferTokens takes in a path. This path is used to determine the swaps that are taking place by the protocol. For instance, A->B->C would take in token A, swap this to B then swap that to C for the user. Finally, the receiver would pay the fees for the transfer. When determining how much to send to a user, it does this by calculating the difference in the balance before the function call _swapSupportingFeeOnTransferTokens() and after the function call. Although this is benign most of the time, there is a subtle bug here. The path variable will perform as many swaps as we want. Additionally, there is no validation that there are duplicate tokens in here. This means that the difference calculation from above may include a transfer used earlier in the path! For instance, Token A->wBNB->B->wBNB would double count the difference n wBNB because the transferring was performed twice. By performing all of these operations, the attacker was able to profit 271wBNB and 37K BUSD for a total of $118K advantage. To make this attack worse, they used a flash loan for the larger numbers. This twitter thread has a root cause as well.
Analysis Summary
# Vulnerability: Logic Error in Fee-On-Transfer Swap Calculation Allowing Re-counting of Balances
## CVE Details
- CVE ID: N/A (Internal Protocol Logic Flaw)
- CVSS Score: N/A (Specific to the protocol, treat as High severity given financial loss)
- CWE: CWE-825 (Improper Neutralization of Data within a Loop) or CWE-682 (Incorrect Calculation)
## Affected Systems
- Products: KaoyaSwap (AMM/Decentralized Exchange Protocol)
- Versions: Contract versions containing the vulnerable `swapExactTokensForETHSupportingFeeOnTransferTokens` function logic. (Specific contract addresses/versions not listed, but the exploit occurred August 24, 2022).
- Configurations: Any configuration utilizing the `swapExactTokensForETHSupportingFeeOnTransferTokens` function with a `path` that contains duplicate tokens, relying on balance difference calculation for output determination.
## Vulnerability Description
The vulnerability resides in the `swapExactTokensForETHSupportingFeeOnTransferTokens` function, which is designed to handle swaps involving Fee-On-Transfer tokens. The function determines the amount to output to the user by calculating the difference between the contract's balance *before* and *after* executing the internal swap logic (`_swapSupportingFeeOnTransferTokens`).
The flaw is that the input `path` variable is not validated for duplicate tokens, and the calculation method poorly handles fee-on-transfer tokens within complex paths. If a token (like wBNB) appears more than once in the swap path (e.g., `Token A -> wBNB -> Token B -> wBNB`), the resulting balance difference calculation incorrectly attributes the fee/transfer effects of the intermediate transfers multiple times to the final output calculation. This allowed the attacker to artificially inflate the calculated `amountOut` sent back to them.
## Exploitation
- Status: **Exploited in the wild** (Attack confirmed on August 24, 2022)
- Complexity: **Medium** (Required designing custom tokens and a specific multi-swap path utilizing a flash loan for capital efficiency.)
- Attack Vector: **Network** (Interaction with the deployed smart contract)
## Impact
- Confidentiality: **None** (Not a confidentiality breach)
- Integrity: **High** (Direct financial loss by extracting unearned tokens from the protocol.)
- Availability: **Low** (Liquidity was likely temporarily affected, but the core contract logic was the primary target.)
## Remediation
### Patches
- **No specific patch version was provided in the source material.**
- **General Mitigation:** Correct the logic governing output calculation in functions supporting fee-on-transfer tokens. Output calculation should track the net change in the *final* token of the specific transfer sequence, or iterate through the path ensuring internal state updates correctly reflect the executed transfers, rather than relying solely on a post-operation balance delta that is prone to double-counting errors when tokens are reused in the path. Additionally, enforcing validation to prevent duplicate token entries in the swap path would prevent the vector.
### Workarounds
- Temporarily disable or restrict the usage of the `swapExactTokensForETHSupportingFeeOnTransferTokens` function until the logic bug is fixed.
- Ensure paths provided by users do not contain duplicate tokens, if such validation is possible client-side or through front-end limitations (though backend contract validation is required for robustness).
## Detection
- **Indicators of Compromise:** Transactions involving the `swapExactTokensForETHSupportingFeeOnTransferTokens` function where the calculated output deviates significantly from expected ratios, especially when involving tokens that appear multiple times in the swap path structure, or large outflows immediately following a flash loan inflow.
- **Detection Methods and Tools:** On-chain monitoring focused on abnormal divergence between expected output amounts derived from AMM pricing models versus the actual amount transferred out to interacting addresses immediately after a multi-hop swap involving fee-on-transfer tokens.
## References
- Exploit Transaction Hash: bscscan com/tx/0xc8db3b620656408a5004844703aa92d895eb3527da057153f0b09f0b58208d74
- Vulnerable Code Location (Router Contract): github com/kaoya1125/contracts/blob/3ea83a229fe8e042ce4bd3d608422679a780e74d/router.sol#L831-L833
- Analysis Source: medium com/quillaudits/kaoyaswap-logic-exploit-analysis-by-quillaudits-team-7c6c1575926a