Platform: Code4rena
Start Date: 12/07/2022
Pot Size: $35,000 USDC
Total HM: 13
Participants: 78
Period: 3 days
Judge: 0xean
Total Solo HM: 6
Id: 135
League: ETH
Rank: 19/78
Findings: 3
Award: $164.06
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xDjango
Also found by: 0x1f8b, 8olidity, Bahurum, Lambda, arcoun, caventa, csanuragjain, hansfriese, joestakey, jonatascm, oyc_109, ronnyx2017
48.5491 USDC - $48.55
https://github.com/code-423n4/2022-07-swivel/blob/fd36ce96b46943026cb2dfcb76dfa3f884f51c18/Creator/ZcToken.sol#L132-L134 https://github.com/code-423n4/2022-07-swivel/blob/fd36ce96b46943026cb2dfcb76dfa3f884f51c18/Creator/ZcToken.sol#L111-L115
The logic around the decrementing the allowance
in the withdraw
and redeem
methods of the contract ZcToken
are wrong implemented and cannot be used.
There are a Denial of Service in the withdraw
and redeem
methods of the ZcToken
contract, the allowance is checked in the opposite way, so if the allowed
amount is greater or equal to the amount, it will be reverted, otherwise, an integer overflow will also revert the execution.
uint256 allowed = allowance[holder][msg.sender]; if (allowed >= previewAmount) { revert Approvals(allowed, previewAmount); } allowance[holder][msg.sender] -= previewAmount;
uint256 allowed = allowance[holder][msg.sender]; - if (allowed >= previewAmount) { + if (allowed < previewAmount) { revert Approvals(allowed, previewAmount); } allowance[holder][msg.sender] -= previewAmount;
#0 - 0xlgtm
2022-07-16T05:08:09Z
#1 - JTraversa
2022-07-20T07:24:44Z
Duplicate of #129
#2 - robrobbins
2022-08-01T15:28:58Z
#3 - bghughes
2022-08-03T14:00:18Z
Duplicate of #129
🌟 Selected for report: joestakey
Also found by: 0x1f8b, 0x52, 0xDjango, 0xNazgul, 0xNineDec, 8olidity, Avci, Bahurum, Bnke0x0, Chom, ElKu, Funen, GimelSec, JC, Junnon, Kaiziron, Meera, PaludoX0, Picodes, ReyAdmirado, Sm4rty, Soosh, Waze, _Adam, __141345__, ak1, aysha, benbaessler, bin2chen, c3phas, cccz, cryptphi, csanuragjain, defsec, exd0tpy, fatherOfBlocks, gogo, hake, hansfriese, itsmeSTYJ, jonatascm, kyteg, mektigboy, oyc_109, pashov, rbserver, rishabh, robee, rokinot, sach1r0, sashik_eth, scaraven, simon135, slywaters
87.4302 USDC - $87.43
It's possible to lose the ownership under specific circumstances.
Because an human error it's possible to set a new invalid owner. When you want to change the owner's address it's better to propose a new owner, and then accept this ownership with the new wallet.
Affected source code:
The following lines require a contract as an argument, in some of them, once the value is set, it cannot be changed again, so it is mandatory to check if these values are as expected.
Affected source code:
The pragma version used is:
pragma solidity ^0.8.4; pragma solidity 0.8.13;
But recently solidity released a new version with important Bugfixes:
The first one is related to ABI-encoding nested arrays directly from calldata. You can find more information here.
The second bug is triggered in certain inheritance structures and can cause a memory pointer to be interpreted as a calldata pointer or vice-versa. We also have a dedicated blog post about this bug.
Apart from these, there are several minor bug fixes and improvements.
The minimum required version should be 0.8.14
The transferNotionalFee
method of VaultTracker
does not check that the argument overflows, as other methods in the same contract do. The logic must be unified.
+ if (a > oVault.notional) { revert Exception(31, a, oVault.notional, address(0), address(0)); } // remove notional from its owner oVault.notional -= a;
It's important to emit events when the governance change important values in the contract, in order to be more open and transparent.
For example, when a contract is paused or unpaused like in the following lines:
ecrecover
returns is not address(0)
The method ecrecover
returns address(0)
when the signature is wrong, so if a user use address(0)
as a maker
the return will be true
.
Affected source code:
The code that contains "open todos" reflects that the development is not finished and that the code can change a posteriori, prior release, with or without audit.
Affected source code:
#0 - robrobbins
2022-08-23T23:45:18Z
agree with 4. addressed: https://github.com/Swivel-Finance/gost/pull/432
#1 - robrobbins
2022-08-25T21:42:31Z
address(0) in the sig lib was addressed elsewhere
🌟 Selected for report: joestakey
Also found by: 0x040, 0x1f8b, 0xDjango, 0xNazgul, 0xsam, Avci, Aymen0909, Bnke0x0, CRYP70, ElKu, Fitraldys, Funen, JC, Kaiziron, MadWookie, Meera, ReyAdmirado, Sm4rty, Soosh, TomJ, Waze, _Adam, __141345__, ajtra, benbaessler, c3phas, csanuragjain, durianSausage, exd0tpy, fatherOfBlocks, hake, ignacio, karanctf, kyteg, m_Rassska, oyc_109, rbserver, robee, rokinot, samruna, sashik_eth, simon135, slywaters
28.0772 USDC - $28.08
Move the following line from VaultTracker.sol#L155-L158:
Vault memory from = vaults[f]; - Vault memory to = vaults[t]; if (a > from.notional) { revert Exception(31, a, from.notional, address(0), address(0)); } + Vault memory to = vaults[t];
Having a method that always returns the same value is not correct in terms of consumption, if you want to modify a value, and the method will perform a revert
in case of failure, it is not necessary to return a true
, since it will never be false
. It is less expensive not to return anything, and it also eliminates the need to double-check the returned value by the caller.
Affected source code:
++i
costs less gas compared to i++
or i += 1
++i
costs less gas compared to i++
or i += 1
for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled.
i++
increments i
and returns the initial value of i
. Which means:
uint i = 1; i++; // == 1 but i == 2
But ++i
returns the actual incremented value:
uint i = 1; ++i; // == 2 and i == 2 too, so no need for a temporary variable
In the first case, the compiler has to create a temporary variable (when used) for returning 1
instead of 2
I suggest using ++i
instead of i++
to increment the value of an uint variable. Same thing for --i
and i--
Affected source code:
delete
optimizationUse delete
instead of set to default value (false
or 0
).
5 gas could be saved per entry in the following affected lines:
Use scientific notation (e.g. 10e17) rather than exponentiation (e.g. 10**18)
Change 2**256 - 1
to type(uint256).max
: