Platform: Code4rena
Start Date: 12/04/2023
Pot Size: $60,500 USDC
Total HM: 21
Participants: 199
Period: 7 days
Judge: hansfriese
Total Solo HM: 5
Id: 231
League: ETH
Rank: 61/199
Findings: 3
Award: $56.50
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: decade
Also found by: 0x3b, 0xDACA, 0xWaitress, 0xWeiss, 0xkaju, Arz, Aymen0909, BPZ, EloiManuel, HaCk0, J4de, Jerry0x, Jiamin, John, Juntao, Kek, Lalanda, MiloTruck, Mukund, PNS, RedTiger, Ruhum, Satyam_Sharma, ToonVH, Tricko, Udsen, ak1, anodaram, bin2chen, carrotsmuggler, cccz, circlelooper, deadrxsezzz, giovannidisiena, jasonxiale, joestakey, juancito, karanctf, kenta, kodyvim, ladboy233, lil_eth, lukino, markus_ether, marwen, mrpathfindr, nobody2018, parlayan_yildizlar_takimi, peakbolt, ravikiranweb3, rbserver, rvierdiiev, silviaxyz, volodya, zhuXKET, zzebra83
0.0748 USDC - $0.07
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Equity.sol#L313
Equity.restructureCapTable function removes only 1 address balance and leave other passive holders with their shares.
There is a bug inside Equity.restructureCapTable
function.
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Equity.sol#L313
function restructureCapTable(address[] calldata helpers, address[] calldata addressesToWipe) public { require(zchf.equity() < MINIMUM_EQUITY); checkQualified(msg.sender, helpers); for (uint256 i = 0; i<addressesToWipe.length; i++){ address current = addressesToWipe[0]; _burn(current, balanceOf(current)); } }
The function loops through the addressesToWipe
array, but it always takes addressesToWipe[0]
, which is first element.
Because of that it actually doesn't remove balances of another addresses and as result passive FPS holders still have shares inside the Equity contract after the function call.
VsCode
Use addressesToWipe[i] to get element.
#0 - c4-pre-sort
2023-04-20T14:22:05Z
0xA5DF marked the issue as duplicate of #941
#1 - c4-judge
2023-05-18T14:27:06Z
hansfriese marked the issue as satisfactory
🌟 Selected for report: peanuts
Also found by: GreedyGoblin, J4de, KIntern_NA, Kumpa, LegendFenGuin, T1MOH, __141345__, deadrxsezzz, deliriusz, ltyu, m9800, rvierdiiev
33.835 USDC - $33.83
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/MintingHub.sol#L140-L148 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/MintingHub.sol#L208-L214 https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L312
Attacker can block positions to make them liquidatable without cost
When challenge is started, then position is blocked and owner can't withdraw collateral, change price, mint/burn zchf tokens.
Everytime someone bids, then position.tryAvertChallenge
function is called. It tries to check if price is good.
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L304-L317
function tryAvertChallenge(uint256 _collateralAmount, uint256 _bidAmountZCHF) external onlyHub returns (bool) { if (block.timestamp >= expiration){ return false; // position expired, let every challenge succeed } else if (_bidAmountZCHF * ONE_DEC18 >= price * _collateralAmount){ // challenge averted, bid is high enough challengedAmount -= _collateralAmount; // Don't allow minter to close the position immediately so challenge can be repeated before // the owner has a chance to mint more on an undercollateralized position restrictMinting(1 days); return true; } else { return false; } }
In case if the price is sound, then restrictMinting(1 days)
is called, which leaves positon freezed for 1 more day. Then challenger collateral is sent to bidder and bidder's amount is sent to challenger. This should be a mechanism that will prevent from user to create fake challenges.
But in case if attacker will be both challenger and bidder, then he will not face any material loss. Attacker can use next steps to block position until it becomes liquidatable: 1.Create challenge with sound price. 2.Then bid to block position for 1 day. 3.Repeat till price has changed and liquidate position. 4.Position was blocked all the time, so couldn't change price and became liquidatable.
VsCode
I don't know good solution.
#0 - c4-pre-sort
2023-04-22T18:54:24Z
0xA5DF marked the issue as duplicate of #745
#1 - c4-judge
2023-05-18T09:00:50Z
hansfriese marked the issue as satisfactory
#2 - c4-judge
2023-05-18T13:47:47Z
hansfriese changed the severity to 2 (Med Risk)