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: 106/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
Judge has assessed an item in Issue #964 as 2 risk. The relevant finding follows:
L1
#0 - c4-judge
2023-05-23T05:33:19Z
hansfriese marked the issue as duplicate of #941
#1 - c4-judge
2023-05-23T05:51:52Z
hansfriese marked the issue as satisfactory
🌟 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
Note that this is my first submission at Code4rena and I am still figuring out how things work. I could not spend much time on this.
Letter | Name | Description |
---|---|---|
L | Low Risk | Potential risk |
NC | Non-critical | Non risky findings |
Total Found Issues | 5 |
---|
Count | Explanation |
---|---|
[L-01] | restructureCapTable() incorrect burning mechanism |
Total Low Risk Issues | 1 |
---|
Count | Explanation |
---|---|
[NC-01] | Missing or vague error messages |
[NC-02] | Constants should be defined rather than using magic numbers |
[NC-03] | Inconsistent Documentation |
[NC-04] | Unnecessary Import |
Total Non-critical Risk Issues | 4 |
---|
restructureCapTable()
incorrect burning mechanismThe function restructureCapTable()
in Equity.sol
is supposed to burn the balance of all addresses in addressesToWipe[]
. However, it would only do it for the first element as per line 313 shown below:
contracts/Equity.sol 309: function restructureCapTable(address[] calldata helpers, address[] calldata addressesToWipe) public { 310: require(zchf.equity() < MINIMUM_EQUITY); 311: checkQualified(msg.sender, helpers); 312: for (uint256 i = 0; i<addressesToWipe.length; i++){ 313: address current = addressesToWipe[0]; 314: _burn(current, balanceOf(current)); 315: }
Note that in the event using addressesToWipe
with a considerable number of elements, it would only burn the tokens of the first address though using a lot of gas.
Change address current = addressesToWipe[0];
to address current = addressesToWipe[i]
.
Some require
statements do not have an error message or are the error messages they have are not clear.
contracts/Position.sol 53: require(initPeriod >= 3 days); // must be at least three days, recommended to use higher values
contracts/Equity.sol 276: require(canRedeem(msg.sender));
contracts/StablecoinBridge.sol 51: require(block.timestamp <= horizon, "expired"); 52: require(chf.balanceOf(address(this)) <= limit, "limit");
A magic number is a numeric literal that is used in the code without any explanation of its meaning. The use of magic numbers makes programs less readable and hence more difficult to maintain and update. Even assembly can benefit from using readable constants instead of hex/numeric literals
contracts/Frankencoin.sol 118: return minterReserveE6 / 1000000; 166: uint256 usableMint = (_amount * (1000_000 - _feesPPM - _reservePPM)) / 1000_000; // rounding down is fine 205: uint256 theoreticalReserve = _reservePPM * mintedAmount / 1000000; 239: return 1000000 * amountExcludingReserve / (1000000 - adjustedReservePPM); // 41 / (1-18%) = 50
The documentation (https://docs.frankencoin.com/positions/open) says that this is the function to open a position:
openPosition( address _collateralAddress, uint256 _minCollateral, uint256 _initialCollateral, uint256 _mintingMaximum, uint256 _expirationSeconds, uint256 _challengeSeconds, uint32 _mintingFeePPM, uint256 _liqPriceE18, uint32 _reservePPM)
It also says: "When opening a position, it is already provided with some collateral, but nothing is minted yet. Minting is not possible until the initialization period of seven days has passed." However, MintingHub also has:
function openPosition( address _collateralAddress, uint256 _minCollateral, uint256 _initialCollateral, uint256 _mintingMaximum, uint256 _initPeriodSeconds, uint256 _expirationSeconds, uint256 _challengeSeconds, uint32 _mintingFeePPM, uint256 _liqPrice, uint32 _reservePPM)
which let's the user choose another value other than 7 days (up to 3 days or more).
Furthermore, on Equity.sol, it says that equity could be negative when it is using a uint
:
300: * If there is less than 1000 ZCHF in equity left (maybe even negative),
The following import in PositionFactory.sol
was not found to be necessary:
5: import "./IFrankencoin.sol";
#0 - 0xA5DF
2023-04-27T11:11:18Z
L1 dupe of #941
#1 - c4-judge
2023-05-16T16:03:42Z
hansfriese marked the issue as grade-b