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: 9/199
Findings: 5
Award: $1,036.45
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: giovannidisiena
946.1175 USDC - $946.12
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Position.sol#L249-L255
If the collateral is a multi-address ERC20 token, the withdraw
function can be used to bypass the checkCollateral
check.
Manual audit
There is no business dealing with other ERC20 tokens in the Position.sol
contract. It is recommended that there is no need to provide token withdraw at a specified address.
#0 - c4-pre-sort
2023-04-22T11:52:32Z
0xA5DF marked the issue as primary issue
#1 - c4-pre-sort
2023-04-22T15:35:58Z
0xA5DF marked the issue as duplicate of #886
#2 - c4-judge
2023-05-18T09:42:18Z
hansfriese changed the severity to 3 (High Risk)
#3 - c4-judge
2023-05-18T09:43:04Z
hansfriese marked the issue as satisfactory
🌟 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#L309-L316
In the loop body, addressesToWipe[0]
is processed every time, which causes the first address to be processed in each value of RestructureCapTable
, which does not conform to the original intention of the RestructureCapTable
function.
Manual audit
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]; + address current = addressesToWipe[i]; _burn(current, balanceOf(current)); } }
#0 - c4-pre-sort
2023-04-20T14:24:23Z
0xA5DF marked the issue as duplicate of #941
#1 - c4-judge
2023-05-18T14:28:47Z
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#L208-L214
File: MintingHub.sol 208 if (challenge.position.tryAvertChallenge(challenge.size, _bidAmountZCHF)) { 209 // bid was high enough, let bidder buy collateral from challenger 210 zchf.transferFrom(msg.sender, challenge.challenger, _bidAmountZCHF); 211 challenge.position.collateral().transfer(msg.sender, challenge.size); 212 emit ChallengeAverted(address(challenge.position), _challengeNumber); 213 delete challenges[_challengeNumber]; 214 } else {
During the challenge, if the bid is high enough to satisfy tryAvertChallenge
, the challenge can be ended immediately, and the bidder and challenger exchange tokens.
File: Position.sol 304 function tryAvertChallenge(uint256 _collateralAmount, uint256 _bidAmountZCHF) external onlyHub returns (bool) { 305 if (block.timestamp >= expiration){ 306 return false; // position expired, let every challenge succeed 307 } else if (_bidAmountZCHF * ONE_DEC18 >= price * _collateralAmount){ 308 // challenge averted, bid is high enough 309 challengedAmount -= _collateralAmount; 310 // Don't allow minter to close the position immediately so challenge can be repeated before 311 // the owner has a chance to mint more on an undercollateralized position 312 restrictMinting(1 days); 313 return true; 314 } else { 315 return false; 316 } 317 }
After satisfying tryAvertChallenge
, position will enter a 1-day cooldown period.
The attacker can act as a challenger and bidder to make the position enter a 1-day cooldown at 0 cost.
Manual audit
It is recommended to charge a certain fee for challengers who fail the challenge.
#0 - c4-pre-sort
2023-04-22T11:55:09Z
0xA5DF marked the issue as primary issue
#1 - c4-pre-sort
2023-04-24T16:27:00Z
0xA5DF marked the issue as duplicate of #745
#2 - c4-judge
2023-05-18T13:53:33Z
hansfriese marked the issue as satisfactory
33.835 USDC - $33.83
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Frankencoin.sol#L1
The power of minter in Frankencoin is very large, and minter may be a third-party component. If minter gets out of control, it may cause Frankencoin to crash. But the current situation is that as long as minter is added, even if it loses control later, Frankencoin shareholders cannot delete or restrict it.
Manual audit
It is recommended that shareholders vote (requires a large number of votes) to delete minter.
#0 - c4-pre-sort
2023-04-28T08:11:55Z
0xA5DF marked the issue as duplicate of #230
#1 - c4-judge
2023-05-18T13:41:43Z
hansfriese changed the severity to 2 (Med Risk)
#2 - c4-judge
2023-05-18T13:44:55Z
hansfriese marked the issue as satisfactory