Transparent pool ordering allows for preferential swaps
Description
The way swaps are performed in the pool allows for anyone to anticipate whose liquidity will be used for the next swap. This transparent queue allows for front-running and other types of attacks that could be used to manipulate the pool's liquidity to an attacker's advantage, should the market conditions be favorable for such an attack.
for (uint i = indexEnd; i > indexStar; i--) {
Issue storage issueInfo = issues[i];
if (issueInfo.isStaking) {
if (amountB > 0) {
// ...
}
Note that the swap
function starts iterating through the issues
array from the last index to the first, which means that the last user to stake
will be the first to have their liquidity used for the next swap.
Impact
Anyone can anticipate whose liquidity will be used for the next swap, which potentially allows for front-running or even denying the service to other users by staking a large amount of tokens and then withdrawing them, effectively clogging the pool's liquidity and rendering the entire pool unusable. As the stakes are essentially a "last in, first out" (LIFO) stack, the newest stake will be always be considered first for a swap. Someone who wants to hamper swapping could potentially front-run an incoming swap, making sure that their own stake is considered first for the swap. The same situation could arise whenever market conditions are right, exacerbated by the fact that the rate is static.
Recommendations
We recommend redesigning the swap
function to use a more dynamic approach in determining which issues
should be considered for the swap and to prevent any potential front-running attacks. This could be achieved by using a more efficient aggregation algorithm, rather than a simple last-in, first-out approach.
Remediation
This issue has been acknowledged by Chateau Capital, and a fix was implemented in commit 849a8a63↗.
Chateau Capital removed the swap
function and states that user will instead use Uniswap or similar exchanges.