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: 119/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/main/1155tech-contracts/src/Market.sol#L150 https://github.com/code-423n4/2023-11-canto/blob/main/1155tech-contracts/src/Market.sol#L174 https://github.com/code-423n4/2023-11-canto/blob/main/1155tech-contracts/src/Market.sol#L132 https://github.com/code-423n4/2023-11-canto/blob/main/1155tech-contracts/src/Market.sol#L141 https://github.com/code-423n4/2023-11-canto/blob/main/1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol#L14
Malicious actors can exploit the buy()
and sell()
functions to instantly profit from front-running or executing a sandwich attack.
The buy()
function allows users to acquire shares by providing asD tokens. The share price increases linearly based on the provided Bonding Curve. As shareData[_id].tokenCount
grows, so does the share price, calculated within getBuyPrice()
.
function getBuyPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) { address bondingCurve = shareData[_id].bondingCurve; (price, fee) = IBondingCurve(bondingCurve).getPriceAndFee(shareData[_id].tokenCount + 1, _amount); }
This function utilizes getPriceAndFee()
to determine each additional share's price increase.
for (uint256 i = shareCount; i < shareCount + amount; i++) { uint256 tokenPrice = priceIncrease * i; price += tokenPrice; fee += (getFee(i) * tokenPrice) / 1e18; }
sell()
follows similar reverse logic, where the larger shareData[_id].tokenCount
, each share can be sold for more. Price decreases as shareData[_id].tokenCount
decreases.
Based on current implementation with linear curve, its safe to assume there will be many MEV bots monitoring the mempool to take advantage of every call made by users.
Attackers can immediately profit from following attacks:
Sandwich Attack: Attackers front-run a user's buy()
by buying at a lower price and back-run the same function by calling sell()
, securing instant profit.
buy()
for 1 share.sell()
for 1 share at price = 2.Front-running: Users intending to sell their shares for profit are vulnerable to attackers who preemptively sell their own shares at a higher price. Attacker can also use this attack to re-adjust their position for a lower price.
sell()
seeing a profitable opportunity.sell()
at a price = 2.Manual Review
Consider introducing max price parameter in both buy()
and sell()
MEV
#0 - c4-pre-sort
2023-11-18T10:07:59Z
minhquanym marked the issue as duplicate of #12
#1 - c4-judge
2023-11-28T23:32:19Z
MarioPoneder marked the issue as satisfactory