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: 104/199
Findings: 2
Award: $22.67
🌟 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#L299#L315
Detailed description of the impact of this finding. Equity.restructureCapTable() function is incorrectly implemented. In the loop of the function, while the function iterates through elements passed in the array, while trying to burn the FPS, it always attempts to burn only the tokens at 0 index.
It is a bug in the logic.
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
for (uint256 i = 0; i<addressesToWipe.length; i++){ address current = addressesToWipe[0]; _burn(current, balanceOf(current)); }
for (uint256 i = 0; i<addressesToWipe.length; i++){ address current = addressesToWipe[i]; <==========Fix _burn(current, balanceOf(current)); }
Manual review
This is a logical error and should be fixed by correcting the way the current address is read from the addressesToWipe array. Instead of a hard code 0 index, use i to retrieve the current address element.
#0 - c4-pre-sort
2023-04-20T14:25:14Z
0xA5DF marked the issue as duplicate of #941
#1 - c4-judge
2023-05-18T14:29:42Z
hansfriese marked the issue as satisfactory
#2 - c4-judge
2023-05-18T14:31:23Z
hansfriese changed the severity to 2 (Med Risk)
🌟 Selected for report: juancito
Also found by: 0xAgro, 0xNorman, 0xSmartContract, 0xStalin, 0xTheC0der, 0xWaitress, 0xhacksmithh, 0xnev, 3dgeville, 8olidity, Arz, Aymen0909, BGSecurity, BRONZEDISC, Bauchibred, Bauer, BenRai, ChainHunters, ChrisTina, CodeFoxInc, DedOhWale, DishWasher, EloiManuel, IceBear, Inspex, Jorgect, Kaysoft, LeoGold, LewisBroadhurst, Madalad, MiloTruck, MohammedRizwan, Nyx, Polaris_tow, RaymondFam, SaharDevep, SanketKogekar, Sathish9098, SolidityATL, Udsen, W0RR1O, aria, ayden, berlin-101, bin2chen, catellatech, codeslide, crc32, decade, descharre, evmboi32, eyexploit, fatherOfBlocks, georgits, giovannidisiena, joestakey, karanctf, kodyvim, ltyu, lukris02, m9800, matrix_0wl, mov, mrpathfindr, nadin, niser93, p0wd3r, parlayan_yildizlar_takimi, pavankv, pontifex, qpzm, ravikiranweb3, rbserver, santipu_, shealtielanz, slvDev, tnevler, wonjun, xmxanuel, yixxas
22.6007 USDC - $22.60
MintingHub contract's function openPosition() The below condition is checked in the overloaded function that created the position. Since the condition is based on input parameter, this check could be done much early in the flow of the program.
Idealy, create a modifier with the below require condition and attach to both openPosition functions.
require(_initialCollateral >= _minCollateral, "must start with min col");
Deleting elements from arrays does not remove the entry from the array unless expensive copy over and pop functions are implemented. instead of doing this, it would be better to mark the state of the challenge as active, expired and concluded using an enum.
Example: enum ChallengeStatus { ACTIVE, DEFEATED, SUCCESSFUL, DISQUALIFIED }
struct Challenge { address challenger; // the address from which the challenge was initiated IPosition position; // the position that was challenged uint256 size; // how much collateral the challenger provided uint256 end; // the deadline of the challenge (block.timestamp) address bidder; // the address from which the highest bid was made, if any uint256 bid; // the highest bid in ZCHF (total amount, not price per unit) ChallengeStatus status; // record status }
Logic to use challenge status in the business logic
Solidity version should be locked for all contracts. Best is to keep the solidity version same for all contracts where possible. It is better to lock the contracts to a specific version of Solidity during testing. Using ^0.8.0 will attempt to run this smart contracts in high version of solidity which are not tested at all.
pragma solidity ^0.8.0; Also, is there a reason to using pragma solidity >=0.8.0 <0.9.0 for equity contract.
Comparing zero address to make it more reader friendly Frankencoin.suggestMinter() function if (minters[_minter] != 0) revert AlreadyRegistered();
to be
if (minters[_minter] != address(0x0)) revert AlreadyRegistered();
https://github.com/code-423n4/2023-04-frankencoin/blob/main/contracts/Frankencoin.sol#L86
#0 - 0xA5DF
2023-04-26T16:23:14Z
3 is in automated findings
#1 - hansfriese
2023-05-17T04:43:29Z
The rest is NC
#2 - c4-judge
2023-05-17T04:43:41Z
hansfriese marked the issue as grade-c
#3 - c4-judge
2023-05-17T06:15:07Z
hansfriese marked the issue as grade-b